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