Non-Maximum Suppression(NMS)

NMS原理

Faster-RCNN中有两处使用NMS,第一处是训练+预测的时候,利用ProposalCreator来生成proposal的时候,因为只需要一部分proposal,所以利用NMS进行筛选。第二处使用是预测的时候,当得到300个分类与坐标偏移结果的时候,需要对每个类别逐一进行非极大值抑制。(根本目的去重
在这里插入图片描述
IOU算法
核心思想:A框的分类得分最高,那么与A框交并比(IOU)的值大于设定的阈值(表示与A重复)的框集合 {B} 剔除。(分类得分高,说明该框和ground truth更为接近,或者该框的feature更利于分类,所以保留该框,剔除其它重复的不好的框)

#一系列的锚框定义方式[左上角x,左上角y,右下角x,右下角y,分类得分]
anchor boxes=[[xmin,ymin,xmax,ymax,scores]....]

在这里插入图片描述
选择两个anchor box中更大的左上角坐标x和y和右下角更大的x和y坐标确定两个交点

#和其他所有框一个一个的比较,得到的是一个列表 
#确定两个交点的坐标
x11 = np.maximum(x1[i], x1[index[1:]]) #这里的[1:]是代码实现中的一个技巧
y11 = np.maximum(y1[i], y1[index[1:]])
x22 = np.minimum(x2[i], x2[index[1:]])
y22 = np.minimum(y2[i], y2[index[1:]])
#计算框的宽度和高度
w = np.maximum(0, x22-x11+1)#未相交的两个框相减会为负数直接置为0   
h = np.maximum(0, y22-y11+1)

在这里插入图片描述
完整案例代码演示

import numpy as np
import matplotlib.pyplot as plt
def py_cpu_nms(dets, thresh):
    #dets的数据格式是dets[[xmin,ymin,xmax,ymax,scores]....]表示每一个anchor box
    #计算每一个anchor box的面积
    x1 = dets[:,0]
    y1 = dets[:,1]
    x2 = dets[:,2]
    y2 = dets[:,3]
    areas = (y2-y1+1) * (x2-x1+1)
    scores = dets[:,4] 
    #这边的keep用于存放,NMS后剩余的方框
    keep = []
    #取出分类得分从大到小排列的索引;
    #argsort()是从小到大排列,[::-1]是列表头和尾颠倒一下。
    index = scores.argsort()[::-1]
    #上面这两句比如分数[0.72 0.8  0.92 0.72 0.81 0.9 ]    
    # 对应的索引index[  2   5    4     1    3   0  ]记住是取出索引,scores列表没变
    #index会剔除遍历过的方框,和合并过的方框。 
    while index.size >0:
        #取出第一个分类得分最高的框进行和其他方框比对
        i = index[0]       # every time the first is the biggst, and add it directly
        #keep保留的是索引值
        keep.append(i)

        #计算交集的左上角和右下角
        #这里要注意,比如x1[i]这个方框的左上角x和所有其他的方框的左上角x的
        x11 = np.maximum(x1[i], x1[index[1:]])    # calculate the points of overlap 
        y11 = np.maximum(y1[i], y1[index[1:]])
        x22 = np.minimum(x2[i], x2[index[1:]])
        y22 = np.minimum(y2[i], y2[index[1:]])
        
        print(x11,y11,x22,y22)
        #这边要注意,如果两个方框相交,X22-X11和Y22-Y11是正的。
        #如果两个方框不相交,X22-X11和Y22-Y11是负的,我们把不相交的W和H设为0.
        w = np.maximum(0, x22-x11+1)    
        h = np.maximum(0, y22-y11+1)    
       
        #利用iou公式计算,不相交的框因为W和H都是0,所以不相交面积为0
        overlaps = w*h
        print('overlaps is',overlaps)
        ious = overlaps / (areas[i]+areas[index[1:]] - overlaps)
        print('ious is',ious)
        
        #这里np.where(ious<=thresh)[0]是一个固定写法,将小于阈值的框留下,所以阈值越大,计算越慢,因为留下的框更多
        #以元素的形式返回索引,一个元素的元组(array([2,3,4]),)所以用[0]取出元素[2,3,4]
        idx = np.where(ious<=thresh)[0]
        print(idx)

        #这边留下的框是去除当前操作的框,和当前操作的框重叠度大于thresh的框
        #每一次都会先去除当前操作框,所以索引的列表就会向前移动移位,要还原就+1,向后移动一位
        index = index[idx+1]   # because index start from 1
        print(index)
    return keep
def plot_bbox(dets, c, name):
    x1 = dets[:,0]
    y1 = dets[:,1]
    x2 = dets[:,2]
    y2 = dets[:,3]
    
    plt.plot([x1,x2], [y1,y1], c)
    plt.plot([x1,x1], [y1,y2], c)
    plt.plot([x1,x2], [y2,y2], c)
    plt.plot([x2,x2], [y1,y2], c)
    plt.title(name)

boxes=np.array([[100,100,210,210,0.72],
        [250,250,420,420,0.8],
        [220,220,320,330,0.92],
        [100,100,210,210,0.72],
        [230,240,325,330,0.81],
        [220,230,315,340,0.9]]) 
plt.figure(1)
ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)
plt.sca(ax1)
plot_bbox(boxes,'b',name="Before NMS")   # before nms
keep = py_cpu_nms(boxes, thresh=0.7)
plt.sca(ax2)
plot_bbox(boxes[keep], 'r', name="After NMS")# after nms
plt.show()

猜你喜欢

转载自blog.csdn.net/qq_40263477/article/details/106447765