Exemplo n.º 1
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
Exemplo n.º 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)
Exemplo n.º 3
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
Exemplo n.º 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)
Exemplo n.º 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)
Exemplo n.º 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
Exemplo n.º 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
Exemplo n.º 8
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])
Exemplo n.º 9
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)