基本思路:从待检测目标中先按照分类置信度,找一个最可信的框。然后判断其他框和它的交并比(IoU),如果大于阈值TH,说明相似,抑制掉就好了。

算法:1.按照置信度排序 2.判断其他框和得分最高的框的IoU,大于阈值则剔除得分较小的建议框 3.从没有处理的框中继续选择一个得分最高的,重复上述过程。 4.遍历所有的建议框,即所有物体种类都做一遍非极大值抑制。

注意在faster rcnn中有两个阈值0.7,第一次是判断正负样本的时候,大于0.7标为正样本,小于0.3为负样本(背景),中间的样本舍弃。 第二个是在nms中,用来判断和得分最高框的相似度,剔除相似样本。

1.局部最大搜索

目标检测问题的老大难问题之一就是如何提高召回率(所有标注的真实边界框有多少被预测出来了)。

  目标检测之非极大值抑制-编程知识网       目标检测之非极大值抑制-编程知识网即recall=正检/(正检+未检)

这就导致最后输出的边界框数量往往远大于实际数量,而这些模型的输出边界框往往是堆叠在一起的。因此,我们需要NMS从堆叠的边框中挑出最好的那个。

  目标检测之非极大值抑制-编程知识网

2.何时使用NMS? When NMS?

回顾我在R-CNN中提到的流程:

  1. 提议区域(选择性搜索)
  2. 提取特征
  3. 目标分类
  4. 回归边框

NMS使用在4. 回归边框之后,即所有的框已经被分类且精修了位置。且所有区域提议的预测结果已经由置信度与阈值初步筛选之后。

3. 如何非极大值抑制 How NMS?

一维简单例子

由于重点是二维(目标检测)的实现,因此一维只放出伪代码便于理解。

判断一维数组I[W]的元素I[i](2<=i<=W-1)是否为局部极大值,即大于其左邻元素I[i-1]和右邻元素I[i+1]

算法流程如下图所示:

  

目标检测之非极大值抑制-编程知识网

 

算法流程3-5行判断当前元素是否大于其左邻与右邻元素,如符合条件,该元素即为极大值点。对于极大值点I[i],已知I[i]>I[i+1],故无需对i+1位置元素做进一步处理,直接跳至i+2位置,对应算法流程第12行。

若元素I[i]不满足算法流程第3行判断条件,将其右邻I[i+1]作为极大值候选,对应算法流程第7行。采用单调递增的方式向右查找,直至找到满足I[i]>I[i+1]的元素,若i<=W-1,该点即为极大值点,对应算法流程第10-11行。

推广至目标检测

首先,根据之前分析确认NMS的前提,输入与输出。

使用前提

目标检测模型已经完成了整个前向计算,并给出所有可能的边界框(位置已精修)。

算法输入

算法对一幅图产生的所有的候选框,每个框有坐标与对应的打分(置信度)。

如一组5维数组:

  • 每个组表明一个边框,组数是待处理边框数
  • 4个数表示框的坐标:X_max,X_min,Y_max,Y_min
  • 1个数表示对应分类下的置信度

注意:每次输入的不是一张图所有的边框,而是一张图中属于某个类的所有边框(因此极端情况下,若所有框的都被判断为背景类,则NMS不执行;反之若存在物体类边框,那么有多少类物体则分别执行多少次NMS)。

除此之外还有一个自行设置的参数:阈值 TH。

算法输出

输入的一个子集,同样是一组5维数组,表示筛选后的边界框。

算法流程

    • 将所有的框按类别划分,并剔除背景类,因为无需NMS。
    • 对每个物体类中的边界框(B_BOX),按照分类置信度降序排列。
    • 在某一类中,选择置信度最高的边界框B_BOX1,将B_BOX1从输入列表中去除,并加入输出列表。
    • 逐个计算B_BOX1与其余B_BOX2的交并比IoU,若IoU(B_BOX1,B_BOX2) > 阈值TH,则在输入去除B_BOX2。
    • 重复步骤3~4,直到输入列表为空,完成一个物体类的遍历。
    • 重复2~5,直到所有物体类的NMS处理完成。
    • 输出列表,算法结束

代码实现及参考:https://www.zhihu.com/question/39405815/answer/791341975