-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathaugment.py
134 lines (107 loc) · 4.67 KB
/
augment.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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:
# Transpose to [height, width, num_batch, channels]
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
# Subtract the mean again after clamping
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