NMS原理
Non-Maximum-Suppression(非极大值抑制):
当两个box空间位置非常接近,就以score更高的那个作为基准,看IOU即重合度如何,如果与其重合度超过阈值,就抑制score更小的box,因为没有必要输出两个接近的box,只保留score大的就可以了。
应用:在目标检测过程中,(Faster-RCNN / YOLOv2)采用NMS来消除冗余的boxes,最终只留下最好的较少的box。
过程:
1 将各组box按照score降序排列
2 从score最大值开始,置为当前box,保存idex,然后依次遍历后面的box,计算与当前box的IOU值,若大于阈值,则抑制,不会输出
3 完成一轮遍历后,继续选择下一个非抑制的box作为当前box,重复步骤2
4 返回没有被抑制的index即符合条件的box
代码实现(被问过)
def NMS(dects,threshhold):
"""
detcs:二维数组(n_samples,5)
5列:x1,y1,x2,y2,score
threshhold: IOU阈值
"""
x1=dects[:,0]
y1=dects[:,1]
x2=dects[:,2]
y2=dects[:,3]
score=dects[:,4]
ndects=dects.shape[0]#box的数量
area=(x2-x1+1)*(y2-y1+1)
order=score.argsort()[::-1] #score从大到小排列的indexs,一维数组
keep=[] #保存符合条件的index
suppressed=np.array([0]*ndects) #初始化为0,若大于threshhold,变为1,表示被抑制
for _i in range(ndects):
i=order[_i] #从得分最高的开始遍历
if suppressed[i]==1:
continue
keep.append(i)
for _j in range(i+1,ndects):
j=order[_j]
if suppressed[j]==1: #若已经被抑制,跳过
continue
xx1=np.max(x1[i],x1[j])#求两个box的交集面积interface
yy1=np.max(y1[i],y1j])
xx2=np.min(x2[i],x2[j])
yy2=np.min(y2[i],y2[j])
w=np.max(0,xx2-xx1+1)
h=np.max(0,yy2-yy1+1)
interface=w*h
overlap=interface/(area[i]+area[j]-interface) #计算IOU(交/并)
if overlap>=threshhold:#IOU若大于阈值,则抑制
suppressed[j]=1
return keep