|
from pathlib import Path |
|
from typing import Any, Union |
|
|
|
import numpy as np |
|
|
|
import cv2 |
|
|
|
from PIL import Image, ImageEnhance |
|
|
|
|
|
def load_image(file_name, path_to_images=None, rgb: bool = True): |
|
path = ( |
|
file_name |
|
if isinstance(file_name, Path) is True |
|
else path_to_images.joinpath(file_name) |
|
) |
|
|
|
try: |
|
img = cv2.imread(str(path)) |
|
if rgb is True: |
|
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) |
|
except Exception as e: |
|
print(file_name) |
|
return img |
|
|
|
|
|
def to_pil(image): |
|
return Image.fromarray(image) |
|
|
|
|
|
def to_cv2(image): |
|
return np.array(image) |
|
|
|
|
|
def enhance_pil_image( |
|
image, color=1, brightness=1, contrast=1, sharpness=1 |
|
) -> Image.Image: |
|
image = ImageEnhance.Sharpness( |
|
image=ImageEnhance.Brightness( |
|
image=ImageEnhance.Contrast( |
|
image=ImageEnhance.Color( |
|
image=( |
|
image |
|
if isinstance(image, Image.Image) is True |
|
else to_pil(image=image) |
|
) |
|
).enhance(color) |
|
).enhance(contrast) |
|
).enhance(brightness) |
|
).enhance(sharpness) |
|
return image |
|
|
|
|
|
def ensure_odd( |
|
i: int, |
|
min_val: Union[None, int] = None, |
|
max_val: Union[None, int] = None, |
|
) -> int: |
|
"""Transforms an odd number into pair number by adding one |
|
Arguments: |
|
i {int} -- number |
|
Returns: |
|
int -- Odd number |
|
""" |
|
if (i > 0) and (i % 2 == 0): |
|
i += 1 |
|
if min_val is not None: |
|
return max(i, min_val) |
|
if max_val is not None: |
|
return min(i, max_val) |
|
return i |
|
|
|
|
|
def get_morphology_kernel(size: int, shape: int): |
|
"""Builds morphology kernel |
|
:param size: kernel size, must be odd number |
|
:param shape: select shape of kernel |
|
:return: Morphology kernel |
|
""" |
|
size = ensure_odd(size) |
|
return cv2.getStructuringElement(shape, (size, size)) |
|
|
|
|
|
def close( |
|
image: Any, |
|
kernel_size: int = 3, |
|
kernel_shape: int = cv2.MORPH_ELLIPSE, |
|
rois: tuple = (), |
|
proc_times: int = 1, |
|
): |
|
"""Morphology - Close wrapper |
|
Arguments: |
|
image {numpy array} -- Source image |
|
kernel_size {int} -- kernel size |
|
kernel_shape {int} -- cv2 constant |
|
roi -- Region of Interest |
|
proc_times {int} -- iterations |
|
Returns: |
|
numpy array -- closed image |
|
""" |
|
morph_kernel = get_morphology_kernel(kernel_size, kernel_shape) |
|
if rois: |
|
result = image.copy() |
|
for roi in rois: |
|
r = roi.as_rect() |
|
result[r.top : r.bottom, r.left : r.right] = cv2.morphologyEx( |
|
result[r.top : r.bottom, r.left : r.right], |
|
cv2.MORPH_CLOSE, |
|
morph_kernel, |
|
iterations=proc_times, |
|
) |
|
else: |
|
result = cv2.morphologyEx( |
|
image, cv2.MORPH_CLOSE, morph_kernel, iterations=proc_times |
|
) |
|
return result |
|
|
|
|
|
def get_concat_h_multi_resize(im_list, resample=Image.Resampling.BICUBIC): |
|
min_height = min(im.height for im in im_list) |
|
im_list_resize = [ |
|
im.resize( |
|
(int(im.width * min_height / im.height), min_height), resample=resample |
|
) |
|
for im in im_list |
|
] |
|
total_width = sum(im.width for im in im_list_resize) |
|
dst = Image.new("RGB", (total_width, min_height)) |
|
pos_x = 0 |
|
for im in im_list_resize: |
|
dst.paste(im, (pos_x, 0)) |
|
pos_x += im.width |
|
return dst |
|
|
|
|
|
def get_concat_v_multi_resize(im_list, resample=Image.Resampling.BICUBIC): |
|
min_width = min(im.width for im in im_list) |
|
im_list_resize = [ |
|
im.resize((min_width, int(im.height * min_width / im.width)), resample=resample) |
|
for im in im_list |
|
] |
|
total_height = sum(im.height for im in im_list_resize) |
|
dst = Image.new("RGB", (min_width, total_height)) |
|
pos_y = 0 |
|
for im in im_list_resize: |
|
dst.paste(im, (0, pos_y)) |
|
pos_y += im.height |
|
return dst |
|
|
|
|
|
def get_concat_tile_resize(im_list_2d, resample=Image.Resampling.BICUBIC): |
|
im_list_v = [ |
|
get_concat_h_multi_resize(im_list_h, resample=resample) |
|
for im_list_h in im_list_2d |
|
] |
|
return get_concat_v_multi_resize(im_list_v, resample=resample) |
|
|
|
|
|
def get_tiles(img_list, row_count, resample=Image.Resampling.BICUBIC): |
|
if isinstance(img_list, np.ndarray) is False: |
|
img_list = np.asarray(img_list, dtype="object") |
|
return get_concat_tile_resize(np.split(img_list, row_count), resample) |
|
|