Source code for utils.image_aug
"""Image Augmentation methods.
"""
import numpy as np
from tensorflow.image import random_contrast, random_saturation
[docs]class ImgAug:
'''Element-wise image augmentation methods, used to preprocess a
given dataset.
(most affine transformations used are implemented in \
:class:`tensorflow.keras.preprocessing.image.ImageDataGenerator`)
'''
[docs] @staticmethod
def random_cutout(np_tensor, cutout_color=127):
'''Randomly applies cutout augmentation to a given rank 3 tensor as
defined in [1]. Defaults to grey cutout
[1] DeVries, T., & Taylor, G. W. (2017). Improved regularization of
convolutional neural networks with cutout.
Args:
np_tensor (:class:`numpy.array`): rank 3 numpy tensor-respresentation of \
the data sample
cutout_color (int, optional): RGB-uniform value of the cutout color \
*(defaults to grey (* :code:`127` *). white (* :code:`255` *) and black \
(* :code:`0` *) are also valid)*
Returns:
:class:`numpy.array`: augmented numpy tensor (with a random cutout)
'''
cutout_height = int(np.random.uniform(0.1, 0.2) * np_tensor.shape[0])
cutout_width = int(np.random.uniform(0.1, 0.2) * np_tensor.shape[1])
cutout_height_point = np.random.randint(np_tensor.shape[0] - cutout_height)
cutout_width_point = np.random.randint(np_tensor.shape[1] - cutout_width)
np_tensor[cutout_height_point: cutout_height_point + cutout_height,
cutout_width_point: cutout_width_point + cutout_width,
:] = cutout_color # 127 = grey cutout,
# 0 (black) or 255 (white) also valid
return np.array(np_tensor)
[docs] @staticmethod
def random_contrast(np_tensor):
'''Apply random contrast augmentation
Args:
np_tensor (:class:`numpy.array`): rank 3 numpy tensor-respresentation of \
the data sample
Returns:
(:class:`numpy.array`): transformed numpy tensor with random contrast
'''
return np.array(random_contrast(np_tensor, 0.5, 2))
[docs] @staticmethod
def random_saturation(np_tensor):
'''Apply random saturation augmentation (only works on RGB images, \
skipped on grayscale datasets)
Args:
np_tensor (:class:`numpy.array`): rank 3 numpy tensor-respresentation of \
the data sample
Returns:
(:class:`numpy.array`): transformed numpy tensor with random saturation
'''
if np_tensor.shape[-1] != 3:
# not an RGB image, skip augmentation
return np.array(np_tensor)
return np.array(random_saturation(np_tensor, 0.2, 3))
[docs] @staticmethod
def augment(np_tensor):
'''Used by ImageDataGenerator's preprocess_function
Args:
np_tensor (:class:`numpy.array`): rank 3 numpy tensor-respresentation of \
the data sample
Returns:
(:class:`numpy.array`): augmented numpy tensor with all applicable \
transformations/augmentations
'''
from config import Params
if np.random.uniform() <= Params['CONTRAST_AUG_PROB']:
np_tensor = ImgAug.random_contrast(np_tensor)
if np.random.uniform() <= Params['SATURATION_AUG_PROB']:
np_tensor = ImgAug.random_saturation(np_tensor)
if np.random.uniform() <= Params['CUTOUT_PROB']:
np_tensor = ImgAug.random_cutout(np_tensor)
return np_tensor