fix(models/utils.py): refactor nms() implmentation, same with torchvision.ops.nms

pull/192/head
zjykzj 11 months ago
parent 6c39635155
commit 5b628bcb14
  1. 92
      models/utils.py

@ -127,50 +127,54 @@ def batched_nms(boxes: ndarray,
return keep_boxes, keep_scores, keep_labels return keep_boxes, keep_scores, keep_labels
def nms(boxes: ndarray, def nms(bboxes: ndarray, scores: ndarray, iou_thresh: float):
scores: ndarray, """
iou_thres: float = 0.65, Performs non-maximum suppression (NMS) on the boxes according
conf_thres: float = 0.25): to their intersection-over-union (IoU).
labels = np.argmax(scores, axis=-1)
scores = np.max(scores, axis=-1) NMS iteratively removes lower scoring boxes which have an
IoU greater than iou_threshold with another (higher scoring)
cand = scores > conf_thres box.
boxes = boxes[cand]
scores = scores[cand] If multiple boxes have the exact same score and satisfy the IoU
labels = labels[cand] criterion with respect to a reference box, the selected box is
not guaranteed to be the same between CPU and GPU. This is similar
keep_boxes = [] to the behavior of argsort in PyTorch when repeated values are present.
keep_scores = []
keep_labels = [] Args:
bboxes (ndarray[N, 4])): boxes to perform NMS on. They
idxs = scores.argsort() are expected to be in ``(x1, y1, x2, y2)`` format with ``0 <= x1 < x2`` and
while idxs.size > 0: ``0 <= y1 < y2``.
max_score_index = idxs[-1] scores (ndarray[N]): scores for each one of the boxes
max_box = boxes[max_score_index:max_score_index + 1] iou_thresh (float): discards all overlapping boxes with IoU > iou_threshold
max_score = scores[max_score_index:max_score_index + 1]
max_label = np.array([labels[max_score_index]], dtype=np.int32) Returns:
keep_boxes.append(max_box) ndarray: int64 tensor with the indices of the elements that have been kept
keep_scores.append(max_score) by NMS, sorted in decreasing order of scores
keep_labels.append(max_label) """
if idxs.size == 1: x1 = bboxes[:, 0]
break y1 = bboxes[:, 1]
idxs = idxs[:-1] x2 = bboxes[:, 2]
other_boxes = boxes[idxs] y2 = bboxes[:, 3]
ious = bbox_iou(max_box, other_boxes) areas = (y2 - y1) * (x2 - x1)
iou_mask = ious < iou_thres
idxs = idxs[iou_mask] result = []
index = scores.argsort()[::-1]
if len(keep_boxes) == 0: while index.size > 0:
keep_boxes = np.empty((0, 4), dtype=np.float32) i = index[0]
keep_scores = np.empty((0, ), dtype=np.float32) result.append(i)
keep_labels = np.empty((0, ), dtype=np.float32)
x11 = np.maximum(x1[i], x1[index[1:]])
else: y11 = np.maximum(y1[i], y1[index[1:]])
keep_boxes = np.concatenate(keep_boxes, axis=0) x22 = np.minimum(x2[i], x2[index[1:]])
keep_scores = np.concatenate(keep_scores, axis=0) y22 = np.minimum(y2[i], y2[index[1:]])
keep_labels = np.concatenate(keep_labels, axis=0) w = np.maximum(0, x22 - x11 + 1)
h = np.maximum(0, y22 - y11 + 1)
return keep_boxes, keep_scores, keep_labels overlaps = w * h
ious = overlaps / (areas[i] + areas[index[1:]] - overlaps)
idx = np.where(ious <= iou_thresh)[0]
index = index[idx + 1]
return np.array(result, dtype=int)
def path_to_list(images_path: Union[str, Path]) -> List: def path_to_list(images_path: Union[str, Path]) -> List:

Loading…
Cancel
Save