11from collections import defaultdict
22from typing import Any , Dict , List , Tuple
33
4- import ensemble_boxes
54import numpy as np
65from loguru import logger
6+ from numba import jit
77
88from pyodi .core .boxes import coco_to_corners , corners_to_coco , denormalize , normalize
99
1010
11+ @jit (nopython = True )
12+ def nms (dets : np .ndarray , scores : np .ndarray , iou_thr : float ) -> np .ndarray :
13+ """Non Maximum supression algorithm from https://github.com/ZFTurbo/Weighted-Boxes-Fusion/blob/master/ensemble_boxes/ensemble_boxes_nms.py.
14+
15+ Args:
16+ dets: Array of predictions in corner format.
17+ scores: Array of scores for each prediction.
18+ iou_thr: None of the filtered predictions will have an iou above `iou_thr`
19+ to any other.
20+
21+ Returns:
22+ List of filtered predictions in COCO format.
23+
24+ """
25+ x1 = dets [:, 0 ]
26+ y1 = dets [:, 1 ]
27+ x2 = dets [:, 2 ]
28+ y2 = dets [:, 3 ]
29+
30+ areas = (x2 - x1 ) * (y2 - y1 )
31+ order = scores .argsort ()[::- 1 ]
32+
33+ keep = []
34+ while order .size > 0 :
35+ i = order [0 ]
36+ keep .append (i )
37+ xx1 = np .maximum (x1 [i ], x1 [order [1 :]])
38+ yy1 = np .maximum (y1 [i ], y1 [order [1 :]])
39+ xx2 = np .minimum (x2 [i ], x2 [order [1 :]])
40+ yy2 = np .minimum (y2 [i ], y2 [order [1 :]])
41+
42+ w = np .maximum (0.0 , xx2 - xx1 )
43+ h = np .maximum (0.0 , yy2 - yy1 )
44+ inter = w * h
45+ ovr = inter / (areas [i ] + areas [order [1 :]] - inter )
46+ inds = np .where (ovr <= iou_thr )[0 ]
47+ order = order [inds + 1 ]
48+
49+ return keep
50+
51+
1152def nms_predictions (
12- predictions : List [Dict [Any , Any ]],
13- nms_mode : str = "nms" ,
14- score_thr : float = 0.0 ,
15- iou_thr : float = 0.5 ,
53+ predictions : List [Dict [Any , Any ]], score_thr : float = 0.0 , iou_thr : float = 0.5 ,
1654) -> List [Dict [Any , Any ]]:
1755 """Apply Non Maximum supression to all the images in a COCO `predictions` list.
1856
1957 Args:
2058 predictions: List of predictions in COCO format.
21- nms_mode: Non Maximum Supression mode. Defaults to "nms".
2259 score_thr: Predictions below `score_thr` will be filtered. Defaults to 0.0.
2360 iou_thr: None of the filtered predictions will have an iou above `iou_thr`
2461 to any other. Defaults to 0.5.
@@ -27,7 +64,6 @@ def nms_predictions(
2764 List of filtered predictions in COCO format.
2865
2966 """
30- nms = getattr (ensemble_boxes , nms_mode )
3167 new_predictions = []
3268 image_id_to_all_boxes : Dict [str , List [List [float ]]] = defaultdict (list )
3369 image_id_to_shape : Dict [str , Tuple [int , int ]] = dict ()
@@ -51,9 +87,10 @@ def nms_predictions(
5187 boxes = normalize (coco_to_corners (boxes ), image_width , image_height )
5288
5389 logger .info (f"Before nms: { boxes .shape } " )
54- boxes , scores , categories = nms (
55- [boxes ], [scores ], [categories ], iou_thr = iou_thr
56- )
90+ keep = nms (boxes , scores , iou_thr = iou_thr )
91+ # Filter out predictions
92+ boxes , categories , scores = boxes [keep ], categories [keep ], scores [keep ]
93+
5794 logger .info (f"After nms: { boxes .shape } " )
5895
5996 logger .info (f"Before score threshold: { boxes .shape } " )
0 commit comments