0. 前言
- NMS,全称 non-maximum suppression,中文翻译是非极大值抑制。
1. NMS的引入与基本流程
- 参考资料:
1.1. 引入
- 检测模型获取得到的检测框一般较多,同一物体很可能有多个框选中,所以就需要筛选一些。
- 筛选的方法主要有两种,一种是通过增加 score 阈值,另一种就是NMS。
- NMS的总体思路就是 从一些类似的候选框中选择一个最好的。
- 类似的候选框指的是两个bbox的IOU大于某一阈值。
- 好的候选框指的是score高的。
- 检测的基本流程
- 参考本文的配图(这张图多个博客引用了,我也不知道最开始从哪里引用的):
- 第一步:对每一类型,根据socre降序排列所有候选框。
- 第二步:以第一步结果作为输入,依次遍历每个候选框,若后续候选框中有与当前候选框的IOU大于阈值,则剔除对应后续候选框中的对象。重复该操作,直到遍历过所有候选框。
- 第三步:剩下的候选框,就是NMS的结果。
- 参考本文的配图(这张图多个博客引用了,我也不知道最开始从哪里引用的):
1.2. 基本实现
- 参考:rgbirshick/py-faster-rcnn: lib/nms,即RGB大佬的NMS实现
- 基本流程
- 第一步:将检测出的bbox按照cls score划分为若干集合。
- 第二步:对每个集合,按照cls score排列,得到一个降序的list_k。
- 第三步:对每个list_k,从top 1 cls score开始,计算当前bbox_a与其他bbox_b的IOU,若IOU大于阈值则去除bbox_b,且最终保留bbox_a,并从list_k中剔除。
- 第四步:从list_k中选择剩余的top 1bbox,按照
第三步
的方法继续进行筛选。 - 第五步:对所有list_k进行相同的操作。
- 源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23def nms(dets, thresh):
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
1.3. 不使用排序实现
- 本文介绍了不使用排序实现NMS的过程。
- 其实本质上来说,NMS做的就是去掉重复的候选框。
- 基本步骤:
- 第一步:依次遍历所有候选框。
- 第二步:计算当前候选框(记作候选框A)与剩下候选框的IOU,选出IOU大于阈值的候选框集合(记作候选框集合B)。
- 第三步:如果候选框A的score比候选框集合B中所有的都大,那就保留候选框A,并去掉所有候选框集合B中元素。
- 第四步:若候选框集合B中有元素的score大于候选框A的score,则去除候选框A。
- 第一步:依次遍历所有候选框。
2. Soft NMS
- 参考资料:
2.1. 引入与理解
- NMS存在一个问题,如果两个同类物体离得太近(即两个同类物体的 gt bbox 本身的IOU就大于阈值),那就只能检测到一个物体。
- 理解:
- 普通NMS的做法是,当两个bbox的IOU大于一定阈值,则会过滤掉score较小的bbox。
- Soft NMS的做法是,当两个bbox的IOU大于一定阈值,score较大的bbox的score保持不变,较小的bbox的score会根据一定的方式减少。
- 普通NMS可以理解为:
- Soft NMS 可以理解为:
- 当然,$s_i(1-iou(M, b_i))$ 也可以通过别的方式
- 当然,$s_i(1-iou(M, b_i))$ 也可以通过别的方式
2.2. 伪代码
- 引用了这篇文章中的配图
- 注意,我觉得伪代码里少了一步,就是根据socre threshold来筛选bbox(否则感觉并没有筛选bbox,而只是修改了score)