- 计算机视觉任务中经常遇到,比如进行目标检测,如果给出了很多可能的提议,就需要选择一个最佳的,否则会有很多overlap。
- 本文首先实现一个三邻域一维NMS,帮助算法理解。然后给出一个根据bbox之间IoU为准则的图像目标检测NMS应用案例.
- 一维NMS代码帮助理解
# 非极大值抑制
"""
3邻域内,如果是最大的就输出索引 且跳转到i+2
如果不是则继续向前爬动,直到当前的大于下一个(且不超出列表长度)
"""
a = [1, 2, 2, 3, 2, 1, 1, 4, 5, 6, 6, 3, 5]
len_a = len(a)
i = 1 # 开始点
MaxIdx = []
while i < len_a - 1:
if a[i] > a[i + 1]:
if a[i] >= a[i - 1]:
MaxIdx.append(i)
else: # a[i] < a[i+1]
i += 1 # 先跳一个格试探一下 不加也没关系
while i < len_a - 1 and a[i] <= a[i + 1]: # 向前爬 条件位置不能互换
i += 1
if i < len_a: # 这时候 a[i] > a[i+1] && a[i] < a[i+1]
MaxIdx.append(i)
i += 2 # 跳两格
print(MaxIdx)
给出处理结果:
可见,非极大值数据被设定为0
-
IoU准则的NMS应用 YOLO场景
简单来讲,对于bbox的NMS,只是把每个bbox对应的类别置信度排序后,放到上面的列表里面去,根据置信度大小,计算相对IoU,进行一维NMS.如果与局部极大置信度所对应的bbox求IoU>0.5,就舍弃这个bbox,作为结果,其置信度被设定为0,否则保留当前bbox对应的类别置信度.
参考一个ppt[3](1)将所有的bbox对应的类别置信度进行排序.因为YOLO里面一个边框对应一个唯一的类别置信度,可以一对一映射.如下如
(2)执行NMS,每次执行都有两种情况.
a. 与被比较的局部极大值对应的bbox IoU>0.5 (这个0.5是超参数,可以调节)
b. 与被比较的局部极大值对应的bbox IoU<0.5
对于情况a,反过来把当前置信度设置为0
对于情况b,保持当前置信度不变.下图可见,置信度排名第二的非零bbox与排名第一的bbox之间IoU>0.5,此时反过来把这个置信度设置为0.此处要强调非零或者小于某一个阈值,是为了减少IoU计算量.如果预测器本来就认为这里没有什么东西,那就不需要计算IoU了,置信度保持为0不变.
下图表明把这个置信度设定为0
还是在这个邻域里面,下图表明IoU小于设定阈值的情况,置信度不变
(3)继续向前移动,对邻域内的bbox重复刚才的操作
(4)如果置信度大于零,就绘制bbox,否则跳过这一个bbox!
参考
[1] https://www.cnblogs.com/liekkas0626/p/5219244.html
[2] 图像中的NMS
[3]https://docs.google.com/presentation/d/1aeRvtKG21KHdD5lg6Hgyhx5rPq_ZOsGjG5rJ1HP7BbA/pub?start=false&loop=false&delayms=3000&slide=id.g137784ab86_4_5070
2020.0713更新
本节给出了浅显易懂的NMS代码实现,并通过YOLO NMS案例理解在目标检测bbox过滤中的应用.