Skip to content

Commit 4bd8993

Browse files
committed
2 parents d3aed59 + 69f48b5 commit 4bd8993

File tree

3 files changed

+152
-146
lines changed

3 files changed

+152
-146
lines changed

core/dataset.py

+1-31
Original file line numberDiff line numberDiff line change
@@ -288,36 +288,6 @@ def parse_annotation(self, annotation):
288288
)
289289
return image, bboxes
290290

291-
def bbox_iou(self, boxes1, boxes2):
292-
boxes1 = np.array(boxes1)
293-
boxes2 = np.array(boxes2)
294-
295-
boxes1_area = boxes1[..., 2] * boxes1[..., 3]
296-
boxes2_area = boxes2[..., 2] * boxes2[..., 3]
297-
298-
boxes1 = np.concatenate(
299-
[
300-
boxes1[..., :2] - boxes1[..., 2:] * 0.5,
301-
boxes1[..., :2] + boxes1[..., 2:] * 0.5,
302-
],
303-
axis=-1,
304-
)
305-
boxes2 = np.concatenate(
306-
[
307-
boxes2[..., :2] - boxes2[..., 2:] * 0.5,
308-
boxes2[..., :2] + boxes2[..., 2:] * 0.5,
309-
],
310-
axis=-1,
311-
)
312-
313-
left_up = np.maximum(boxes1[..., :2], boxes2[..., :2])
314-
right_down = np.minimum(boxes1[..., 2:], boxes2[..., 2:])
315-
316-
inter_section = np.maximum(right_down - left_up, 0.0)
317-
inter_area = inter_section[..., 0] * inter_section[..., 1]
318-
union_area = boxes1_area + boxes2_area - inter_area
319-
320-
return inter_area / union_area
321291

322292
def preprocess_true_boxes(self, bboxes):
323293
label = [
@@ -366,7 +336,7 @@ def preprocess_true_boxes(self, bboxes):
366336
)
367337
anchors_xywh[:, 2:4] = self.anchors[i]
368338

369-
iou_scale = self.bbox_iou(
339+
iou_scale = utils.bbox_iou(
370340
bbox_xywh_scaled[i][np.newaxis, :], anchors_xywh
371341
)
372342
iou.append(iou_scale)

core/utils.py

+148-38
Original file line numberDiff line numberDiff line change
@@ -153,59 +153,169 @@ def draw_bbox(image, bboxes, classes=read_class_names(cfg.YOLO.CLASSES), show_la
153153
return image
154154

155155

156+
def bbox_iou(bboxes1, bboxes2):
157+
"""
158+
@param bboxes1: (a, b, ..., 4)
159+
@param bboxes2: (A, B, ..., 4)
160+
x:X is 1:n or n:n or n:1
161+
@return (max(a,A), max(b,B), ...)
162+
ex) (4,):(3,4) -> (3,)
163+
(2,1,4):(2,3,4) -> (2,3)
164+
"""
165+
bboxes1_area = bboxes1[..., 2] * bboxes1[..., 3]
166+
bboxes2_area = bboxes2[..., 2] * bboxes2[..., 3]
167+
168+
bboxes1_coor = tf.concat(
169+
[
170+
bboxes1[..., :2] - bboxes1[..., 2:] * 0.5,
171+
bboxes1[..., :2] + bboxes1[..., 2:] * 0.5,
172+
],
173+
axis=-1,
174+
)
175+
bboxes2_coor = tf.concat(
176+
[
177+
bboxes2[..., :2] - bboxes2[..., 2:] * 0.5,
178+
bboxes2[..., :2] + bboxes2[..., 2:] * 0.5,
179+
],
180+
axis=-1,
181+
)
182+
183+
left_up = tf.maximum(bboxes1_coor[..., :2], bboxes2_coor[..., :2])
184+
right_down = tf.minimum(bboxes1_coor[..., 2:], bboxes2_coor[..., 2:])
185+
186+
inter_section = tf.maximum(right_down - left_up, 0.0)
187+
inter_area = inter_section[..., 0] * inter_section[..., 1]
188+
189+
union_area = bboxes1_area + bboxes2_area - inter_area
190+
191+
iou = tf.math.divide_no_nan(inter_area, union_area)
192+
193+
return iou
194+
195+
196+
def bbox_giou(bboxes1, bboxes2):
197+
"""
198+
Generalized IoU
199+
@param bboxes1: (a, b, ..., 4)
200+
@param bboxes2: (A, B, ..., 4)
201+
x:X is 1:n or n:n or n:1
202+
@return (max(a,A), max(b,B), ...)
203+
ex) (4,):(3,4) -> (3,)
204+
(2,1,4):(2,3,4) -> (2,3)
205+
"""
206+
bboxes1_area = bboxes1[..., 2] * bboxes1[..., 3]
207+
bboxes2_area = bboxes2[..., 2] * bboxes2[..., 3]
208+
209+
bboxes1_coor = tf.concat(
210+
[
211+
bboxes1[..., :2] - bboxes1[..., 2:] * 0.5,
212+
bboxes1[..., :2] + bboxes1[..., 2:] * 0.5,
213+
],
214+
axis=-1,
215+
)
216+
bboxes2_coor = tf.concat(
217+
[
218+
bboxes2[..., :2] - bboxes2[..., 2:] * 0.5,
219+
bboxes2[..., :2] + bboxes2[..., 2:] * 0.5,
220+
],
221+
axis=-1,
222+
)
223+
224+
left_up = tf.maximum(bboxes1_coor[..., :2], bboxes2_coor[..., :2])
225+
right_down = tf.minimum(bboxes1_coor[..., 2:], bboxes2_coor[..., 2:])
226+
227+
inter_section = tf.maximum(right_down - left_up, 0.0)
228+
inter_area = inter_section[..., 0] * inter_section[..., 1]
229+
230+
union_area = bboxes1_area + bboxes2_area - inter_area
231+
232+
iou = tf.math.divide_no_nan(inter_area, union_area)
233+
234+
enclose_left_up = tf.minimum(bboxes1_coor[..., :2], bboxes2_coor[..., :2])
235+
enclose_right_down = tf.maximum(
236+
bboxes1_coor[..., 2:], bboxes2_coor[..., 2:]
237+
)
238+
239+
enclose_section = enclose_right_down - enclose_left_up
240+
enclose_area = enclose_section[..., 0] * enclose_section[..., 1]
241+
242+
giou = iou - tf.math.divide_no_nan(enclose_area - union_area, enclose_area)
243+
244+
return giou
245+
246+
247+
def bbox_ciou(bboxes1, bboxes2):
248+
"""
249+
Complete IoU
250+
@param bboxes1: (a, b, ..., 4)
251+
@param bboxes2: (A, B, ..., 4)
252+
x:X is 1:n or n:n or n:1
253+
@return (max(a,A), max(b,B), ...)
254+
ex) (4,):(3,4) -> (3,)
255+
(2,1,4):(2,3,4) -> (2,3)
256+
"""
257+
bboxes1_area = bboxes1[..., 2] * bboxes1[..., 3]
258+
bboxes2_area = bboxes2[..., 2] * bboxes2[..., 3]
156259

157-
def bboxes_iou(boxes1, boxes2):
260+
bboxes1_coor = tf.concat(
261+
[
262+
bboxes1[..., :2] - bboxes1[..., 2:] * 0.5,
263+
bboxes1[..., :2] + bboxes1[..., 2:] * 0.5,
264+
],
265+
axis=-1,
266+
)
267+
bboxes2_coor = tf.concat(
268+
[
269+
bboxes2[..., :2] - bboxes2[..., 2:] * 0.5,
270+
bboxes2[..., :2] + bboxes2[..., 2:] * 0.5,
271+
],
272+
axis=-1,
273+
)
158274

159-
boxes1 = np.array(boxes1)
160-
boxes2 = np.array(boxes2)
275+
left_up = tf.maximum(bboxes1_coor[..., :2], bboxes2_coor[..., :2])
276+
right_down = tf.minimum(bboxes1_coor[..., 2:], bboxes2_coor[..., 2:])
161277

162-
boxes1_area = (boxes1[..., 2] - boxes1[..., 0]) * (boxes1[..., 3] - boxes1[..., 1])
163-
boxes2_area = (boxes2[..., 2] - boxes2[..., 0]) * (boxes2[..., 3] - boxes2[..., 1])
278+
inter_section = tf.maximum(right_down - left_up, 0.0)
279+
inter_area = inter_section[..., 0] * inter_section[..., 1]
164280

165-
left_up = np.maximum(boxes1[..., :2], boxes2[..., :2])
166-
right_down = np.minimum(boxes1[..., 2:], boxes2[..., 2:])
281+
union_area = bboxes1_area + bboxes2_area - inter_area
167282

168-
inter_section = np.maximum(right_down - left_up, 0.0)
169-
inter_area = inter_section[..., 0] * inter_section[..., 1]
170-
union_area = boxes1_area + boxes2_area - inter_area
171-
ious = np.maximum(1.0 * inter_area / union_area, np.finfo(np.float32).eps)
283+
iou = tf.math.divide_no_nan(inter_area, union_area)
172284

173-
return ious
285+
enclose_left_up = tf.minimum(bboxes1_coor[..., :2], bboxes2_coor[..., :2])
286+
enclose_right_down = tf.maximum(
287+
bboxes1_coor[..., 2:], bboxes2_coor[..., 2:]
288+
)
174289

175-
def bboxes_ciou(boxes1, boxes2):
290+
enclose_section = enclose_right_down - enclose_left_up
176291

177-
boxes1 = np.array(boxes1)
178-
boxes2 = np.array(boxes2)
292+
c_2 = enclose_section[..., 0] ** 2 + enclose_section[..., 1] ** 2
179293

180-
left = np.maximum(boxes1[..., 0], boxes2[..., 0])
181-
up = np.maximum(boxes1[..., 1], boxes2[..., 1])
182-
right = np.maximum(boxes1[..., 2], boxes2[..., 2])
183-
down = np.maximum(boxes1[..., 3], boxes2[..., 3])
294+
center_diagonal = bboxes2[..., :2] - bboxes1[..., :2]
184295

185-
c = (right - left) * (right - left) + (up - down) * (up - down)
186-
iou = bboxes_iou(boxes1, boxes2)
296+
rho_2 = center_diagonal[..., 0] ** 2 + center_diagonal[..., 1] ** 2
187297

188-
ax = (boxes1[..., 0] + boxes1[..., 2]) / 2
189-
ay = (boxes1[..., 1] + boxes1[..., 3]) / 2
190-
bx = (boxes2[..., 0] + boxes2[..., 2]) / 2
191-
by = (boxes2[..., 1] + boxes2[..., 3]) / 2
298+
diou = iou - tf.math.divide_no_nan(rho_2, c_2)
192299

193-
u = (ax - bx) * (ax - bx) + (ay - by) * (ay - by)
194-
d = u/c
300+
v = (
301+
(
302+
tf.math.atan(
303+
tf.math.divide_no_nan(bboxes1[..., 2], bboxes1[..., 3])
304+
)
305+
- tf.math.atan(
306+
tf.math.divide_no_nan(bboxes2[..., 2], bboxes2[..., 3])
307+
)
308+
)
309+
* 2
310+
/ np.pi
311+
) ** 2
195312

196-
aw = boxes1[..., 2] - boxes1[..., 0]
197-
ah = boxes1[..., 3] - boxes1[..., 1]
198-
bw = boxes2[..., 2] - boxes2[..., 0]
199-
bh = boxes2[..., 3] - boxes2[..., 1]
313+
alpha = tf.math.divide_no_nan(v, 1 - iou + v)
200314

201-
ar_gt = bw/bh
202-
ar_pred = aw/ah
315+
ciou = diou - alpha * v
203316

204-
ar_loss = 4 / (np.pi * np.pi) * (np.arctan(ar_gt) - np.arctan(ar_pred)) * (np.arctan(ar_gt) - np.arctan(ar_pred))
205-
alpha = ar_loss / (1 - iou + ar_loss + 0.000001)
206-
ciou_term = d + alpha * ar_loss
317+
return ciou
207318

208-
return iou - ciou_term
209319

210320
def nms(bboxes, iou_threshold, sigma=0.3, method='nms'):
211321
"""
@@ -226,7 +336,7 @@ def nms(bboxes, iou_threshold, sigma=0.3, method='nms'):
226336
best_bbox = cls_bboxes[max_ind]
227337
best_bboxes.append(best_bbox)
228338
cls_bboxes = np.concatenate([cls_bboxes[: max_ind], cls_bboxes[max_ind + 1:]])
229-
iou = bboxes_iou(best_bbox[np.newaxis, :4], cls_bboxes[:, :4])
339+
iou = bbox_iou(best_bbox[np.newaxis, :4], cls_bboxes[:, :4])
230340
weight = np.ones((len(iou),), dtype=np.float32)
231341

232342
assert method in ['nms', 'soft-nms']

core/yolov4.py

+3-77
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ def decode_trt(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=0, XYSCA
246246
return pred_xywh, pred_prob
247247
# return tf.concat([pred_xywh, pred_conf, pred_prob], axis=-1)
248248

249+
249250
def filter_boxes(box_xywh, scores, score_threshold=0.4, input_shape = tf.constant([416,416])):
250251
scores_max = tf.math.reduce_max(scores, axis=-1)
251252

@@ -273,81 +274,6 @@ def filter_boxes(box_xywh, scores, score_threshold=0.4, input_shape = tf.constan
273274
# return tf.concat([boxes, pred_conf], axis=-1)
274275
return (boxes, pred_conf)
275276

276-
def bbox_iou(boxes1, boxes2):
277-
278-
boxes1_area = boxes1[..., 2] * boxes1[..., 3]
279-
boxes2_area = boxes2[..., 2] * boxes2[..., 3]
280-
281-
boxes1_coor = tf.concat([boxes1[..., :2] - boxes1[..., 2:] * 0.5,
282-
boxes1[..., :2] + boxes1[..., 2:] * 0.5], axis=-1)
283-
boxes2_coor = tf.concat([boxes2[..., :2] - boxes2[..., 2:] * 0.5,
284-
boxes2[..., :2] + boxes2[..., 2:] * 0.5], axis=-1)
285-
286-
left_up = tf.maximum(boxes1_coor[..., :2], boxes1_coor[..., :2])
287-
right_down = tf.minimum(boxes2_coor[..., 2:], boxes2_coor[..., 2:])
288-
289-
inter_section = tf.maximum(right_down - left_up, 0.0)
290-
inter_area = inter_section[..., 0] * inter_section[..., 1]
291-
union_area = boxes1_area + boxes2_area - inter_area
292-
293-
return 1.0 * inter_area / union_area
294-
295-
def bbox_ciou(boxes1, boxes2):
296-
boxes1_coor = tf.concat([boxes1[..., :2] - boxes1[..., 2:] * 0.5,
297-
boxes1[..., :2] + boxes1[..., 2:] * 0.5], axis=-1)
298-
boxes2_coor = tf.concat([boxes2[..., :2] - boxes2[..., 2:] * 0.5,
299-
boxes2[..., :2] + boxes2[..., 2:] * 0.5], axis=-1)
300-
301-
left = tf.maximum(boxes1_coor[..., 0], boxes2_coor[..., 0])
302-
up = tf.maximum(boxes1_coor[..., 1], boxes2_coor[..., 1])
303-
right = tf.maximum(boxes1_coor[..., 2], boxes2_coor[..., 2])
304-
down = tf.maximum(boxes1_coor[..., 3], boxes2_coor[..., 3])
305-
306-
c = (right - left) * (right - left) + (up - down) * (up - down)
307-
iou = bbox_iou(boxes1, boxes2)
308-
309-
u = (boxes1[..., 0] - boxes2[..., 0]) * (boxes1[..., 0] - boxes2[..., 0]) + (boxes1[..., 1] - boxes2[..., 1]) * (boxes1[..., 1] - boxes2[..., 1])
310-
d = u / c
311-
312-
ar_gt = boxes2[..., 2] / boxes2[..., 3]
313-
ar_pred = boxes1[..., 2] / boxes1[..., 3]
314-
315-
ar_loss = 4 / (np.pi * np.pi) * (tf.atan(ar_gt) - tf.atan(ar_pred)) * (tf.atan(ar_gt) - tf.atan(ar_pred))
316-
alpha = ar_loss / (1 - iou + ar_loss + 0.000001)
317-
ciou_term = d + alpha * ar_loss
318-
319-
return iou - ciou_term
320-
321-
def bbox_giou(boxes1, boxes2):
322-
323-
boxes1 = tf.concat([boxes1[..., :2] - boxes1[..., 2:] * 0.5,
324-
boxes1[..., :2] + boxes1[..., 2:] * 0.5], axis=-1)
325-
boxes2 = tf.concat([boxes2[..., :2] - boxes2[..., 2:] * 0.5,
326-
boxes2[..., :2] + boxes2[..., 2:] * 0.5], axis=-1)
327-
328-
boxes1 = tf.concat([tf.minimum(boxes1[..., :2], boxes1[..., 2:]),
329-
tf.maximum(boxes1[..., :2], boxes1[..., 2:])], axis=-1)
330-
boxes2 = tf.concat([tf.minimum(boxes2[..., :2], boxes2[..., 2:]),
331-
tf.maximum(boxes2[..., :2], boxes2[..., 2:])], axis=-1)
332-
333-
boxes1_area = (boxes1[..., 2] - boxes1[..., 0]) * (boxes1[..., 3] - boxes1[..., 1])
334-
boxes2_area = (boxes2[..., 2] - boxes2[..., 0]) * (boxes2[..., 3] - boxes2[..., 1])
335-
336-
left_up = tf.maximum(boxes1[..., :2], boxes2[..., :2])
337-
right_down = tf.minimum(boxes1[..., 2:], boxes2[..., 2:])
338-
339-
inter_section = tf.maximum(right_down - left_up, 0.0)
340-
inter_area = inter_section[..., 0] * inter_section[..., 1]
341-
union_area = boxes1_area + boxes2_area - inter_area
342-
iou = inter_area / union_area
343-
344-
enclose_left_up = tf.minimum(boxes1[..., :2], boxes2[..., :2])
345-
enclose_right_down = tf.maximum(boxes1[..., 2:], boxes2[..., 2:])
346-
enclose = tf.maximum(enclose_right_down - enclose_left_up, 0.0)
347-
enclose_area = enclose[..., 0] * enclose[..., 1]
348-
giou = iou - 1.0 * (enclose_area - union_area) / enclose_area
349-
350-
return giou
351277

352278
def compute_loss(pred, conv, label, bboxes, STRIDES, NUM_CLASS, IOU_LOSS_THRESH, i=0):
353279
conv_shape = tf.shape(conv)
@@ -366,13 +292,13 @@ def compute_loss(pred, conv, label, bboxes, STRIDES, NUM_CLASS, IOU_LOSS_THRESH,
366292
respond_bbox = label[:, :, :, :, 4:5]
367293
label_prob = label[:, :, :, :, 5:]
368294

369-
giou = tf.expand_dims(bbox_giou(pred_xywh, label_xywh), axis=-1)
295+
giou = tf.expand_dims(utils.bbox_giou(pred_xywh, label_xywh), axis=-1)
370296
input_size = tf.cast(input_size, tf.float32)
371297

372298
bbox_loss_scale = 2.0 - 1.0 * label_xywh[:, :, :, :, 2:3] * label_xywh[:, :, :, :, 3:4] / (input_size ** 2)
373299
giou_loss = respond_bbox * bbox_loss_scale * (1- giou)
374300

375-
iou = bbox_iou(pred_xywh[:, :, :, :, np.newaxis, :], bboxes[:, np.newaxis, np.newaxis, np.newaxis, :, :])
301+
iou = utils.bbox_iou(pred_xywh[:, :, :, :, np.newaxis, :], bboxes[:, np.newaxis, np.newaxis, np.newaxis, :, :])
376302
max_iou = tf.expand_dims(tf.reduce_max(iou, axis=-1), axis=-1)
377303

378304
respond_bgd = (1.0 - respond_bbox) * tf.cast( max_iou < IOU_LOSS_THRESH, tf.float32 )

0 commit comments

Comments
 (0)