class RotateLine(iaa.meta.Augmenter): """ Drop-in replace for imgaug's Affine's rotation as the supplied rotation does not support fill in cval. With probability 60% """ def __init__(self, angle=(-10, 10), cval=255, name=None, deterministic=False, random_state=None): """Initialize the augmentator # Arguments angle [float or tuple of 2 floats]: if it is a single number, then image will be rotated in that degree. If it is a tuple of 2 numbers, then the angle value will be chosen randomly cval [int]: fill-in value to new pixels """ super(RotateLine, self).__init__(name=name, deterministic=deterministic, random_state=random_state) if isinstance(angle, StochasticParameter): self.angle = angle elif ia.is_single_number(angle): self.angle = Deterministic(angle) elif ia.is_iterable(angle): ia.do_assert( len(angle) == 2, "Expected rotate tuple/list with 2 entries, got {} entries.". format((len(angle)))) ia.do_assert(all([ia.is_single_number(val) for val in angle]), "Expected floats/ints in angle tuple/list.") self.angle = Uniform(angle[0], angle[1]) else: raise Exception( "Expected float, int, tuple/list with 2 entries or " "StochasticParameter. Got {}.".format(type(angle))) self.cval = cval def _augment_images(self, images, random_state, parents, hooks): """Augment the images # Arguments images [list of np array]: the list of images # Returns [list of np array]: the list of augmented images """ result = images seed = random_state.randint(0, 10**6, 1)[0] angle_values = self.angle.draw_samples( (len(images), ), random_state=ia.new_random_state(seed + 90)) for _idx, image in enumerate(result): angle = angle_values[_idx] if angle == 0: continue result[_idx] = rotate(image, angle, order=1, cval=self.cval) return result def _augment_keypoints(self, keypoints_on_images, random_state, parents, hooks): return keypoints_on_images def _augment_heatmaps(self, **kwargs): return def get_parameters(self): return [self.angle, self.cval]
def main(): params = [ ("Binomial(0.1)", Binomial(0.1)), ("Choice", Choice([0, 1, 2])), ("Choice with p", Choice([0, 1, 2], p=[0.1, 0.2, 0.7])), ("DiscreteUniform(0, 10)", DiscreteUniform(0, 10)), ("Poisson(0)", Poisson(0)), ("Poisson(5)", Poisson(5)), ("Discretize(Poisson(5))", Discretize(Poisson(5))), ("Normal(0, 1)", Normal(0, 1)), ("Normal(1, 1)", Normal(1, 1)), ("Normal(1, 2)", Normal(0, 2)), ("Normal(Choice([-1, 1]), 2)", Normal(Choice([-1, 1]), 2)), ("Discretize(Normal(0, 1.0))", Discretize(Normal(0, 1.0))), ("Positive(Normal(0, 1.0))", Positive(Normal(0, 1.0))), ("Positive(Normal(0, 1.0), mode='reroll')", Positive(Normal(0, 1.0), mode="reroll")), ("Negative(Normal(0, 1.0))", Negative(Normal(0, 1.0))), ("Negative(Normal(0, 1.0), mode='reroll')", Negative(Normal(0, 1.0), mode="reroll")), ("Laplace(0, 1.0)", Laplace(0, 1.0)), ("Laplace(1.0, 3.0)", Laplace(1.0, 3.0)), ("Laplace([-1.0, 1.0], 1.0)", Laplace([-1.0, 1.0], 1.0)), ("ChiSquare(1)", ChiSquare(1)), ("ChiSquare([1, 6])", ChiSquare([1, 6])), ("Weibull(0.5)", Weibull(0.5)), ("Weibull((1.0, 3.0))", Weibull((1.0, 3.0))), ("Uniform(0, 10)", Uniform(0, 10)), ("Beta(0.5, 0.5)", Beta(0.5, 0.5)), ("Deterministic(1)", Deterministic(1)), ("Clip(Normal(0, 1), 0, None)", Clip(Normal(0, 1), minval=0, maxval=None)), ("Multiply(Uniform(0, 10), 2)", Multiply(Uniform(0, 10), 2)), ("Add(Uniform(0, 10), 5)", Add(Uniform(0, 10), 5)), ("Absolute(Normal(0, 1))", Absolute(Normal(0, 1))), ("RandomSign(Poisson(1))", RandomSign(Poisson(1))), ("RandomSign(Poisson(1), 0.9)", RandomSign(Poisson(1), 0.9)) ] params_arithmetic = [ ("Normal(0, 1.0)", Normal(0.0, 1.0)), ("Normal(0, 1.0) + 5", Normal(0.0, 1.0) + 5), ("Normal(0, 1.0) * 10", Normal(0.0, 1.0) * 10), ("Normal(0, 1.0) / 10", Normal(0.0, 1.0) / 10), ("Normal(0, 1.0) ** 2", Normal(0.0, 1.0) ** 2) ] params_noise = [ ("SimplexNoise", SimplexNoise()), ("Sigmoid(SimplexNoise)", Sigmoid(SimplexNoise())), ("SimplexNoise(linear)", SimplexNoise(upscale_method="linear")), ("SimplexNoise(nearest)", SimplexNoise(upscale_method="nearest")), ("FrequencyNoise((-4, 4))", FrequencyNoise(exponent=(-4, 4))), ("FrequencyNoise(-2)", FrequencyNoise(exponent=-2)), ("FrequencyNoise(2)", FrequencyNoise(exponent=2)) ] images_params = [param.draw_distribution_graph() for (title, param) in params] images_arithmetic = [param.draw_distribution_graph() for (title, param) in params_arithmetic] images_noise = [param.draw_distribution_graph(size=(1000, 10, 10)) for (title, param) in params_noise] misc.imshow(np.vstack(images_params)) misc.imshow(np.vstack(images_arithmetic)) misc.imshow(np.vstack(images_noise))
class ItalicizeLine(iaa.meta.Augmenter): """ Drop-in replace for shear transformation in iaa.Affine (the implementation inside iaa.Affine crop images while italicizee) """ def __init__(self, shear=(-40, 41), cval=255, vertical=False, name=None, deterministic=False, random_state=None): """Initialize the augmentator # Arguments shear [float or tuple of 2 floats]: if it is a single number, then image will be sheared in that degree. If it is a tuple of 2 numbers, then the shear value will be chosen randomly cval [int]: fill-in value to new pixels """ super(ItalicizeLine, self).__init__(name=name, deterministic=deterministic, random_state=random_state) if isinstance(shear, StochasticParameter): self.shear = shear elif ia.is_single_number(shear): self.shear = Deterministic(shear) elif ia.is_iterable(shear): ia.do_assert( len(shear) == 2, "Expected rotate tuple/list with 2 entries, got {} entries.". format((len(shear)))) ia.do_assert(all([ia.is_single_number(val) for val in shear]), "Expected floats/ints in shear tuple/list.") self.shear = Uniform(shear[0], shear[1]) else: raise Exception( "Expected float, int, tuple/list with 2 entries or " "StochasticParameter. Got {}.".format(type(shear))) self.cval = cval self.vertical = vertical def _augment_images(self, images, random_state, parents, hooks): """Augment the images # Arguments images [list of np array]: the list of images # Returns [list of np array]: the list of augmented images """ result = images seed = random_state.randint(0, 10**6, 1)[0] shear_values = self.shear.draw_samples( (len(images), ), random_state=ia.new_random_state(seed + 80)) for _idx, image in enumerate(result): angle = shear_values[_idx] if angle == 0: continue if self.vertical: # use horizontal italicization method image = rotate(image, -90, order=1, cval=self.cval) height, original_width, _ = image.shape distance = int(height * math.tan(math.radians(math.fabs(angle)))) if angle > 0: point1 = np.array([[0, 0], [0, height], [5, 0]], dtype=np.float32) point2 = np.array( [[distance, 0], [0, height], [5 + distance, 0]], dtype=np.float32) image = np.concatenate([ image, np.ones((height, distance, 1), dtype=np.uint8) * self.cval ], axis=1) else: point1 = np.array( [[distance, 0], [distance, height], [distance + 5, 0]], dtype=np.float32) point2 = np.array([[0, 0], [distance, height], [5, 0]], dtype=np.float32) image = np.concatenate([ np.ones((height, distance, 1), dtype=np.uint8) * self.cval, image ], axis=1) height, width, _ = image.shape matrix = cv2.getAffineTransform(point1, point2) image = cv2.warpAffine(image, matrix, (width, height), borderValue=self.cval) if self.vertical: # use horizontal intalicization method image = rotate(image, 90, order=1, cval=self.cval) if image.ndim == 2: image = image[..., np.newaxis] result[_idx] = image return result def _augment_keypoints(self, keypoints_on_images, random_state, parents, hooks): return keypoints_on_images def _augment_heatmaps(self, **kwargs): return def get_parameters(self): return [self.shear, self.cval]
class HSVShift(augmenter_base.ParamatarizedAugmenter): """ Perform random HSV shift on the RGB data. MODIFIED FROM LIGHTNET YOLO into imgaug format Args: hue (Number): Random number between -hue,hue is used to shift the hue. The number is specified as a percentage of the available hue space (e.g. hue * 255 or hue * 360). saturation (Number): Random number between 1,saturation is used to shift the saturation; 50% chance to get 1/dSaturation instead of dSaturation value (Number): Random number between 1,value is used to shift the value; 50% chance to get 1/dValue in stead of dValue CommandLine: python -m netharn.data.transforms.augmenters HSVShift --show Example: >>> self = HSVShift(0.1, 1.5, 1.5) >>> img = demodata_hsv_image() >>> aug = self.augment_image(img) >>> det = self.to_deterministic() >>> assert np.all(det.augment_image(img) == det.augment_image(img)) >>> # xdoc: +REQUIRES(--show) >>> from netharn.util import mplutil >>> import ubelt as ub >>> mplutil.autompl() >>> mplutil.figure(doclf=True, fnum=3) >>> self = HSVShift(0.5, 1.5, 1.5) >>> pnums = mplutil.PlotNums(5, 5) >>> #random_state = self.random_state >>> self.reseed(random.Random(0)) >>> mplutil.imshow(img, colorspace='rgb', pnum=pnums[0], title='orig') >>> for i in range(1, len(pnums)): >>> aug = self.augment_image(img) >>> title = 'aug: {}'.format(ub.repr2(self._prev_params, nl=0, precision=3)) >>> mplutil.imshow(aug, colorspace='rgb', pnum=pnums[i], title=title) >>> mplutil.show_if_requested() Ignore: >>> from netharn.data.transforms.augmenters import * >>> lnpre = ub.import_module_from_path(ub.truepath('~/code/lightnet/lightnet/data/transform/_preprocess.py')) >>> self = lnpre.HSVShift(0.1, 1.5, 1.5) >>> from PIL import Image >>> img = demodata_hsv_image() >>> from_ = ub.identity >>> #img = Image.fromarray(img) >>> #from_ = np.array >>> aug = self(img) >>> # xdoc: +REQUIRES(--show) >>> from netharn.util import mplutil >>> import ubelt as ub >>> mplutil.autompl() >>> mplutil.figure(doclf=True, fnum=1) >>> import random >>> random.seed(0) >>> pnums = mplutil.PlotNums(5, 5) >>> mplutil.imshow(from_(img), colorspace='rgb', pnum=pnums[0], title='orig') >>> for i in range(1, len(pnums)): >>> aug = self(img) >>> #title = 'aug: {}'.format(ub.repr2(self._prev_params, nl=0, precision=3)) >>> title = 'foo' >>> mplutil.imshow(from_(aug), colorspace='rgb', pnum=pnums[i], title=title) >>> mplutil.show_if_requested() """ def __init__(self, hue, sat, val, input_colorspace='rgb'): super(HSVShift, self).__init__() self.input_colorspace = input_colorspace self.hue = Uniform(-hue, hue) self.sat = Uniform(1, sat) self.val = Uniform(1, val) self.flip_val = Binomial(.5) self.flip_sat = Binomial(.5) def _augment_heatmaps(self, *args, **kw): # TODO raise NotImplementedError pass def _augment_images(self, images, random_state, parents, hooks): return [self.forward(img, random_state) for img in images] def _augment_keypoints(self, keypoints_on_images, random_state, parents, hooks): return keypoints_on_images @profiler.profile def forward(self, img, random_state=None): assert self.input_colorspace == 'rgb' assert img.dtype.kind == 'u' and img.dtype.itemsize == 1 dh = self.hue.draw_sample(random_state) ds = self.sat.draw_sample(random_state) dv = self.val.draw_sample(random_state) if self.flip_sat.draw_sample(random_state): ds = 1.0 / ds if self.flip_val.draw_sample(random_state): dv = 1.0 / dv self._prev_params = (dh, ds, dv) # Note the cv2 conversion to HSV does not go into the 0-1 range, # instead it goes into (0-360, 0-1, 0-1) for hue, sat, and val. img01 = img.astype(np.float32) / 255.0 hsv = cv2.cvtColor(img01, cv2.COLOR_RGB2HSV) hue_bound = 360.0 sat_bound = 1.0 val_bound = 1.0 def wrap_hue(new_hue, hue_bound): """ This is about 10x faster than using modulus """ out = new_hue out[out >= hue_bound] -= hue_bound out[out < 0] += hue_bound return out # add to hue hsv[:, :, 0] = wrap_hue(hsv[:, :, 0] + (hue_bound * dh), hue_bound) # scale saturation and value hsv[:, :, 1] = np.clip(ds * hsv[:, :, 1], 0.0, sat_bound) hsv[:, :, 2] = np.clip(dv * hsv[:, :, 2], 0.0, val_bound) img01 = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB) img255 = (img01 * 255).astype(np.uint8) return img255