原理解释
转载自:https://blog.csdn.net/shuzfan/article/details/52711706
NMS(non maximum suppression),中文名非极大值抑制,在很多计算机视觉任务中都有广泛应用,如:边缘检测、目标检测等。
这里主要以人脸检测中的应用为例,来说明NMS,并给出Matlab和C++示例程序。
人脸检测的一些概念
(1) 绝大部分人脸检测器的核心是分类器,即给定一个尺寸固定图片,分类器判断是或者不是人脸;
**(2)**将分类器进化为检测器的关键是:在原始图像上从多个尺度产生窗口,并resize到固定尺寸,然后送给分类器做判断。最常用的方法是滑动窗口。
以下图为例,由于滑动窗口,同一个人可能有好几个框(每一个框都带有一个分类器得分)
而我们的目标是一个人只保留一个最优的框:
于是我们就要用到非极大值抑制,来抑制那些冗余的框: 抑制的过程是一个迭代-遍历-消除的过程。
**(1)**将所有框的得分排序,选中最高分及其对应的框:
**(2)**遍历其余的框,如果和当前最高分框的重叠面积(IOU)大于一定阈值,我们就将框删除。
**(3)**从未处理的框中继续选一个得分最高的,重复上述过程。
Pytorch实现nms
参考代码1
from torchvision.ops import nms
keep = nms(
torch.from_numpy(roi).cuda(),
torch.from_numpy(score).cuda(),
self.nms_thresh
)
关于NMS的参数说明:
Parameters
----------
boxes : Tensor[N, 4])
boxes to perform NMS on. They
are expected to be in (x1, y1, x2, y2) format
scores : Tensor[N]
scores for each one of the boxes
iou_threshold : float
discards all overlapping
boxes with IoU < iou_threshold
Returns
-------
keep : Tensor
int64 tensor with the indices
of the elements that have been kept
by NMS, sorted in decreasing order of scores
代码参考faster_rcnn
参考代码2
def nms(detections_class,nms_thres=0.7):
max_detections = []
while np.shape(detections_class)[0]:
# 取出这一类置信度最高的,一步一步往下判断,判断重合程度是否大于nms_thres,如果是则去除掉
max_detections.append(np.expand_dims(detections_class[0],0))
if len(detections_class) == 1:
break
ious = bbox_iou(max_detections[-1][:,:4], detections_class[1:,:4])[0]
detections_class = detections_class[1:][ious < nms_thres]
if len(max_detections)==0:
return []
max_detections = np.concatenate(max_detections,axis=0)
return max_detections
参考代码3
# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------
import numpy as np
def py_cpu_nms(dets, thresh):
"""Pure Python NMS baseline."""
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
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:]])
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
ovr = inter / (areas[i] + areas[order[1:]] - inter)
inds = np.where(ovr <= thresh)[0]
order = order[inds + 1]
return keep