def linear_adjustment(a_img: ImageImpl) -> ImageImpl:
    """
    Given a matrix image representation apply, if necessary, linear transformation
    to bring values in the pixel value range (0, 255).
    :param a_img: numpy array of 2 or 3 dimensions.
    :return: np.ndarray of same shape with values in range
    """

    min_value = a_img.min_value()
    max_value = a_img.max_value()

    if MAX_PIXEL_VALUE >= max_value and MIN_PIXEL_VALUE <= min_value:
        # values are in range
        return a_img  # pixels should be ints no floats
    # if values are out of range, adjust based on current values

    if max_value == min_value:
        # a transformation should only shift values in this case
        slope = 0
    else:
        slope = (MAX_PIXEL_VALUE - MIN_PIXEL_VALUE) / (max_value - min_value)
    if max_value == min_value:
        if max_value > MAX_PIXEL_VALUE:
            constant = MAX_PIXEL_VALUE
        elif min_value < MIN_PIXEL_VALUE:
            constant = MIN_PIXEL_VALUE
        else:
            constant = max_value
    else:
        # as we want the tranformation to map MIN_PIXEL_VALUE to the min_value found
        # we just solve y = mx + b for known x, y and m
        constant = MIN_PIXEL_VALUE - slope * min_value

    return a_img.mul_scalar(slope).add_scalar(constant)
Beispiel #2
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)
Beispiel #3
0
def hough_circle_detector(
    image: ImageImpl,
    threshold: int = 0.4,
    min_radius: int = 10,
    max_radius: int = 40,
    steps: int = 100,
    high_threshold: float = 75,
    low_threshold: float = 35,
) -> ImageImpl:

    img = Image.fromarray(image.to_rgb().get_array())
    img = img.resize((300, 200), Image.ANTIALIAS)
    image = ImageImpl(np.array(img))

    border_image = border_detection.canny_detection(image, 3, 10,
                                                    high_threshold,
                                                    low_threshold, 10)

    edge_pixels = np.where(
        border_image.get_array()[..., 0] == constants.MAX_PIXEL_VALUE)

    rmin = min_radius
    rmax = max_radius
    points = []
    for r in range(rmin, rmax + 1):
        for t in range(steps):
            points.append((r, int(r * cos(2 * pi * t / steps)),
                           int(r * sin(2 * pi * t / steps))))

    coordinates = list(zip(edge_pixels[0], edge_pixels[1]))
    acc = defaultdict(int)

    for y, x in coordinates:
        for r, dx, dy in points:
            a = x - dx
            b = y - dy
            acc[(a, b, r)] += 1

    circles = []
    iterator = sorted(acc.items(), key=lambda i: -i[1])
    for k, v in iterator:
        x, y, r = k
        if v / steps >= threshold and all(
            (x - xc)**2 + (y - yc)**2 > rc**2 for xc, yc, rc in circles):
            print(v / steps, x, y, r)
            circles.append((x, y, r))

    result = image.to_rgb()

    img = Image.fromarray(result.get_array())
    draw_result = ImageDraw.Draw(img)
    for x, y, r in circles:
        draw_result.ellipse((x - r, y - r, x + r, y + r),
                            outline=(255, 0, 0, 0))

    result = ImageImpl(np.array(img))
    return result
Beispiel #4
0
def draw_circle(image: ImageImpl, a: float, b: float, radius: float,
                epsilon: float) -> ImageImpl:
    x_start = int(a - radius)
    x_end = int(a + radius)
    y_start = int(b - radius)
    y_end = int(b + radius)

    for y in range(y_start, y_end):
        for x in range(x_start, x_end):
            if 0 <= x < image.width and 0 <= y < image.height:
                x_difference = pow(x - a, 2)
                y_difference = pow(y - b, 2)
                squared_radius = pow(radius, 2)
                value = abs(x_difference + y_difference - squared_radius)
                if value <= epsilon:
                    image.array[y, x, 0] = 0
                    image.array[y, x, 1] = constants.MAX_PIXEL_VALUE
                    image.array[y, x, 2] = 0
                    for i in range(1, 4):
                        if (0 <= x - 1 and x + 1 < image.width and 0 <= y - 1
                                and y + 1 < image.height):
                            image.array[y + i, x,
                                        1] = constants.MAX_PIXEL_VALUE
                            image.array[y - i, x,
                                        1] = constants.MAX_PIXEL_VALUE
                            image.array[y, x + i,
                                        1] = constants.MAX_PIXEL_VALUE
                            image.array[y, x - i,
                                        1] = constants.MAX_PIXEL_VALUE
                            image.array[y, x, 1] = constants.MAX_PIXEL_VALUE
    return image
Beispiel #5
0
def weighted_median_filter(a_img: ImageImpl, kernel_size: int) -> ImageImpl:
    """
    Given an Image instance, apply the weighted median filter using a square kernel of size
    kernel_size.
    :param a_img: Image instance
    :param kernel_size: kernel size int
    :return: transformed image
    """
    a_img.convolution(
        kernel_size,
        lambda window: _weighted_median(window, kernel_size),
    )

    return a_img
Beispiel #6
0
def mean_filter_fast(a_img: ImageImpl, kernel_size: int) -> ImageImpl:
    """
    Given an Image instance, apply the mean filter using a square kernel of size
    kernel_size.
    :param a_img: Image instance
    :param kernel_size: kernel size int
    :return: transformed image
    """
    kernel_size = int(kernel_size)
    a_img.convolution_fast(
        np.ones((kernel_size, kernel_size)),
    )

    return a_img
Beispiel #7
0
def high_filter(a_img: ImageImpl, kernel_size: int) -> ImageImpl:
    """
    Given a Image instance, apply high value filter.
    :param a_img:
    :param kernel_size:
    :return: transformed Image instance
    """

    a_img.convolution(
        kernel_size,
        lambda window: apply_high_filter(window, int(kernel_size)),
    )

    return a_img
Beispiel #8
0
def gaussian_filter(a_img: ImageImpl, kernel_size: int, sigma: float) -> ImageImpl:
    """
    Given an Image instance, apply the weighted gaussian filter using a square kernel of size
    kernel_size.
    :param a_img: Image instance
    :param kernel_size: kernel size int
    :param sigma: sigma value
    :return: transformed image
    """
    a_img.convolution(
        kernel_size,
        lambda window: _apply_gaussian_filter(window, int(kernel_size), sigma),
    )

    return a_img
Beispiel #9
0
def load_image(filename: str) -> ImageImpl:
    image = ImageIO.load_image(filename)
    image_matrix = np.array(image)
    dims = len(image_matrix.shape)
    image_matrix = (np.expand_dims(image_matrix, axis=dims)
                    if dims == 2 else image_matrix)
    return ImageImpl(image_matrix)
Beispiel #10
0
def has_border_neighbours_without_thresholds(image: ImageImpl, i: int, j: int,
                                             four_neighbours: bool):
    height, width = image.height, image.width
    image_array = image.get_array()[..., 0]

    if four_neighbours:
        increments = [[0, -1], [1, 0], [0, 1], [-1, 0]]
    else:
        increments = [
            [-1, -1],
            [0, -1],
            [1, -1],
            [1, 0],
            [1, 1],
            [0, 1],
            [-1, 1],
            [-1, 0],
        ]
    for k in range(0, len(increments)):
        new_i = i + increments[k][0]
        new_j = j + increments[k][1]
        if (0 <= new_i < width and 0 <= new_j < height
                and image_array[new_i, new_j] == constants.MAX_PIXEL_VALUE):
            return True
    return False
Beispiel #11
0
def sobel_detector(a_img: ImageImpl,
                   return_all: bool = False) -> List[ImageImpl]:
    """
    Given an image object, return the gradient filter (border detection) as
    denoted by the sobel operator.
    :param return_all:
    :param a_img: image matrix representation
    :return: image gradient filter matrix representation
    """

    horizontal_kernel = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]])
    # calcualte vertical gradient
    vertical_kernel = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])

    horizontal_grad = copy(a_img)
    horizontal_grad.convolution_fast(horizontal_kernel)

    vertical_grad = copy(a_img)
    vertical_grad.convolution_fast(vertical_kernel)

    # finally the module of the value is calculated as the sqrt([dFx ** 2 + dFy ** 2])
    grad_img = ImageImpl(
        np.sqrt(horizontal_grad.array**2 + vertical_grad.array**2))

    result = [grad_img]
    if return_all:
        result.append(horizontal_grad)
        result.append(vertical_grad)

    return result
Beispiel #12
0
def anisodiff(a_img: ImageImpl, steps, b) -> ImageImpl:
    """
    Given an image implementation, calculates the ansiotropic filter as described in the paper by Perona- Malik et al.

    :param a_img: image matrix representation
    :param steps: the number of iterations to apply the mask
    :param b: the leclerc coefficient hyper parameter
    :return: ImageImpl
    """

    lam = 0.25
    # convert to int
    steps = int(steps)
    im = a_img.array

    im_new = np.zeros(im.shape, dtype=im.dtype)
    for t in range(steps):
        # calculate the gradient with respect to each cardinal direction
        # the sneaky way is to get get the far right sub matrix (without the last
        # row and subtract the far left one, and the do the same for all other directions.
        dn = im[:-2, 1:-1] - im[1:-1, 1:-1]
        ds = im[2:, 1:-1] - im[1:-1, 1:-1]
        de = im[1:-1, 2:] - im[1:-1, 1:-1]
        dw = im[1:-1, :-2] - im[1:-1, 1:-1]
        im_new[1:-1, 1:-1] = im[1:-1, 1:-1] + lam * (
            leclerc_coef(dn, b) * dn
            + leclerc_coef(ds, b) * ds
            + leclerc_coef(de, b) * de
            + leclerc_coef(dw, b) * dw
        )
        im = im_new
    return ImageImpl(im)
Beispiel #13
0
def high_filter_fast(a_img: ImageImpl, kernel_size: int) -> ImageImpl:
    """
    Given a Image instance, apply high value filter.
    :param a_img:
    :param kernel_size:
    :return: transformed Image instance
    """
    kernel_size = int(kernel_size)
    kernel = np.ones((kernel_size, kernel_size)) * -1
    # augment the center value
    kernel[int(kernel_size / 2), int(kernel_size / 2)] = kernel_size

    a_img.convolution_fast(
        kernel,
    )
    return a_img
Beispiel #14
0
def gaussian_filter_fast(a_img: ImageImpl, kernel_size: int, sigma: float) -> ImageImpl:
    """
    Given an Image instance, apply the weighted gaussian filter using a square kernel of size
    kernel_size.
    :param a_img: Image instance
    :param kernel_size: kernel size int
    :param sigma: sigma value
    :return: transformed image
    """
    kernel_size = int(kernel_size)
    kernel = gaussian_kernel(kernel_size, sigma) * MAX_PIXEL_VALUE
    a_img.convolution_fast(
        (1 / kernel_size ** 2) * kernel,
    )

    return a_img
Beispiel #15
0
def threshold_filter(a_img: ImageImpl, threshold: float) -> ImageImpl:
    """
    Given a matrix image representation, apply treshold transformation
    and return a binary matrix which follows this transformation:
    F(img[i,j]):| max_pixel_value if img[i, j] >= threshold
                | 0 else
    :param a_img: matrix image representation
    :param threshold: float between [0, max pixel value]
    :return: transformed matrix
    """

    # applies if element wise
    a_img.array = a_img.array >= threshold
    # transform a boolean matrix binary and scales
    a_img.array = a_img.array.astype(int) * MAX_PIXEL_VALUE

    return a_img
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)
Beispiel #17
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)
Beispiel #18
0
def median_filter(a_img: ImageImpl, kernel_size: int) -> ImageImpl:
    """
    Given an Image instance, apply the median filter using a square kernel of size
    kernel_size.
    :param a_img: Image instance
    :param kernel_size: kernel size int
    :return: transformed image
    """
    a_img.convolution(
        kernel_size,
        lambda window: np.median(
            window.reshape(
                -1,
            )
        ),
    )

    return a_img
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
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
Beispiel #21
0
def negative_img_fun(a_img: ImageImpl) -> ImageImpl:
    """
    Given an image matrix representation, invert pixel values.
    Following the function:
    F: PixelDomain -> PixelDomain/
    F(r) = -r + Max_Pixel_value
    :param a_img: matrix image representation
    :return: transformed matrix
    """

    return a_img.mul_scalar(-1).add_scalar(MAX_PIXEL_VALUE)
Beispiel #22
0
def hysteresis(
    image: ImageImpl,
    four_neighbours: bool = True,
    weak: int = int(constants.MAX_PIXEL_VALUE / 2),
    strong: int = constants.MAX_PIXEL_VALUE,
) -> ImageImpl:
    height, width = image.height, image.width
    image_array = image.get_array()[..., 0]

    border_image = np.array(image_array)

    for i in range(1, width - 1):
        for j in range(1, height - 1):
            if border_image[i, j] == weak:
                if has_border_neighbours_without_thresholds(
                        image, i, j, four_neighbours):
                    border_image[i, j] = strong
                else:
                    border_image[i, j] = 0

    return ImageImpl(border_image[:, :, np.newaxis])
Beispiel #23
0
def canny_detection(
    a_img: ImageImpl,
    kernel_size: int,
    sigma_s: float,
    sigma_r: float,
    high_threshold: float,
    low_threshold: float,
    four_neighbours: bool = True,
) -> ImageImpl:
    """
    apply caddy mask and border detection
    :param four_neighbours:
    :param a_img:
    :param kernel_size:
    :param sigma_s:
    :param sigma_r:
    :return:
    """

    gray_image = a_img.to_gray()

    filtered_image = bilateral_filter(gray_image, kernel_size, sigma_s,
                                      sigma_r)

    border_images = sobel_detector(filtered_image, True)

    synthesized_image = linear_adjustment(border_images[0])
    horizontal_image = border_images[1]
    vertical_image = border_images[2]

    # this calcualtes the direction in radians
    angle_matrix = np.arctan2(horizontal_image.array[..., 0],
                              vertical_image.array[..., 0])
    # now we convert to degrees
    angle_matrix = np.rad2deg(angle_matrix)
    angle_matrix[angle_matrix < 0] += 180

    suppressed_image = suppress_false_maximums2(synthesized_image,
                                                angle_matrix)

    # high_threshold = np.amax(suppressed_image.array) * 0.15
    # low_threshold = np.amax(suppressed_image.array) * 0.05

    umbralized_image = umbralization_with_two_thresholds(
        suppressed_image, high_threshold, low_threshold)

    border_image = hysteresis(umbralized_image, bool(four_neighbours))

    # import cv2
    # edges = cv2.Canny(filtered_image.get_array()[..., 0], 100, 200)
    # border_image = ImageImpl.from_array(edges[:, :, np.newaxis])

    return linear_adjustment(border_image)
Beispiel #24
0
def draw_lines(image: ImageImpl, rho: float, theta: float) -> ImageImpl:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a * rho
    y0 = b * rho
    x1 = int(x0 + 1000 * (-b))
    y1 = int(y0 + 1000 * (a))
    x2 = int(x0 - 1000 * (-b))
    y2 = int(y0 - 1000 * (a))
    if x1 == x2:
        for y in range(0, image.width):
            image.array[y, int(x0), 0] = constants.MAX_PIXEL_VALUE
            image.array[y, int(x0), 1] = 0
            image.array[y, int(x0), 2] = 0

    else:
        slope = (y2 - y1) / (x2 - x1)
        origin_ordenate = y0 - slope * x0
        for x in range(0, image.width):
            y = int(slope * x + origin_ordenate)
            # y = int(- ((np.cos(theta) / np.sin(theta)) * x) + rho / np.sin(theta))
            if 0 <= y < image.height:
                image.array[y, x, 0] = constants.MAX_PIXEL_VALUE
                image.array[y, x, 1] = 0
                image.array[y, x, 2] = 0
    return image
Beispiel #25
0
def susan_detection(a_img: ImageImpl, threshold: int, low_filter: float,
                    high_filter: float, color: int) -> ImageImpl:
    """
    :param a_img:
    :param kernel_size:
    :param threshold:
    :return:
    """
    # circ_kernel = circular_kernel(7)
    circ_kernel = np.array([
        [0, 0, 1, 1, 1, 0, 0],
        [0, 1, 1, 1, 1, 1, 0],
        [1, 1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 1, 1],
        [0, 1, 1, 1, 1, 1, 0],
        [0, 0, 1, 1, 1, 0, 0],
    ])

    original = ImageImpl(a_img.get_array())
    a_img.apply_filter(
        circ_kernel,
        lambda m: _calculate_c_for_susan(m, circ_kernel, threshold))
    # a_img.array = np.uint8(a_img.array > 0.75)

    border_img = np.uint8(a_img.array > low_filter)
    b_img = border_img - np.uint8(a_img.array > high_filter)
    border_img = np.zeros((border_img.shape[0], border_img.shape[1], 3))
    # because we only have 3 channels
    color = color % 3
    border_img[:, :, color] = b_img[:, :, 0]

    border_img = ImageImpl(border_img)

    result = border_img.mul_scalar(255)

    original = original.to_rgb()

    # result.add_image(original)
    return original.add(result)
Beispiel #26
0
def get_object_color(
    mask_array: np.ndarray,
    image: ImageImpl,
    top_left_vertex_x: int,
    top_left_vertex_y: int,
    bottom_right_vertex_x: int,
    bottom_right_vertex_y: int,
    lin: dict,
    lout: dict,
) -> np.ndarray:
    color_sum = np.zeros(image.channels)
    image_array = image.get_array()

    square_height = (bottom_right_vertex_y - top_left_vertex_y) + 1
    square_width = (bottom_right_vertex_x - top_left_vertex_x) + 1
    square_size = square_height * square_width
    for y in range(top_left_vertex_y, bottom_right_vertex_y + 1):
        for x in range(top_left_vertex_x, bottom_right_vertex_x + 1):
            mask_array[y, x] = -3
            for k in range(0, image.channels):
                color_sum[k] += image_array[y, x, k]

    for y in range(top_left_vertex_y, bottom_right_vertex_y + 1):
        mask_array[y, top_left_vertex_x - 1] = -1
        lin[(top_left_vertex_x - 1, y)] = -1
        mask_array[y, bottom_right_vertex_x + 1] = -1
        lin[(bottom_right_vertex_x + 1, y)] = -1
        mask_array[y, top_left_vertex_x - 2] = 1
        lout[(top_left_vertex_x - 2, y)] = 1
        mask_array[y, bottom_right_vertex_x + 2] = 1
        lout[(bottom_right_vertex_x + 2, y)] = 1

    for x in range(top_left_vertex_x, bottom_right_vertex_x + 1):
        mask_array[top_left_vertex_y - 1, x] = -1
        lin[(x, top_left_vertex_y - 1)] = -1
        mask_array[bottom_right_vertex_y + 1, x] = -1
        lin[(x, bottom_right_vertex_y + 1)] = -1
        mask_array[top_left_vertex_y - 2, x] = 1
        lout[(x, top_left_vertex_y - 2)] = 1
        mask_array[bottom_right_vertex_y + 2, x] = 1
        lout[(x, bottom_right_vertex_y + 2)] = 1

    mask_array[top_left_vertex_y - 1, top_left_vertex_x - 1] = 1
    lout[(top_left_vertex_x - 1, top_left_vertex_y - 1)] = 1
    mask_array[bottom_right_vertex_y + 1, top_left_vertex_x - 1] = 1
    lout[(top_left_vertex_x - 1, bottom_right_vertex_y + 1)] = 1
    mask_array[bottom_right_vertex_y + 1, bottom_right_vertex_x + 1] = 1
    lout[(bottom_right_vertex_x + 1, bottom_right_vertex_y + 1)] = 1
    mask_array[top_left_vertex_y - 1, bottom_right_vertex_x + 1] = 1
    lout[(bottom_right_vertex_x + 1, top_left_vertex_y - 1)] = 1

    return color_sum / square_size
Beispiel #27
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)
Beispiel #28
0
def gamma_fun(a_img: ImageImpl, gamma: float) -> ImageImpl:
    """
    Given a matrix image representation, apply gamma filter
    :param a_img: image matrix representation
    :param gamma: gamma value, should be positive value
    :return: image matrix after filter transformation
    """
    # remember T(img) = C^(1 - gamma) * img ^ (gamma)
    # calculate C value
    c = MAX_PIXEL_VALUE
    # element wise power function
    img = a_img.apply(lambda x: np.power(x, gamma))
    return img.apply(lambda x: x.dot(c ** (1 - gamma)))
Beispiel #29
0
def median_filter_fast(a_img: ImageImpl, kernel_size: int) -> ImageImpl:
    """
    Given an Image instance, apply the median filter using a square kernel of size
    kernel_size.
    :param a_img: Image instance
    :param kernel_size: kernel size int
    :return: transformed image
    """
    # build kernel
    kernel_size = int(kernel_size)

    filtered = ndimage.median_filter(a_img.array, size=kernel_size)
    a_img.array = filtered
    return a_img
Beispiel #30
0
def histogram_equalization(a_img: ImageImpl) -> ImageImpl:
    """
    Given a matrix representation of an image, apply histogram equalization as given by:

    T(Rk) = sum from 0 to k of Nj/N
    where:
        - Rk: k-th grey value in the scale from o - max pixel value
        - Nj: number of pixel with j-th grey value in the matrix
        - N: total number of pixels.
    :param a_img: image matrix representation
    :return: transformed matrix
    """

    return a_img.equalize_image()