NMS用于剔除图像中检出的冗余bbox,标准NMS的具体做法为:
step-1:将所有检出的output_bbox按cls score划分(如pascal voc分20个类,也即将output_bbox按照其对应的cls score划分为21个集合,1个bg类,只不过bg类就没必要做NMS而已);
step-2:在每个集合内根据各个bbox的cls score做降序排列,得到一个降序的list_k;
step-3:从list_k中top1 cls score开始,计算该bbox_x与list中其他bbox_y的IoU,若IoU大于阈值T,则剔除该bbox_y,最终保留bbox_x,从list_k中取出;
step-4:选择list_k中top2 cls score(步骤3取出top 1 bbox_x后,原list_k中的top 2就相当于现list_k中的top 1了,但如果step-3中剔除的bbox_y刚好是原list_k中的top 2,就依次找top 3即可,理解这么个意思就行),重复step-3中的迭代操作,直至list_k中所有bbox都完成筛选;
step-5:对每个集合的list_k,重复step-3、4中的迭代操作,直至所有list_k都完成筛选;
精简代码示例:
import numpy as np
import pdb
#dets shape: n,5
def nms(dets,th):
x1=dets[:,0]
y1=dets[:,1]
x2=dets[:,2]
y2=dets[:,3]
arear=(x2-x1+1)*(y2-y1+1)
index=dets[:,4].argsort()[::-1]
keep=[]
while len(index)>0:
i=index[0]
others=index[1:]
keep.append(i)
#cal iou
over_x1=np.maximum(x1[i],x1[others])
over_y1=np.maximum(y1[i],y1[others])
over_x2=np.minimum(x2[i],x2[others])
over_y2=np.minimum(y2[i],y2[others])
w=np.maximum(over_x2-over_x1+1,0)
h=np.maximum(over_y2-over_y1+1,0)
inter=w*h
top_arear=arear[i]
iou=inter/(arear[i]+arear[others]-inter)
index=others[iou<th]
return dets[np.array(keep)]
if __name__ == "__main__":
dets=np.array([[100,120,170,200,0.98],
[20,40,80,90,0.99],
[20,38,82,88,0.96],
[200,380,282,488,0.9],
[19,38,75,91,0.8] ])
out=nms(dets,0.5)
print(out)