Skip to content

Commit 63b59de

Browse files
committed
Added image padding to ONNX inference
1 parent 03f780a commit 63b59de

File tree

1 file changed

+50
-16
lines changed

1 file changed

+50
-16
lines changed

deploy/onnx_inference.py

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,14 @@ def main(args):
4545

4646
# Image preprocessing
4747
img_path = args.image # TODO: make sure the image is in img_path
48-
image = Image.open(img_path)
49-
orig_w, orig_h = image.size # PIL is (width, height)
50-
img = image.resize((model_size, model_size))
48+
# image = Image.open(img_path)
49+
img = cv2.imread(img_path) # read as numpy
50+
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
51+
orig_h, orig_w = img.shape[:2] # PIL is (width, height)
5152
x = np.array(img, dtype='float32')
5253
x /= 255.
54+
x, pad = pad_image(x) # use when the model has been trained on padded data
55+
x = cv2.resize(x, dsize=((model_size, model_size)), interpolation=cv2.INTER_CUBIC)
5356
x = np.expand_dims(x, 0)
5457

5558
# Check model
@@ -81,20 +84,25 @@ def main(args):
8184
end = timer()
8285
print('{} seconds for inference with ONNX runtime'.format((end-start)))
8386

87+
## Subtract padding offset
88+
if orig_h < orig_w:
89+
out_boxes[:,[0,2]] -= pad*(model_size/orig_w) / 2.
90+
elif orig_h > orig_w:
91+
out_boxes[:,[1,3]] -= pad*(model_size/orig_h) / 2.
92+
else:
93+
pass # square image
94+
out_boxes = np.clip(out_boxes, 0.0, model_size)
8495
# Resize to original dimensions
8596
out_boxes[:,[0,2]] *= orig_h // model_size
8697
out_boxes[:,[1,3]] *= orig_w // model_size
87-
88-
# Print
89-
for i, c in enumerate(out_classes):
90-
score = out_scores[i]
91-
box = out_boxes[i]
92-
print(box, ' ', class_names[c])
98+
99+
# Read in as PIL format
100+
pil_image = Image.open(img_path)
93101

94102
# Formatting
95-
thickness = (image.size[0] + image.size[1]) // 300
103+
thickness = (pil_image.size[0] + pil_image.size[1]) // 300
96104
font = ImageFont.truetype(font='font/FiraMono-Medium.otf',
97-
size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32'))
105+
size=np.floor(3e-2 * pil_image.size[1] + 0.5).astype('int32'))
98106
# Generate colors for drawing bounding boxes.
99107
hsv_tuples = [(x / len(class_names), 1., 1.)
100108
for x in range(len(class_names))]
@@ -111,14 +119,14 @@ def main(args):
111119

112120
if score > args.score:
113121
label = '{} {:.2f}'.format(predicted_class, score)
114-
draw = ImageDraw.Draw(image)
122+
draw = ImageDraw.Draw(pil_image)
115123
label_size = draw.textsize(label, font)
116124

117125
top, left, bottom, right = box
118126
top = max(0, np.floor(top + 0.5).astype('int32'))
119127
left = max(0, np.floor(left + 0.5).astype('int32'))
120-
bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32'))
121-
right = min(image.size[0], np.floor(right + 0.5).astype('int32'))
128+
bottom = min(pil_image.size[1], np.floor(bottom + 0.5).astype('int32'))
129+
right = min(pil_image.size[0], np.floor(right + 0.5).astype('int32'))
122130
print(label, (left, top), (right, bottom))
123131

124132
if top - label_size[1] >= 0:
@@ -139,8 +147,8 @@ def main(args):
139147

140148
# Save image w/ bbox
141149
suffix = '.'+img_path.split('.')[-1]
142-
save_path = image.save(img_path.replace(suffix, '_onnx_out.'+suffix))
143-
image.show()
150+
save_path = pil_image.save(img_path.replace(suffix, '_onnx_out.'+suffix))
151+
pil_image.show()
144152

145153
def get_class(classes_path):
146154
classes_path = os.path.expanduser(classes_path)
@@ -156,6 +164,32 @@ def get_anchors(anchors_path):
156164
anchors = [float(x) for x in anchors.split(',')]
157165
return np.array(anchors).reshape(-1, 2)
158166

167+
def pad_image(np_img):
168+
"""Use numpy operations to add padding around an image in
169+
numpy format (an array of rank 3 - so 3 channels) in order
170+
to create a square image.
171+
"""
172+
h, w, c = np_img.shape[0:3]
173+
side_len = max(h, w)
174+
# Create our square "palette" or area upon which the image data is placed
175+
# Make it kinda grey
176+
new_np_img = np.ones(side_len * side_len * c, dtype='float32').reshape(side_len,
177+
side_len, c) / 2.0
178+
179+
if h > w:
180+
for i in range(c):
181+
old_patch = np_img[:, :, i]
182+
pad = (side_len - w)//2
183+
new_np_img[:, pad:(pad + w), i] = old_patch
184+
elif w > h:
185+
for i in range(c):
186+
old_patch = np_img[:, :, i]
187+
pad = (side_len - h)//2
188+
new_np_img[pad:(pad + h), :, i] = old_patch
189+
else:
190+
return np_img, 0
191+
return new_np_img, pad
192+
159193
def yolo_head(feats, anchors, num_classes, input_shape, calc_loss=False):
160194
"""Convert final layer features to bounding box parameters."""
161195
feats = K.constant(feats)

0 commit comments

Comments
 (0)