自学内容网 自学内容网

非极大值抑制NMS详解(Non Maximum Suppression)

深度学习



前言

非极大值抑制广泛应用在目标检测,目标跟踪,边缘检测。

一、步骤

大致步骤:
1、假设检测器检测到n个置信度的框。
2、将这些框分别按照置信度从小到大排列(从大到小皆可)
3、选择置信度最大的框放入到输出列表中,然后在原先的这个框从原先的候选框中删除。
4、计算这个框与其他框的IOU,将大于nms_threshold的框删除。
重复3-4步骤。直到原先列表里没有框框了。

1.过程描述

1.假设,经过目标检测,检测到图中有6个Bounding Boxes,共属于两个类的。每个Bounding Boxes 的置信度已经标在了图上。(假设IOU阈值为0.3)
在这里插入图片描述

  1. 我们依据所有Bounding Boxes的置信度排序。

B 0.99 > P 0.98 > B 0.88 > P 0.87 > B 0.65 > P 0.45

3.选择置信度最大的一个Bounding Boxes,为B 0.99。将这个Bounding Box移到输出列表里,原先的剩余列表为。

P 0.98 > B 0.88 > P 0.87 > B 0.65 > P 0.45

4.然后计算B 0.99与列表中剩下的Bounding boxes的IOU,从剩余列表里删除与B 0.99的IOU距离大于0.3的,删除过后的剩余列表为

P 0.98 > P 0.87 > P 0.45
在这里插入图片描述

5.然后重复步骤2到4。此时的输出列表为:

B 0.99

6.在剩余列表里取置信度最大的Bounding Boxes(P 0.98)放到输出列表里,此时的输出列表为:

B 0.99, P 0.98

此时的剩余列表为

P 0.87 > P 0.45

  1. 计算当前活跃的最大置信度Bounding Box与剩余列表的IOU,删除剩余列表里与P 0.98的IOU距离大于0.3的,删除过后的剩余列表为:

最后的输出列表为

P 0.99, P 0.98

8.算法结束。
在这里插入图片描述

2.解析
这个NMS算法是以置信度为完全信任指标的,意思就是置信度最大的肯定是预测的最准的。因为在多目标检测中,同一个图片里面可能含有多个类别的多个框框,其他类别的框框肯定是离这个置信度最大的框框“比较远的”,这儿这个比较远的衡量指标就是IOU,一个循环执行的是对当前对象的所有候选框框进行处理的,所以IOU小于阈值的,就理解为“比较远了”,不属于当前这个对象,就留下来,等待下一个对象来循环,而大于阈值的,是属于当前对象的,但是由于已经有了一个置信度最高的候选框,就删除。

然后再次在剩下的选择最大的框框,依次再来执行上面的过程。

提示:两个box距离越近,IOU越大,距离越远,IOU越小。

二、代码实现

def bbox_ious(boxes1, boxes2, x1y1x2y2=True):
    '''
    两种box的位置坐标格式
    '''
    if x1,y1,x2,y2:#(左上点x,左上点y,右下点x,右下点y)
        mx = torch.min(boxes1[0], boxes2[0])
        Mx = torch.max(boxes1[2], boxes2[2])
        my = torch.min(boxes1[1], boxes2[1])
        My = torch.max(boxes1[3], boxes2[3])
        w1 = boxes1[2] - boxes1[0]
        h1 = boxes1[3] - boxes1[1]
        w2 = boxes2[2] - boxes2[0]
        h2 = boxes2[3] - boxes2[1]
    else:#(左上点x,左上点y,box的宽,box的高)
        mx = torch.min(boxes1[0] - boxes1[2] / 2.0, boxes2[0] - boxes2[2] / 2.0)
        Mx = torch.max(boxes1[0] + boxes1[2] / 2.0, boxes2[0] + boxes2[2] / 2.0)
        my = torch.min(boxes1[1] - boxes1[3] / 2.0, boxes2[1] - boxes2[3] / 2.0)
        My = torch.max(boxes1[1] + boxes1[3] / 2.0, boxes2[1] + boxes2[3] / 2.0)
        w1 = boxes1[2]
        h1 = boxes1[3]
        w2 = boxes2[2]
        h2 = boxes2[3]
    uw = Mx - mx
    uh = My - my
    cw = w1 + w2 - uw
    ch = h1 + h2 - uh
    mask = ((cw <= 0) + (ch <= 0) > 0)
    area1 = w1 * h1
    area2 = w2 * h2
    carea = cw * ch
    carea[mask] = 0
    uarea = area1 + area2 - carea
    return carea / uarea

def nms(boxes, nms_thresh):
    '''
    目标检测的非极大值抑制
    boxes:{list:n} 一个nx7的列表,
    n代表检测到的box数量,
    7代表:4个坐标(x,y,w,h其中xy表示中心坐标,wh是bbox的宽高)2个置信度,1个类别
    nms_thresh:{float} 一个浮点数,越小表示越严格
    ----------------
    return
        返回一个mx7的列表 {list:m} m表示经过nms后的剩余box数量
    '''
    if len(boxes) == 0:
        return boxes

    #下面这个张量用来保存着与1-置信度的值,相当于反转了一下,这样就可以从小到大排序进行处理
    det_inverse_confs = [ 1 - bb[4] for bb in boxes]
    det_inverse_confs = torch.asarray(det_inverse_confs)

    _, sortIds = torch.sort(det_inverse_confs)#从小到大排序,返回排序后的值和对应的索引
    out_boxes = []  #输出列表
    for i in range(len(boxes)):
        box_i = boxes[sortIds[i]]   #从最小的值的索引开始处理,box_i是最小值的索引对应的原先的box
        if box_i[4] > 0:    #如果这个最小值大于0。
            out_boxes.append(box_i)
            for j in range(i + 1, len(boxes)):#用for循环计算这个最大置信度box与其他box的IOU
                box_j = boxes[sortIds[j]]#i的下一个box,也就是次第二大的置信度的box
                if bbox_iou(box_i, box_j, x1y1x2y2=False) > nms_thresh:#删除IOU大于阈值的box
                    box_j[4] = 0    #将IOU大于阈值的box的conf重置为0,即置信度为0后,就不会放入output_boxes,相当于删除。
    return out_boxes

原文地址:https://blog.csdn.net/zyq880625/article/details/143743646

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!