Skip to content

Commit

Permalink
Merge pull request #386 from kwcckw/dev
Browse files Browse the repository at this point in the history
Added image quilting in PaperFactory's random texture generation.
  • Loading branch information
kwcckw authored Oct 25, 2023
2 parents 21386c1 + 811620a commit 2997e97
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 62 deletions.
43 changes: 14 additions & 29 deletions augraphy/augmentations/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,9 @@ def quilt_texture(image_texture, patch_size, patch_number_width, patch_number_he
xsize = (patch_number_width * patch_size) - (patch_number_width - 1) * overlap

# convert from gray to bgr
is_gray = 0
if len(image_texture.shape) < 3:
is_gray = 1
image_texture = cv2.cvtColor(image_texture, cv2.COLOR_GRAY2BGR)

# output
Expand Down Expand Up @@ -217,8 +219,13 @@ def quilt_texture(image_texture, patch_size, patch_number_width, patch_number_he
# smoothing
image_quilt = cv2.medianBlur(image_quilt, ksize=11)

# enhance contrast of texture
image_quilt = enhance_contrast(image_quilt)

# image follows input texture color channel
if is_gray:
image_quilt = cv2.cvtColor(image_quilt, cv2.COLOR_BGR2GRAY)

return image_quilt


Expand Down Expand Up @@ -360,37 +367,15 @@ def generate_texture(ysize, xsize, channel, value=255, sigma=1, turbulence=2):
new_max - new_min
) + new_min

# convert to 3 channels and uint8
image_output = cv2.cvtColor(image_output.astype("uint8"), cv2.COLOR_GRAY2BGR)
# convert to uint8
image_output = np.uint8(image_output)

# add colors into the texture
# conver to color image
if channel == 3:

# generate random color
hue_offset = random.randint(0, 15)
hue = random.randint(hue_offset, 254 - hue_offset)
hue_range = [hue - hue_offset, hue + hue_offset + 1]

# set min and max saturation
saturation_offset = random.randint(40, 60)
saturation = random.randint(saturation_offset, 254 - saturation_offset)
saturation_range = [saturation - saturation_offset, saturation + saturation_offset + 1]

# convert to hsv and get each channel
image_hsv = cv2.cvtColor(image_output, cv2.COLOR_BGR2HSV)
image_h = image_hsv[:, :, 0]
image_s = image_hsv[:, :, 1]
image_v = image_hsv[:, :, 2]

# update new hue and saturation value
image_h[:] = np.random.randint(hue_range[0], hue_range[1], size=(ysize, xsize))
image_s[:] = np.random.randint(saturation_range[0], saturation_range[1], size=(ysize, xsize))
# set min and max value
image_v[image_v < 50] += 50
image_v[image_v > 200] -= 50

# convert back to bgr
image_output = cv2.cvtColor(image_hsv, cv2.COLOR_HSV2BGR)
image_output = cv2.cvtColor(image_output, cv2.COLOR_GRAY2BGR)
elif channel == 1:
# remove additional channel for grayscale image
image_output = image_output[:, :, 0]

return image_output

Expand Down
117 changes: 84 additions & 33 deletions augraphy/base/paperfactory.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
import numpy as np

from augraphy.augmentations.brightness import Brightness
from augraphy.augmentations.colorpaper import ColorPaper
from augraphy.augmentations.lib import generate_average_intensity
from augraphy.augmentations.lib import generate_texture
from augraphy.augmentations.lib import quilt_texture
from augraphy.base.augmentation import Augmentation
from augraphy.base.augmentationresult import AugmentationResult
from augraphy.utilities.overlaybuilder import OverlayBuilder
Expand All @@ -19,8 +21,12 @@ class PaperFactory(Augmentation):
:param texture_path: Directory location to pull paper textures from.
:type texture_path: string, optional
:param texture_enable_color: Flag to enable color in the texture.
Use "random" for random choice.
:type texture__enable_color: int or string, optional
:param blend_texture: Flag to blend multiple textures.
:type blend_texture: int, optional
Use "random" for random choice.
:type blend_texture: int or string, optional
:param blend_method: The method to blend multiple textures.
:type blend_method: string, optional
:param p: The probability that this Augmentation will be applied.
Expand All @@ -30,13 +36,15 @@ class PaperFactory(Augmentation):
def __init__(
self,
texture_path="./paper_textures",
blend_texture=1,
texture_enable_color="random",
blend_texture="random",
blend_method="random",
p=1,
):
"""Constructor method"""
super().__init__(p=p)
self.texture_path = texture_path
self.texture_enable_color = texture_enable_color
self.blend_texture = blend_texture
self.blend_method = blend_method
self.texture_file_names = []
Expand All @@ -59,9 +67,14 @@ def __init__(

# Constructs a string representation of this Augmentation.
def __repr__(self):
return f"PaperFactory(texture_path={self.texture_path},blend_texture={self.blend_texture}, blend_method={self.blend_method}, p={self.p})"
return f"PaperFactory(texture_path={self.texture_path},texture_enable_color={self.texture_enable_color},blend_texture={self.blend_texture}, blend_method={self.blend_method}, p={self.p})"

def retrieve_texture(self, image):
"""Retrieve image texture from the input texture path.
:param image: The input image.
:type image: numpy array
"""
shape = image.shape
random_index = random.randint(0, len(self.paper_textures) - 1)
texture = self.paper_textures[random_index]
Expand Down Expand Up @@ -92,56 +105,74 @@ def retrieve_texture(self, image):

return texture

def generate_random_texture(self, image):
"""Generate random texture by creating random or repeating patterns.
:param image: The input image.
:type image: numpy array
"""

ysize, xsize = image.shape[:2]
sigma = random.uniform(3, 5)
turbulence = random.randint(3, 9)
texture = generate_texture(
ysize,
xsize,
channel=1,
value=255,
sigma=sigma,
turbulence=turbulence,
)

# quilt texture to create new repeating texture
if random.randint(0, 1):
patch_size = random.randint(15, 30)
patch_number_width = int(xsize / patch_size)
patch_number_height = int(ysize / patch_size)
texture = quilt_texture(texture, patch_size, patch_number_width, patch_number_height)

return texture

# 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():

# check for flag in blending textures
if self.blend_texture == "random":
blend_texture = random.randint(0, 1)
else:
blend_texture = self.blend_texture

# check for flag in enabling texture's color
if self.texture_enable_color == "random":
texture_enable_color = random.randint(0, 1)
else:
texture_enable_color = self.texture_enable_color

# get texture from paper
if self.paper_textures:
# get image texture
texture = self.retrieve_texture(image)
# generate random mask as texture
else:
ysize, xsize = image.shape[:2]
sigma = random.uniform(3, 5)
turbulence = random.randint(3, 9)
texture = generate_texture(
ysize,
xsize,
channel=random.choice([1, 3]),
value=255,
sigma=sigma,
turbulence=turbulence,
)
texture = self.generate_random_texture(image)

# blend multiple textures
if self.blend_texture:
if len(texture.shape) < 3:
texture = cv2.cvtColor(texture, cv2.COLOR_GRAY2BGR)
if blend_texture:

# get another image as texture
if len(self.paper_textures) > 0:
new_texture = self.retrieve_texture(image)
if len(new_texture.shape) < 3:
new_texture = self.retrieve_texture(texture)
if len(new_texture.shape) < 3 and len(texture.shape) > 2:
new_texture = cv2.cvtColor(new_texture, cv2.COLOR_GRAY2BGR)

# generate noise as texture if no texture is provided
elif len(new_texture.shape) > 2 and len(texture.shape) < 3:
new_texture = cv2.cvtColor(new_texture, cv2.COLOR_BGR2GRAY)
else:
ysize, xsize = texture.shape[:2]
sigma = random.uniform(3, 5)
turbulence = random.randint(3, 9)
new_texture = generate_texture(
ysize,
xsize,
channel=random.choice([1, 3]),
value=255,
sigma=sigma,
turbulence=turbulence,
)
new_texture = self.generate_random_texture(texture)

# resize for size consistency between both textures
new_texture = cv2.resize(
new_texture,
texture,
(texture.shape[1], texture.shape[0]),
interpolation=cv2.INTER_AREA,
)
Expand Down Expand Up @@ -181,6 +212,26 @@ def __call__(self, image, layer=None, mask=None, keypoints=None, bounding_boxes=

texture = ob.build_overlay()

if texture_enable_color:
if len(texture.shape) < 3:
# use ColorPaper to add color into the paper
texture = cv2.cvtColor(texture, cv2.COLOR_GRAY2BGR)

hue_offset = 10
hue = random.randint(hue_offset, 255 - hue_offset)
hue_range = [hue - hue_offset, hue + hue_offset]

saturation_offset = 10
saturation = random.randint(50 + saturation_offset, 205 - saturation_offset)
saturation_range = [saturation - saturation_offset, saturation + saturation_offset]

color_paper = ColorPaper(hue_range=hue_range, saturation_range=saturation_range)

texture = color_paper(texture)
else:
if len(texture.shape) > 2:
texture = cv2.cvtColor(texture, cv2.COLOR_BGR2GRAY)

# texture_intensity
texture_intensity = generate_average_intensity(texture)
# brighten dark texture based on target intensity, max intensity = 255 (brightest)
Expand Down

0 comments on commit 2997e97

Please sign in to comment.