diff --git a/cv_analysis/utils/image_operations.py b/cv_analysis/utils/image_operations.py new file mode 100644 index 0000000..58b3ffe --- /dev/null +++ b/cv_analysis/utils/image_operations.py @@ -0,0 +1,51 @@ +from typing import Tuple + +import cv2 as cv +import numpy as np +from PIL import ImageOps + +Color = Tuple[int, int, int] + + +def blur(image: np.ndarray): + return cv.blur(image, (3, 3)) + + +def sharpen(image: np.ndarray): + return cv.filter2D(image, -1, np.array([[-1, -1, -1], [-1, 6, -1], [-1, -1, -1]])) + + +def overlay(images, mode=np.sum): + assert mode in [np.sum, np.max] + images = np.stack(list(images)) + image = mode(images, axis=0) + image = (image / image.max() * 255).astype(np.uint8) + return image + + +def tint_image(src, color="#FFFFFF"): + src.load() + r, g, b, alpha = src.split() + gray = ImageOps.grayscale(src) + result = ImageOps.colorize(gray, (0, 0, 0), color) + result.putalpha(alpha) + return result + + +def color_shift_array(image: np.ndarray, color: Color): + """Creates a 3-tensor from a 2-tensor by stacking the 2-tensor three times weighted by the color tuple.""" + assert image.ndim == 3 + assert image.shape[-1] == 3 + assert isinstance(color, tuple) + assert max(color) <= 255 + assert image.max() <= 255 + + color = np.array(color) + weights = color / color.sum() / 10 + assert max(weights) <= 1 + + colored = (image * weights).astype(np.uint8) + + assert colored.shape == image.shape + + return colored diff --git a/test/fixtures/page_generation/page.py b/test/fixtures/page_generation/page.py index 12c26c3..ab8c21a 100644 --- a/test/fixtures/page_generation/page.py +++ b/test/fixtures/page_generation/page.py @@ -12,10 +12,9 @@ from pathlib import Path from typing import Tuple, Iterable, List import blend_modes -import cv2 as cv import numpy as np import pytest -from PIL import Image, ImageOps, ImageFont, ImageDraw, ImageEnhance +from PIL import Image, ImageFont, ImageDraw, ImageEnhance from PIL.Image import Transpose from faker import Faker from loguru import logger @@ -24,6 +23,7 @@ from matplotlib.colors import ListedColormap from cv_analysis.utils import star, rconj, conj from cv_analysis.utils.conversion import normalize_image_format_to_array, normalize_image_format_to_pil +from cv_analysis.utils.image_operations import blur, sharpen, overlay from cv_analysis.utils.merging import merge_related_rectangles from cv_analysis.utils.postprocessing import remove_overlapping, remove_included from cv_analysis.utils.spacial import area @@ -70,9 +70,6 @@ from cv_analysis.utils.display import show_image from cv_analysis.utils.rectangle import Rectangle -Color = Tuple[int, int, int] - - @pytest.fixture( params=[ # "rough_grain", @@ -176,10 +173,6 @@ def texture_fn(texture_name, size): return normalize_image_function(fn) -def blur(image: np.ndarray): - return cv.blur(image, (3, 3)) - - def normalize_image_function(func): def inner(image): image = normalize_image_format_to_array(image) @@ -190,18 +183,6 @@ def normalize_image_function(func): return inner -def sharpen(image: np.ndarray): - return cv.filter2D(image, -1, np.array([[-1, -1, -1], [-1, 6, -1], [-1, -1, -1]])) - - -def overlay(images, mode=np.sum): - assert mode in [np.sum, np.max] - images = np.stack(list(images)) - image = mode(images, axis=0) - image = (image / image.max() * 255).astype(np.uint8) - return image - - @pytest.fixture def texture(tinted_blank_page, base_texture): texture = superimpose_texture_with_transparency(base_texture, tinted_blank_page) @@ -222,34 +203,6 @@ def blank_page(size, color, color_intensity): return page -def tint_image(src, color="#FFFFFF"): - src.load() - r, g, b, alpha = src.split() - gray = ImageOps.grayscale(src) - result = ImageOps.colorize(gray, (0, 0, 0), color) - result.putalpha(alpha) - return result - - -def color_shift_array(image: np.ndarray, color: Color): - """Creates a 3-tensor from a 2-tensor by stacking the 2-tensor three times weighted by the color tuple.""" - assert image.ndim == 3 - assert image.shape[-1] == 3 - assert isinstance(color, tuple) - assert max(color) <= 255 - assert image.max() <= 255 - - color = np.array(color) - weights = color / color.sum() / 10 - assert max(weights) <= 1 - - colored = (image * weights).astype(np.uint8) - - assert colored.shape == image.shape - - return colored - - @pytest.fixture def size(dpi, orientation): if orientation == "portrait":