-
Notifications
You must be signed in to change notification settings - Fork 31
/
utils.py
178 lines (149 loc) · 6.75 KB
/
utils.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
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
167
168
169
170
171
172
173
174
175
176
177
"""
The code implementation of the paper:
A. Rasouli, I. Kotseruba, T. Kunic, and J. Tsotsos, "PIE: A Large-Scale Dataset and Models for Pedestrian Intention Estimation and
Trajectory Prediction", ICCV 2019.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import sys
import PIL
from keras.preprocessing.image import img_to_array, load_img
def update_progress(progress):
barLength = 20 # Modify this to change the length of the progress bar
status = ""
if isinstance(progress, int):
progress = float(progress)
block = int(round(barLength*progress))
text = "\r[{}] {:0.2f}% {}".format( "#"*block + "-"*(barLength-block), progress*100, status)
sys.stdout.write(text)
sys.stdout.flush()
######### DATA UTILITIES ##############
def img_pad(img, mode = 'warp', size = 224):
'''
Pads a given image.
Crops and/or pads a image given the boundries of the box needed
img: the image to be coropped and/or padded
bbox: the bounding box dimensions for cropping
size: the desired size of output
mode: the type of padding or resizing. The modes are,
warp: crops the bounding box and resize to the output size
same: only crops the image
pad_same: maintains the original size of the cropped box and pads with zeros
pad_resize: crops the image and resize the cropped box in a way that the longer edge is equal to
the desired output size in that direction while maintaining the aspect ratio. The rest of the image is
padded with zeros
pad_fit: maintains the original size of the cropped box unless the image is biger than the size in which case
it scales the image down, and then pads it
'''
assert(mode in ['same', 'warp', 'pad_same', 'pad_resize', 'pad_fit']), 'Pad mode %s is invalid' % mode
image = img.copy()
if mode == 'warp':
warped_image = image.resize((size,size),PIL.Image.NEAREST)
return warped_image
elif mode == 'same':
return image
elif mode in ['pad_same','pad_resize','pad_fit']:
img_size = image.size # size is in (width, height)
ratio = float(size)/max(img_size)
if mode == 'pad_resize' or \
(mode == 'pad_fit' and (img_size[0] > size or img_size[1] > size)):
img_size = tuple([int(img_size[0]*ratio),int(img_size[1]*ratio)])
image = image.resize(img_size, PIL.Image.NEAREST)
padded_image = PIL.Image.new("RGB", (size, size))
padded_image.paste(image, ((size-img_size [0])//2,
(size-img_size [1])//2))
return padded_image
def squarify(bbox, squarify_ratio, img_width):
width = abs(bbox[0] - bbox[2])
height = abs(bbox[1] - bbox[3])
width_change = height * squarify_ratio - width
# width_change = float(bbox[4])*self._squarify_ratio - float(bbox[3])
bbox[0] = bbox[0] - width_change/2
bbox[2] = bbox[2] + width_change/2
# bbox[1] = str(float(bbox[1]) - width_change/2)
# bbox[3] = str(float(bbox[3]) + width_change)
# Squarify is applied to bounding boxes in Matlab coordinate starting from 1
if bbox[0] < 0:
bbox[0] = 0
# check whether the new bounding box goes beyond image boarders
# If this is the case, the bounding box is shifted back
if bbox[2] > img_width:
# bbox[1] = str(-float(bbox[3]) + img_dimensions[0])
bbox[0] = bbox[0]-bbox[2] + img_width
bbox[2] = img_width
return bbox
def bbox_sanity_check(img, bbox):
'''
This is to confirm that the bounding boxes are within image boundaries.
If this is not the case, modifications is applied.
This is to deal with inconsistencies in the annotation tools
'''
img_width, img_heigth = img.size
if bbox[0] < 0:
bbox[0] = 0.0
if bbox[1] < 0:
bbox[1] = 0.0
if bbox[2] >= img_width:
bbox[2] = img_width - 1
if bbox[3] >= img_heigth:
bbox[3] = img_heigth - 1
return bbox
def jitter_bbox(img_path,bbox, mode, ratio):
'''
This method jitters the position or dimentions of the bounding box.
mode: 'same' returns the bounding box unchanged
'enlarge' increases the size of bounding box based on the given ratio.
'random_enlarge' increases the size of bounding box by randomly sampling a value in [0,ratio)
'move' moves the center of the bounding box in each direction based on the given ratio
'random_move' moves the center of the bounding box in each direction by randomly sampling a value in [-ratio,ratio)
ratio: The ratio of change relative to the size of the bounding box. For modes 'enlarge' and 'random_enlarge'
the absolute value is considered.
Note: Tha ratio of change in pixels is calculated according to the smaller dimension of the bounding box.
'''
assert(mode in ['same','enlarge','move','random_enlarge','random_move']), \
'mode %s is invalid.' % mode
if mode == 'same':
return bbox
img = load_img(img_path)
img_width, img_heigth = img.size
if mode in ['random_enlarge', 'enlarge']:
jitter_ratio = abs(ratio)
else:
jitter_ratio = ratio
if mode == 'random_enlarge':
jitter_ratio = np.random.random_sample()*jitter_ratio
elif mode == 'random_move':
# for ratio between (-jitter_ratio, jitter_ratio)
# for sampling the formula is [a,b), b > a,
# random_sample * (b-a) + a
jitter_ratio = np.random.random_sample() * jitter_ratio * 2 - jitter_ratio
jit_boxes = []
for b in bbox:
bbox_width = b[2] - b[0]
bbox_height = b[3] - b[1]
width_change = bbox_width * jitter_ratio
height_change = bbox_height * jitter_ratio
if width_change < height_change:
height_change = width_change
else:
width_change = height_change
if mode in ['enlarge','random_enlarge']:
b[0] = b[0] - width_change //2
b[1] = b[1] - height_change //2
else:
b[0] = b[0] + width_change //2
b[1] = b[1] + height_change //2
b[2] = b[2] + width_change //2
b[3] = b[3] + height_change //2
# Checks to make sure the bbox is not exiting the image boundaries
b = bbox_sanity_check(img, b)
jit_boxes.append(b)
# elif crop_opts['mode'] == 'border_only':
return jit_boxes