非极大值抑制(NMS)即抑制不是极大值的元素,搜索局部的极大值。这个局部代表的是一个邻域,邻域有两个参数可变,一是邻域的维数,二是邻域的大小。例如在行人检测中,滑动窗口提取特征,经分类器分类识别后,每个窗口都会得到一个score。但是滑动窗口会导致很多窗口与其他窗口存在包含或者大部分交叉的情况。这时就需要用到NMS来选取那些邻域里score最高(行人的概率最大),抑制那些score较低的窗口。
算法思想如下:
设定阈值,找到最大分类概率的检测框F,从它开始,其他框中与F重复度IOU > 阈值:舍去,标记并保留F。
—— 从剩下的检测框中再找最大分类概率的检测框E,其他框中与E重复度IOU > 阈值:舍去,标记并保留E。
—— 如此操作完剩下的框,找到所有被保留下来的检测框。
Fast R-CNN关于NMS的源代码(python版),Faster R-CNN也是用的这段代码。
# --------------------------------------------------------
# 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
参考:https://www.julyedu.com/question/big/kp_id/26/ques_id/2141
代码参考:https://blog.csdn.net/leviopku/article/details/80886386