def expand_with_white(image: Image, where, size: int) -> Image:
    verification.verify_is_image_or_exception(image)

    fill = white_color_by_mode(image.mode)

    if where == 'to_left':
        result = Image.new(image.mode, (image.width + size, image.height))
        draw = ImageDraw.Draw(im=result, mode=result.mode)
        draw.rectangle(xy=[(0, 0), (size + 1, result.height + 1)], fill=fill)
        result.paste(im=image, box=(size + 1, 0))
    elif where == 'to_right':
        result = Image.new(image.mode, (image.width + size, image.height))
        draw = ImageDraw.Draw(im=result, mode=result.mode)
        draw.rectangle(xy=[(result.width - 1 - size, 0), (result.width + 1, result.height + 1)], fill=fill)
        result.paste(im=image, box=(0, 0))
    elif where == 'to_top':
        result = Image.new(image.mode, (image.width, image.height + size))
        draw = ImageDraw.Draw(im=result, mode=result.mode)
        draw.rectangle(xy=[(0, 0), (result.width + 1, size + 1)], fill=fill)
        result.paste(im=image, box=(0, size + 1))
    elif where == 'to_bottom':
        result = Image.new(image.mode, (image.width, image.height + size))
        draw = ImageDraw.Draw(im=result, mode=result.mode)
        draw.rectangle(xy=[(0, result.height - 1 - size), (result.width + 1, result.height + 1)], fill=fill)
        result.paste(im=image, box=(0, 0))
    else:
        raise ValueError(f'Where argument {where} is unsupported')

    return result
def symbol_segments(image: Image, diff_threshold: float):
    verify_is_image_or_exception(image)

    v_levels, v_projections = inverted_vertical_projection(image)
    max_v_projection = max(v_projections)
    min_v_projection = min(v_projections)

    diff = (max_v_projection - min_v_projection) * diff_threshold

    start = 0

    prev_v_projection = 0
    result = []

    for i in range(len(v_projections) - 1):
        if prev_v_projection - diff <= 0 < v_projections[i] - diff:
            start = i
        elif prev_v_projection - diff > 0 >= v_projections[i] - diff:
            result.append((start, i))
            start = -1

        prev_v_projection = v_projections[i]

    if start != -1:
        result.append((start, len(v_projections) - 1))

    return result
def roberts_cross(image):
    verify_is_image_or_exception(image)

    result = Image.new(image.mode, (image.width, image.height))
    gradient_max = 0
    gradient_matrix = list()

    for x in range(result.width - 1):
        gradient_matrix.append(list())
        for y in range(result.height - 1):
            gradient_x = roberts_cross_gradient_x(image, x, y)
            gradient_y = roberts_cross_gradient_y(image, x, y)
            gradient = roberts_cross_gradient(gradient_x, gradient_y)

            if gradient > gradient_max:
                gradient_max = gradient

            gradient_matrix[x].append(gradient)

    for x in range(result.width - 1):
        for y in range(result.height - 1):
            result.putpixel(
                (x, y), int(round(gradient_matrix[x][y] * 255 / gradient_max)))

    return result
Exemple #4
0
def balansed_histogram_method(image):
    verify_is_image_or_exception(image)

    histogram = image.histogram()
    result = Image.new(THRESHOLDING_MODE, image.size)

    extreme_left = 0
    extreme_right = len(histogram) - 1
    histogram_center = histogram_weight_center(histogram, extreme_left,
                                               extreme_right)

    while extreme_left < extreme_right:
        left_part_weight = sum(histogram[extreme_left:histogram_center])
        right_part_weight = sum(histogram[histogram_center:extreme_right])

        if left_part_weight > right_part_weight:
            extreme_left += 1
        else:
            extreme_right -= 1

        histogram_center = histogram_weight_center(histogram, extreme_left,
                                                   extreme_right)

    threshold = histogram_center

    for x in range(result.width):
        for y in range(result.height):
            result.putpixel((x, y), image.getpixel((x, y)) >= threshold)

    return result
Exemple #5
0
def draw_projections(image: Image) -> Image:
    verification.verify_is_image_or_exception(image)

    x_expand_size = 30
    y_expand_size = 30

    result = expand_with_white(image=expand_with_white(image=image,
                                                       where='to_left',
                                                       size=x_expand_size),
                               where='to_bottom',
                               size=y_expand_size).convert('RGB')
    result_draw = ImageDraw.Draw(im=result)

    h_color = (44, 176, 62)
    h_levels, h_projections = horizontal_projection(image)
    max_h_projection = max(h_projections)

    for y in range(image.height):
        x_projection_coord = int(
            round(lerp(0, 0, max_h_projection, 30, h_projections[y]))) + 1
        result_draw.rectangle(xy=[(0, y), (x_projection_coord, y + 1)],
                              fill=h_color)

    v_color = (166, 29, 5)
    v_levels, v_projections = inverted_vertical_projection(image)
    max_v_projection = max(v_projections)

    for x in range(image.width):
        y_projection_coord = result.height - int(
            round(lerp(0, 0, max_v_projection, 30, v_projections[x])))
        result_draw.rectangle(xy=[(x + x_expand_size, y_projection_coord),
                                  (x + x_expand_size + 1, result.height + 1)],
                              fill=v_color)

    return result
def black_weight(image):
    verify_is_image_or_exception(image)

    result = 0

    for x in range(image.width):
        for y in range(image.height):
            result += image.getpixel((x, y))

    return result
def central_vertical_axial_moment(image):
    verify_is_image_or_exception(image)

    center = gravity_center(image)
    result = 0

    for x in range(image.width):
        for y in range(image.height):
            result += (x - center[0])**2 * image.getpixel((x, y))

    return result
Exemple #8
0
def mean_grayscale(image):
    verify_is_image_or_exception(image)

    result = Image.new(GRAYSCALE_MODE, (image.width, image.height))

    for x in range(result.width):
        for y in range(result.height):
            result.putpixel((x, y),
                            pixel_mean_value_grayscale(image.getpixel((x, y))))

    return result
def gravity_center(image):
    verify_is_image_or_exception(image)

    x_coord = 0
    y_coord = 0

    for x in range(image.width):
        for y in range(image.height):
            pixel = image.getpixel((x, y))
            x_coord += x * pixel
            y_coord += y * pixel

    weight = black_weight(image)
    return int(round(x_coord / weight)), int(round(y_coord / weight))
Exemple #10
0
def simple_threshold(image, threshold):
    verify_is_image_or_exception(image)
    verify_is_natural_or_exception(threshold)

    if threshold > 255:
        raise ValueError(f'Parameter threshold {threshold} > 255')

    result = Image.new(THRESHOLDING_MODE, image.size)

    for x in range(image.width):
        for y in range(image.height):
            result.putpixel((x, y), image.getpixel((x, y)) > threshold)

    return result
def spatial_smoothing_difference(image):
    verify_is_image_or_exception(image)

    spatial_smoothed = spatial_smoothing(image)
    result = Image.new(image.mode, (image.width, image.height))

    for x in range(result.width):
        for y in range(result.height):
            result.putpixel((x, y),
                            abs(
                                image.getpixel((x, y)) -
                                spatial_smoothed.getpixel((x, y))))

    return result
def horizontal_projection(image):
    verify_is_image_or_exception(image)

    levels = []
    projections = []

    for y in range(image.height):
        y_projection = 0
        for x in range(image.width):
            y_projection += image.getpixel((x, y))

        levels.append(y)
        projections.append(y_projection)

    return levels, projections
def spatial_smoothing(image):
    verify_is_image_or_exception(image)

    result = Image.new(image.mode, (image.width, image.height))

    for x in range(1, result.width - 1):
        for y in range(1, result.height - 1):
            window = list()
            for i in range(3):
                for j in range(3):
                    window.append(image.getpixel((x + i - 1, y + j - 1)))

            result.putpixel((x, y), int(round(mean(window))))

    return result
def inverted_vertical_projection(image):
    verify_is_image_or_exception(image)

    levels = []
    projections = []

    for x in range(image.width):
        x_projection = 0
        for y in range(image.height):
            x_projection += white_color_by_mode(image.mode) - image.getpixel(
                (x, y))

        levels.append(x)
        projections.append(x_projection)

    return levels, projections
def one_pass_resampling(image, upsample_factor, downsample_factor):
    verification.verify_is_image_or_exception(image)

    verification.verify_is_natural_or_exception(upsample_factor)
    verification.verify_is_natural_or_exception(downsample_factor)

    if upsample_factor == downsample_factor:
        return image.copy()

    result_width = image.width * upsample_factor // downsample_factor
    result_height = image.height * upsample_factor // downsample_factor
    result = Image.new(image.mode, (result_width, result_height))

    for x in range(result_width):
        for y in range(result_height):
            result.putpixel((x, y), image.getpixel((x * downsample_factor // upsample_factor, y * downsample_factor / upsample_factor)))

    return result
def closest_neighbor_upsampling(image, factor):
    verification.verify_is_image_or_exception(image)

    if factor == 1:
        return image.copy()

    verification.verify_is_natural_or_exception(factor)

    result_width = image.width * factor
    result_height = image.height * factor
    result = Image.new(image.mode, (result_width, result_height))

    for x in range(result_width):
        x_nearest = int(x * image.width / result_width)
        for y in range(result_height):
            y_nearest = int(y * image.height / result_height)
            result.putpixel((x, y), image.getpixel((x_nearest, y_nearest)))

    return result
Exemple #17
0
def draw_symbol_segments(image: Image, diff_threshold: float) -> Image:
    verification.verify_is_image_or_exception(image)

    start_color = (66, 218, 245)
    stop_color = (204, 87, 247)

    segments = symbol_segments(image, diff_threshold)
    result = image.copy().convert('RGB')
    result_draw = ImageDraw.Draw(im=result)

    for segment in segments:
        result_draw.rectangle(xy=[(segment[0], 0),
                                  (segment[0], result.height)],
                              fill=start_color)
        result_draw.rectangle(xy=[(segment[1], 0),
                                  (segment[1], result.height)],
                              fill=stop_color)

    return result
def cut_empty_rows_and_cols(image):
    verification.verify_is_image_or_exception(image)

    empty_row_numbers = []
    empty_column_numbers = []

    for x in range(image.width):
        is_col_empty = True
        for y in range(image.height):
            if image.getpixel((x, y)) < 255:
                is_col_empty = False
                break

        if is_col_empty:
            empty_column_numbers.append(x)

    for y in range(image.height):
        is_row_empty = True
        for x in range(image.width):
            if image.getpixel((x, y)) < 255:
                is_row_empty = False
                break

        if is_row_empty:
            empty_row_numbers.append(y)

    def last_element_in_a_row(elements, start_element, step):
        prev_element = start_element

        for element in elements[::step]:
            if abs(element - prev_element) > 1:
                return prev_element + step

            prev_element = element

        return prev_element + step

    left_whitespace_end = last_element_in_a_row(empty_column_numbers, -1, 1)
    upper_whitespace_end = last_element_in_a_row(empty_row_numbers, -1, 1)
    right_whitespace_end = last_element_in_a_row(empty_column_numbers, image.width, -1)
    lower_whitespace_end = last_element_in_a_row(empty_row_numbers, image.height, -1)

    return image.crop(box=(left_whitespace_end, upper_whitespace_end, right_whitespace_end + 1, lower_whitespace_end + 1))
Exemple #19
0
def power_transformation(image: Image, c: float = 1, f_zero: float = 0, gamma: float = 0.5) -> Image:
    def calculate_brightness(pixel_brightness: int) -> int:
        normalized_pixel_brightness = math.lerp(x1=0, f1=0, x2=255, f2=1, x=pixel_brightness)
        result_brightness = c * pow(normalized_pixel_brightness + f_zero, gamma)
        return int(round(math.lerp(x1=0, f1=0, x2=1, f2=255, x=result_brightness)))

    verification.verify_is_image_or_exception(image)

    assert c >= 0
    assert f_zero >= 0
    assert gamma >= 0

    result = image.copy()

    for x in range(result.width):
        for y in range(result.height):
            brightness = calculate_brightness(result.getpixel((x, y)))
            result.putpixel((x, y), brightness)

    return result
Exemple #20
0
def linear_contrasting(image: Image, min_brightness: int = 0, max_brightness: int = 255) -> Image:
    def calculate_brightness(f, f_min, f_max, g_min, g_max):
        return round(int((f - f_min) / (f_max - f_min) * (g_max - g_min) + g_min))

    verification.verify_is_image_or_exception(image)

    image_pixels = list(image.getdata())

    image_min_brightness = min(image_pixels)
    image_max_brightness = max(image_pixels)

    result = image.copy()

    for x in range(result.width):
        for y in range(result.height):
            brightness = calculate_brightness(result.getpixel((x, y)), image_min_brightness, image_max_brightness,
                                              min_brightness, max_brightness)
            result.putpixel((x, y), brightness)

    return result
def proximity_measure(image_a: Image, image_b: Image) -> float:
    verify_is_image_or_exception(image_a)
    verify_is_image_or_exception(image_b)

    signs = [(normalized_black_weight(image_a),
              normalized_black_weight(image_b))]

    normalized_center_a = normalized_gravity_center(image_a)
    normalized_center_b = normalized_gravity_center(image_b)

    signs.append((normalized_center_a[0], normalized_center_b[0]))
    signs.append((normalized_center_a[1], normalized_center_b[1]))

    signs.append((normalized_central_horizontal_axial_moment(image_a),
                  normalized_central_horizontal_axial_moment(image_b)))

    signs.append((normalized_central_vertical_axial_moment(image_a),
                  normalized_central_vertical_axial_moment(image_b)))

    return euclidean_metric(signs)
def bilinear_interpolation_upsampling(image, factor):
    verification.verify_is_image_or_exception(image)

    if factor == 1:
        return image.copy()

    verification.verify_is_natural_or_exception(factor)

    result_width = image.width * factor
    result_height = image.height * factor
    result = Image.new(image.mode, (result_width, result_height))

    for x in range(result_width):
        for y in range(result_height):
            if (x % factor == 0) and (y % factor == 0):
                result.putpixel((x, y), image.getpixel((x // factor, y // factor)))
                continue

            prev_row_number = y // factor
            next_row_number = prev_row_number + 1
            prev_col_number = x // factor
            next_col_number = prev_col_number + 1

            if (next_row_number >= image.height) or (next_col_number >= image.width):
                result.putpixel((x, y), (0, 0, 0))
                continue

            prev_row_prev_col_pixel = image.getpixel((prev_col_number, prev_row_number))
            prev_row_next_col_pixel = image.getpixel((next_col_number, prev_row_number))
            next_row_prev_col_pixel = image.getpixel((prev_col_number, next_row_number))
            next_row_next_col_pixel = image.getpixel((next_col_number, next_row_number))

            upper_pseudo_pixel = math.rgb_color_lerp(prev_col_number, prev_row_prev_col_pixel, next_col_number, prev_row_next_col_pixel, x / factor)
            lower_pseudo_pixel = math.rgb_color_lerp(prev_col_number, next_row_prev_col_pixel, next_col_number, next_row_next_col_pixel, x / factor)

            result.putpixel((x, y), math.rgb_color_lerp(prev_row_number, upper_pseudo_pixel, next_row_number, lower_pseudo_pixel, y / factor))

    return result
def decimation_downsampling(image, factor):
    verification.verify_is_image_or_exception(image)

    if factor == 1:
        return image.copy()

    verification.verify_is_natural_or_exception(factor)

    result_width = image.width // factor
    result_height = image.height // factor
    result = Image.new(image.mode, (result_width, result_height))

    for x in range(image.width - factor + 1):
        if x % factor != 0:
            continue

        for y in range(image.height - factor + 1):
            if y % factor != 0:
                continue

            result.putpixel((x // factor, y // factor), image.getpixel((x, y)))

    return result
Exemple #24
0
def draw_series_length_matrix(image: Image) -> Image:
    verification.verify_is_image_or_exception(image)

    series_length_matrix = texturing.texturing.series_length_matrix(image)

    result = Image.new(mode=constants.constants.GRAYSCALE_MODE,
                       size=(len(series_length_matrix[0]),
                             len(series_length_matrix)))

    max_series_length = max([max(row) for row in series_length_matrix])

    for x in range(result.width):
        for y in range(result.height):
            result.putpixel(
                (x, y),
                int(
                    round(
                        math.math.lerp(x1=0,
                                       f1=0,
                                       x2=max_series_length,
                                       f2=255,
                                       x=series_length_matrix[y][x]))))

    return result
def normalized_black_weight(image):
    verify_is_image_or_exception(image)

    return black_weight(image) / (image.width * image.height)
def normalized_gravity_center(image):
    verify_is_image_or_exception(image)

    x, y = gravity_center(image)

    return (x - 1) / (image.width - 1), (y - 1) / (image.height - 1)
def normalized_central_vertical_axial_moment(image):
    verify_is_image_or_exception(image)

    return central_vertical_axial_moment(image) / (image.width**2 +
                                                   image.height**2)