예제 #1
0
def bilateral_filter(
    a_img: ImageImpl, kernel_size: int, sigma_s: float, sigma_r: float
) -> ImageImpl:
    """
    Given an Image instance, apply the bilateral filter
    kernel_size.
    :param a_img: Image instance
    :param kernel_size: kernel size int
    :param sigma_s: sigma_s value
    :param sigma_r: sigma_r value
    :return: transformed image
    """

    img_in = a_img.get_array()

    if a_img.channels == 1:
        img_in = img_in[:, :, 0]

    gaussian = (
        lambda r2, sigma: (np.exp(-0.5 * r2 / sigma ** 2) * 3).astype(int) * 1.0 / 3.0
    )

    # define the window width to be the 3 time the spatial std. dev. to
    # be sure that most of the spatial kernel is actually captured
    win_width = int(kernel_size)

    # initialize the results and sum of weights to very small values for
    # numerical stability. not strictly necessary but helpful to avoid
    # wild values with pathological choices of parameters
    reg_constant = 1e-8
    wgt_sum = np.ones(img_in.shape) * reg_constant
    result = img_in * reg_constant

    # accumulate the result by circularly shifting the image across the
    # window in the horizontal and vertical directions. within the inner
    # loop, calculate the two weights and accumulate the weight sum and
    # the unnormalized result image
    for shft_x in range(-win_width, win_width + 1):
        for shft_y in range(-win_width, win_width + 1):
            # compute the spatial weight
            w = gaussian(shft_x ** 2 + shft_y ** 2, sigma_s)

            # shift by the offsets
            off = np.roll(img_in, [shft_y, shft_x], axis=[0, 1])

            # compute the value weight
            tw = w * gaussian((off - img_in) ** 2, sigma_r)

            # accumulate the results
            result += off * tw
            wgt_sum += tw

    # normalize the result and return

    out = result / wgt_sum
    dims = len(out.shape)
    out = np.expand_dims(out, axis=dims) if dims == 2 else out

    return ImageImpl.from_array(out)
예제 #2
0
def salt_and_pepper_apply(image: ImageImpl, p0: float, p1=None) -> ImageImpl:
    if p1 is None:
        p1 = 1 - p0

    mask = np.random.uniform(low=0.0, high=1.0, size=image.array.shape)
    mask_p0 = np.where(mask > p0, 1.0, 0.0)
    mask_p1 = np.where(mask < p1, 1.0, 0.0)
    mask_p1_add = np.where(mask > p1, 1.0, 0.0)

    result = image.array * mask_p0
    result = result * mask_p1 + mask_p1_add * constants.MAX_PIXEL_VALUE

    return ImageImpl.from_array(result)
예제 #3
0
def apply_noise(image: ImageImpl, random_generator: Generator,
                is_additive: bool, threshold: float) -> ImageImpl:

    noise = random_generator.generate()
    noise = np.array(noise).reshape(image.array.shape)

    mask = np.random.uniform(low=0.0, high=1.0, size=image.array.shape)
    mask = np.where(mask > threshold, 1.0, 0.0)

    if is_additive:
        result = image.array + mask * noise
    else:
        result = image.array * mask * noise

    return ImageImpl.from_array(result)
예제 #4
0
def umbralization_with_two_thresholds(a_img: ImageImpl, high_threshold: float,
                                      low_threshold: float) -> ImageImpl:
    image_array = a_img.get_array()
    res = np.zeros_like(image_array)

    weak = np.int32(constants.MAX_PIXEL_VALUE / 2)
    strong = np.int32(constants.MAX_PIXEL_VALUE)

    strong_i, strong_j, strong_k = np.where(image_array >= high_threshold)

    weak_i, weak_j, weak_k = np.where((image_array <= high_threshold)
                                      & (image_array >= low_threshold))

    res[strong_i, strong_j, strong_k] = strong
    res[weak_i, weak_j, weak_k] = weak

    return ImageImpl.from_array(res)
예제 #5
0
def generate_image_with_border(mask_array: np.ndarray,
                               image: ImageImpl) -> ImageImpl:
    border_image = np.zeros((image.height, image.width, 3), dtype=np.uint8)
    image_array = image.get_array()

    for y in range(0, image.height):
        for x in range(0, image.width):
            if mask_array[y, x] == -1 or mask_array[y, x] == 1:
                border_image[y, x, 0] = np.uint8(0)
                border_image[y, x, 1] = np.uint8(255)
                border_image[y, x, 2] = np.uint8(0)
            else:
                border_image[y, x, 0] = image_array[y, x, 0]
                border_image[y, x, 1] = image_array[y, x, 1]
                border_image[y, x, 2] = image_array[y, x, 2]

    return ImageImpl.from_array(border_image)
예제 #6
0
def global_thresholding(image: ImageImpl) -> (ImageImpl, list):
    img_array = image.get_array()
    t = []
    img_binary = []

    for c in range(image.channels):
        current_t = int(np.mean(img_array[:, :, c]))
        last_t = 0

        while abs(last_t - current_t) >= 0.5:
            last_t = current_t
            current_t = _calculate_global_threshold(img_array[:, :, c], last_t)

        img_binary.append(
            _array_binarize(img_array[:, :, c], current_t) *
            constants.MAX_PIXEL_VALUE)
        t.append(int(current_t))

    return ImageImpl.from_array(np.moveaxis(np.array(img_binary), 0, 2)), t
예제 #7
0
def otsu_thresholding(image: ImageImpl):
    hists = image.df()
    img_array = image.get_array()
    t = []
    img_binary = []

    for c in range(image.channels):
        prob = np.array(hists[c]) / len(img_array[:, :, c])
        prob_sumcum = np.array(ImageImpl._cdf_hist(hists[c])) / 255
        means = _compute_means(prob)
        global_means = _compute_global_mean(prob)

        variances = _compute_variance(global_means, means, prob_sumcum)
        threshold = _get_threshold_from_variance(variances)
        img_binary.append(
            _array_binarize(img_array[:, :, c], threshold) *
            constants.MAX_PIXEL_VALUE)
        t.append(threshold)

    return ImageImpl.from_array(np.moveaxis(np.array(img_binary), 0, 2)), t
예제 #8
0
def suppress_false_maximums2(synthesized_image: ImageImpl,
                             angle: np.ndarray) -> ImageImpl:
    synthesized_array = synthesized_image.array[..., 0]
    result = np.zeros_like(synthesized_array)

    for i in range(1, result.shape[0] - 1):
        for j in range(1, result.shape[1] - 1):

            # angle 0
            if (0 <= angle[i, j] < 22.5) or (157.5 <= angle[i, j] <= 180):
                after_pixel = synthesized_array[i, j + 1]
                before_pixel = synthesized_array[i, j - 1]

            # angle 45
            elif 22.5 <= angle[i, j] < 67.5:
                after_pixel = synthesized_array[i + 1, j - 1]
                before_pixel = synthesized_array[i - 1, j + 1]

            # angle 90
            elif 67.5 <= angle[i, j] < 112.5:
                after_pixel = synthesized_array[i + 1, j]
                before_pixel = synthesized_array[i - 1, j]

            # angle 135
            elif 112.5 <= angle[i, j] < 157.5:
                after_pixel = synthesized_array[i - 1, j - 1]
                before_pixel = synthesized_array[i + 1, j + 1]

            else:
                ValueError("Angle not valid")

            if (synthesized_array[i, j] >= after_pixel
                    and synthesized_array[i, j] >= before_pixel):
                result[i, j] = synthesized_array[i, j]
            else:
                result[i, j] = 0
    return ImageImpl.from_array(result[:, :, np.newaxis])