@@ -153,59 +153,169 @@ def draw_bbox(image, bboxes, classes=read_class_names(cfg.YOLO.CLASSES), show_la
153
153
return image
154
154
155
155
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 ]
156
259
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
+ )
158
274
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 :] )
161
277
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 ]
164
280
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
167
282
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 )
172
284
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
+ )
174
289
175
- def bboxes_ciou ( boxes1 , boxes2 ):
290
+ enclose_section = enclose_right_down - enclose_left_up
176
291
177
- boxes1 = np .array (boxes1 )
178
- boxes2 = np .array (boxes2 )
292
+ c_2 = enclose_section [..., 0 ] ** 2 + enclose_section [..., 1 ] ** 2
179
293
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 ]
184
295
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
187
297
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 )
192
299
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
195
312
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 )
200
314
201
- ar_gt = bw / bh
202
- ar_pred = aw / ah
315
+ ciou = diou - alpha * v
203
316
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
207
318
208
- return iou - ciou_term
209
319
210
320
def nms (bboxes , iou_threshold , sigma = 0.3 , method = 'nms' ):
211
321
"""
@@ -226,7 +336,7 @@ def nms(bboxes, iou_threshold, sigma=0.3, method='nms'):
226
336
best_bbox = cls_bboxes [max_ind ]
227
337
best_bboxes .append (best_bbox )
228
338
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 ])
230
340
weight = np .ones ((len (iou ),), dtype = np .float32 )
231
341
232
342
assert method in ['nms' , 'soft-nms' ]
0 commit comments