Source code for augraphy.augmentations.moire

import random

import cv2
import numba as nb
import numpy as np
from numba import config
from numba import jit

from augraphy.base.augmentation import Augmentation
from augraphy.utilities.overlaybuilder import OverlayBuilder


[docs] class Moire(Augmentation): """Creates a moire pattern effect in the image by blending the moire pattern using OverlayBuilder. :param moire_density: Pair of ints determining of density of the moire pattern stripes. :type moire_density: tuple, optional :param moire_blend_method: The blending method to blend moire pattern into the input image. :type moire_blend_method: int, optional :param moire_blend_alpha: The blending alpha value for blending method with the usage of alpha. :type moire_blend_alpha: float, optional :param numba_jit: The flag to enable numba jit to speed up the processing in the augmentation. :type numba_jit: int, optional :param p: The probability this Augmentation will be applied. :type p: float, optional """ def __init__( self, moire_density=(15, 20), moire_blend_method="normal", moire_blend_alpha=0.1, numba_jit=1, p=1, ): """Constructor method""" super().__init__(p=p) self.moire_density = moire_density self.moire_blend_method = moire_blend_method self.moire_blend_alpha = moire_blend_alpha self.numba_jit = numba_jit config.DISABLE_JIT = bool(1 - numba_jit) # Constructs a string representation of this Augmentation. def __repr__(self): return f"Moire(moire_density={self.moire_density}, moire_blend_method={self.moire_blend_method}, moire_blend_alpha={self.moire_blend_alpha}, numba_jit={self.numba_jit}, p={self.p})"
[docs] @staticmethod @jit(nopython=True, cache=True, parallel=True) def generate_moire_pattern(xsize, ysize, density_range): """Generate moire pattern by using sine function. :param xsize: Width of generated moire pattern. :type xsize: int, optional :param ysize: Height of generated moire pattern. :type ysize: int, optional :param density_range: Pair of ints determining of density of the moire pattern stripes. :type density_range: tuple, optional """ image = np.zeros((ysize, xsize), dtype="uint8") # random relative location relative_x = random.randint(5, 10) relative_y = random.randint(5, 10) # random density density = random.randint(density_range[0], density_range[1]) # random phase phase = 2 * np.pi * random.uniform(0.001, 0.01) # random offset if random.random() > 0.5: x_offset = random.randint(-5, -2) else: x_offset = random.randint(2, 5) if random.random() > 0.5: y_offset = random.randint(-5, -2) else: y_offset = random.randint(2, 5) # create moire pattern for y in nb.prange(ysize): new_y = ((y / ysize) * (y_offset * relative_y)) - relative_y for x in nb.prange(xsize): new_x = ((x / xsize) * (x_offset * relative_x)) - relative_x value = np.sin(phase + (density * 2 * np.pi * (np.sqrt(new_x**2 + new_y**2)))) image[x, y] = int(255 * (value + 1) / 2) return image
[docs] def blend_moire(self, image, image_moire): """Blend moire pattern into the image by using OverLayBuilder. :param image: The input image. :type image: numpy array, optional :param image_moire: Image with generated moire pattern. :type image_moire: numpy array, optional """ # minimum intensity so that pattern will not be too dark image_moire[image_moire < 30] = 30 # Create overlay object and blend moire pattern ob = OverlayBuilder( self.moire_blend_method, image_moire, image, 1, (1, 1), "center", self.moire_blend_alpha, ) image_output = ob.build_overlay() return image_output
# Applies the Augmentation to input data. def __call__(self, image, layer=None, mask=None, keypoints=None, bounding_boxes=None, force=False): if force or self.should_run(): image = image.copy() # convert and make sure image is color image has_alpha = 0 if len(image.shape) > 2: is_gray = 0 if image.shape[2] == 4: has_alpha = 1 image, image_alpha = image[:, :, :3], image[:, :, 3] else: is_gray = 1 image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) # create moire pattern image_moire1 = self.generate_moire_pattern(1000, 1000, self.moire_density) image_moire2 = self.generate_moire_pattern(1000, 1000, self.moire_density) # Create overlay object and blend moire pattern ob = OverlayBuilder( "overlay", image_moire1, image_moire2, 1, (1, 1), "center", 0.5, ) image_moire = ob.build_overlay() image_moire = cv2.resize(image_moire, (image.shape[1], image.shape[0]), interpolation=cv2.INTER_LINEAR) # enhance effect by using median filter image_moire = cv2.medianBlur(image_moire, 5) # blend moire pattern into image image_output = self.blend_moire(image, image_moire) # return image follows the input image color channel if is_gray: image_output = cv2.cvtColor(image_output, cv2.COLOR_BGR2GRAY) if has_alpha: image_output = np.dstack((image_output, image_alpha)) # check for additional output of mask, keypoints and bounding boxes outputs_extra = [] if mask is not None or keypoints is not None or bounding_boxes is not None: outputs_extra = [mask, keypoints, bounding_boxes] # returns additional mask, keypoints and bounding boxes if there is additional input if outputs_extra: # returns in the format of [image, mask, keypoints, bounding_boxes] return [image_output] + outputs_extra else: return image_output