| import numpy as np |
| import tensorflow as tf |
|
|
| from .spatial_transformer import transformer |
|
|
|
|
| def random_affine(tensors, *, |
| max_translation_x=0.0, max_translation_y=0.0, |
| max_rotation=0.0, min_scale=1.0, max_scale=1.0, |
| horizontal_flipping=False): |
| """Applies geometric augmentations to a list of tensors. |
| |
| Each element in the list is augmented in the same way. |
| For all elements, num_batch must be equal while height, width and channels |
| may differ. |
| """ |
| def _deg2rad(deg): |
| return (deg * np.pi) / 180.0 |
|
|
| with tf.variable_scope('random_affine'): |
| num_batch = tf.shape(tensors[0])[0] |
|
|
| zero = tf.zeros([num_batch]) |
| one = tf.ones([num_batch]) |
|
|
| tx = tf.random_uniform([num_batch], -max_translation_x, max_translation_x) |
| ty = tf.random_uniform([num_batch], -max_translation_y, max_translation_y) |
| rot = tf.random_uniform([num_batch], -max_rotation, max_rotation) |
| rad = _deg2rad(rot) |
| scale = tf.random_uniform([num_batch], min_scale, max_scale) |
|
|
| t1 = [[tf.cos(rad), -tf.sin(rad), tx], |
| [tf.sin(rad), tf.cos(rad), ty]] |
| t1 = tf.transpose(t1, [2, 0, 1]) |
|
|
| scale_x = scale |
| if horizontal_flipping: |
| flip = tf.random_uniform([num_batch], 0, 1) |
| flip = tf.where(tf.greater(flip, 0.5), -one, one) |
| scale_x = scale_x * flip |
|
|
| t2 = [[scale_x, zero, zero], |
| [zero, scale, zero], |
| [zero, zero, one]] |
| t2 = tf.transpose(t2, [2, 0, 1]) |
|
|
| t = tf.matmul(t1, t2) |
|
|
| out = [] |
| for tensor in tensors: |
| shape = tf.shape(tensor) |
| tensor = transformer(tensor, t, (shape[1], shape[2])) |
| out.append(tf.stop_gradient(tensor)) |
| return out |
|
|
|
|
| def random_photometric(ims, *, |
| noise_stddev=0.0, min_contrast=0.0, max_contrast=0.0, |
| brightness_stddev=0.0, min_colour=1.0, max_colour=1.0, |
| min_gamma=1.0, max_gamma=1.0): |
| """Applies photometric augmentations to a list of image batches. |
| |
| Each image in the list is augmented in the same way. |
| For all elements, num_batch must be equal while height and width may differ. |
| |
| Args: |
| ims: list of 3-channel image batches normalized to [0, 1]. |
| channel_mean: tensor of shape [3] which was used to normalize the pixel |
| values ranging from 0 ... 255. |
| |
| Returns: |
| Batch of normalized images with photometric augmentations. Has the same |
| shape as the input batch. |
| """ |
|
|
| with tf.variable_scope('random_photometric'): |
| num_batch = tf.shape(ims[0])[0] |
|
|
| contrast = tf.random_uniform([num_batch, 1], min_contrast, max_contrast) |
| gamma = tf.random_uniform([num_batch, 1], min_gamma, max_gamma) |
| gamma_inv = 1.0 / gamma |
| colour = tf.random_uniform([num_batch, 3], min_colour, max_colour) |
| if noise_stddev > 0.0: |
| noise = tf.random_normal([num_batch, 1], stddev=noise_stddev) |
| else: |
| noise = tf.zeros([num_batch, 1]) |
| if brightness_stddev > 0.0: |
| brightness = tf.random_normal([num_batch, 1], |
| stddev=brightness_stddev) |
| else: |
| brightness = tf.zeros([num_batch, 1]) |
|
|
| out = [] |
| for im in ims: |
| |
| im_re = tf.transpose(im, [1, 2, 0, 3]) |
| im_re = im_re |
| im_re = (im_re * (contrast + 1.0) + brightness) * colour |
| im_re = tf.maximum(0.0, tf.minimum(1.0, im_re)) |
| im_re = tf.pow(im_re, gamma_inv) |
|
|
| im_re = im_re + noise |
|
|
| |
| im_re = im_re |
|
|
| im = tf.transpose(im_re, [2, 0, 1, 3]) |
| im = tf.stop_gradient(im) |
| out.append(im) |
| return out |
|
|
|
|
| def random_crop(tensors, size, seed=None, name=None): |
| """Randomly crops multiple tensors (of the same shape) to a given size. |
| |
| Each tensor is cropped in the same way.""" |
| with tf.name_scope(name, "random_crop", [size]) as name: |
| size = tf.convert_to_tensor(size, dtype=tf.int32, name="size") |
| if len(tensors) == 2: |
| shape = tf.minimum(tf.shape(tensors[0]), tf.shape(tensors[1])) |
| else: |
| shape = tf.shape(tensors[0]) |
|
|
| limit = shape - size + 1 |
| offset = tf.random_uniform( |
| tf.shape(shape), |
| dtype=size.dtype, |
| maxval=size.dtype.max, |
| seed=seed) % limit |
| results = [] |
| for tensor in tensors: |
| result = tf.slice(tensor, offset, size) |
| results.append(result) |
| return results |
|
|