-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcustom_transforms.py
More file actions
166 lines (137 loc) · 5.24 KB
/
custom_transforms.py
File metadata and controls
166 lines (137 loc) · 5.24 KB
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
from __future__ import division
import torch
import random
import numpy as np
import math
import cv2
'''Set of transform random routines that takes list of inputs as arguments,
in order to have random but coherent transformations.'''
class Compose(object):
"""
Transform that composes transforms.
"""
def __init__(self, transforms):
"""
Initializer
:param transforms: list of transforms
:type transforms: list
"""
self.transforms = transforms
def __call__(self, images, intrinsics):
"""
Call to the transform.
:param images: list of image tensors on which the transforms have to be applied
:type images: list
:param intrinsics: intrinsics tensor
:type intrinsics: tensor
:return: images with all the transforms applied on it and the intrinsics tensor
:rtype: tuple
"""
for t in self.transforms:
images, intrinsics = t(images, intrinsics)
return images, intrinsics
class Normalize(object):
"""
Normalizes an image tensor with the specified mean and standard deviation.
"""
def __init__(self, mean, std):
"""
Initializes the transform.
:param mean: mean of the tensor data
:type mean: float
:param std: standard deviation of the tensor data
:type std: float
"""
self.mean = mean
self.std = std
def __call__(self, images, intrinsics):
"""
Call to the transform. Normalizes the input tensor.
:param images: list of image tensors that have to be normalized
:type images: list
:param intrinsics: Intrinsics tensor. Not used, just returned as is
:type intrinsics: tensor
:return: normalized image tensors and the intrinsics tensor
:rtype: tuple
"""
for tensor in images:
tensor.sub_(self.mean).div_(self.std)
return images, intrinsics
class ArrayToTensor(object):
"""
Converts a list of numpy.ndarray (H x W x C) along with a intrinsics matrix to a list
of torch.FloatTensor of shape (C x H x W) with a intrinsics tensor.
"""
def __call__(self, images, intrinsics):
"""
Call to the transform.
:param images: list of numpy.ndarray of shape (H x W x C)
:type images: list
:param intrinsics: intrinsics matrix
:type intrinsics: numpy array
:return: list of image tensors of shape (C x H x W) and the intrinsics tensor
:rtype: tuple
"""
tensors = []
for im in images:
# put it from HWC to CHW format
if (len(im.shape)) > 2:
im = np.transpose(im, (2, 0, 1))
else:
im = im.reshape([1, im.shape[0], im.shape[1]])
# handle numpy array
tensors.append(torch.from_numpy(im).float() / 255.0)
return tensors, intrinsics
class RandomHorizontalFlip(object):
"""
Randomly horizontally flips the given numpy array with a probability of 0.5
"""
def __call__(self, images, intrinsics):
"""
Call to the transform
:param images: list of image tensors
:type images: list
:param intrinsics: intrinsics tensor. not used. returned as is.
:type intrinsics: tensor
:return: list of transformed images and the intrinsics tensor
:rtype: list
"""
assert intrinsics is not None
if random.random() < 0.5:
output_intrinsics = np.copy(intrinsics)
output_images = [np.copy(np.fliplr(im)) for im in images]
w = output_images[0].shape[1]
output_intrinsics[0, 2] = w - output_intrinsics[0, 2]
else:
output_images = images
output_intrinsics = intrinsics
return output_images, output_intrinsics
class RandomScaleCrop(object):
"""
Randomly zooms images up to 15% and crops them to keep same size as before.
"""
def __call__(self, images, intrinsics):
"""
Call to the transform
:param images: list of image tensors
:type images: list
:param intrinsics: intrinsics tensor. not used. returned as is.
:type intrinsics: tensor
:return: list of transformed images and the intrinsics tensor
:rtype: list
"""
assert intrinsics is not None
output_intrinsics = np.copy(intrinsics)
in_h, in_w, _ = images[0].shape
x_scaling, y_scaling = np.random.uniform(1, 1.15, 2)
scaled_h, scaled_w = int(in_h * y_scaling), int(in_w * x_scaling)
output_intrinsics[0] *= x_scaling
output_intrinsics[1] *= y_scaling
# scaled_images = [imresize(im, (scaled_h, scaled_w)) for im in images] # scipy imresize is Deprecated
scaled_images = [cv2.resize(im, (scaled_w, scaled_h)) for im in images] # Note width first and height next
offset_y = np.random.randint(scaled_h - in_h + 1)
offset_x = np.random.randint(scaled_w - in_w + 1)
cropped_images = [im[offset_y:offset_y + in_h, offset_x:offset_x + in_w] for im in scaled_images]
output_intrinsics[0, 2] -= offset_x
output_intrinsics[1, 2] -= offset_y
return cropped_images, output_intrinsics