Source code for otx.api.utils.nms
"""NMS Module."""
# Copyright (C) 2021-2022 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
import numpy as np
[docs]
def nms(boxes, scores, thresh):
"""Adapted NMS implementation from OMZ: model_zoo/model_api/models/utils.py#L181."""
# pylint: disable=too-many-locals
x1, y1, x2, y2 = boxes.T
areas = (x2 - x1) * (y2 - y1)
order = scores.argsort()[::-1]
keep = []
while order.size > 0:
i = order[0]
keep.append(i)
xx1 = np.maximum(x1[i], x1[order[1:]])
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
width = np.maximum(0.0, xx2 - xx1)
height = np.maximum(0.0, yy2 - yy1)
intersection = width * height
union = areas[i] + areas[order[1:]] - intersection
overlap = np.divide(
intersection,
union,
out=np.zeros_like(intersection, dtype=float),
where=union != 0,
)
order = order[np.where(overlap <= thresh)[0] + 1]
return keep
[docs]
def multiclass_nms(
detections: np.ndarray,
iou_threshold=0.45,
max_num=200,
):
"""Multi-class NMS.
strategy: in order to perform NMS independently per class,
we add an offset to all the boxes. The offset is dependent
only on the class idx, and is large enough so that boxes
from different classes do not overlap
Args:
detections (np.ndarray): labels, scores and boxes
iou_threshold (float, optional): IoU threshold. Defaults to 0.45.
max_num (int, optional): Max number of objects filter. Defaults to 200.
Returns:
tuple: (dets, indices), Dets are boxes with scores. Indices are indices of kept boxes.
"""
labels = detections[:, 0]
scores = detections[:, 1]
boxes = detections[:, 2:]
max_coordinate = boxes.max()
offsets = labels.astype(boxes.dtype) * (max_coordinate + 1)
boxes_for_nms = boxes + offsets[:, None]
keep = nms(boxes_for_nms, scores, iou_threshold)
if max_num > 0:
keep = keep[:max_num]
keep = np.array(keep)
det = detections[keep]
return det, keep