非极大值抑制

目录

相关知识

非极大值抑制介绍

代码部分

代码参考


相关知识

非极大值抑制介绍

目前,常用的目标检测算法,无论是One-stageSSD系列算法、YOLO系列算法还是Two-stage的基于R-CNN系列的算法,非极大值抑制都是其中必不可少的一个组件。在现有的基于anchor的目标检测算法中,都会产生数量巨大的候选矩形框,这些矩形框有很多是指向同一目标,因此就存在大量冗余的候选矩形框。非极大值抑制算法的目的正在于此,它可以消除多余的框,找到最佳的物体检测位置。

非极大值抑制(Non-Maximum Suppression,以下简称NMS算法)的思想是搜索局部极大值,抑制非极大值元素

由于是滑动窗口,一个对象可能有多个Bounding box,每个边界框都有一个分类器得分,而我们的最终目标是留下那个最优的Bounding box。 而其中,我们应用了非极大值抑制来去掉冗余的框:它就是一个迭代-遍历-消除的过程。

  • 将所有框的得分进行排序,选中最高分及其对应的框:

  • 遍历其余的框,如果和当前最高分框的重叠面积(IOU)大于一定阈值,我们就将框删除:

  • 从未处理的框中继续选一个得分最高的,重复上述过程:

举例,下面图片定位一个车辆,最后算法找出一堆的方框,我们需要判别哪些矩形框是没用的。非极大值抑制的方法是:先假设有6个矩形框,根据分类器的类别分类概率做排序,假设从小到大属于车辆的概率 分别为A、B、C、D、E、F。

  • 1、从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个设定的阈值;
  • 2、假设B、D与F的重叠度超过阈值,那么就扔掉B、D;并标记第一个矩形框F,是我们保留下来的。
  • 3、从剩下的矩形框A、C、E中,选择概率最大的E,然后判断E与A、C的重叠度,重叠度大于一定的阈值,那么就扔掉;并标记E是我们保留下来的第二个矩形框。
  • 4、一直重复这个过程,找到所有曾经被保留下来的矩形框。
代码部分

获取坐标位置以及置信度

# 生成数据,shape=(5, 5)
 a = np.eye(5)
# 获取第一列的数据
res = a[:, 1]
print(res)
# 显示结果
array([0., 1., 0., 0., 0.])
置信度得分排序,这里使用的是argsort函数进行排序,但是argsort函数默认是从小到大进行排序,所以在后面用[::-1]实现倒序。

argsort函数介绍:

x = np.array([1, 4, 3, -1, 6, 9])
print(x.argsort())
# 返回结果,它是索引排序和数据类型
array([3, 0, 2, 1, 4, 5], dtype=int64)

置信度排序过程:

 代码参考
import numpy as np
from matplotlib import pyplot as plt


# 2.假设生成如下Bbox
boxes = np.array([[100, 100, 210, 220, 0.71],
                  [250, 250, 420, 420, 0.8],
                  [220, 200, 320, 330, 0.92],
                  [100, 100, 210, 210, 0.72],
                  [230, 240, 325, 330, 0.81],
                  [220, 230, 315, 340, 0.9]])


def nms(bboxs, thresh):
    # bboxs:形似上面设置的boxes,是一组包含了诸多框坐标的数组
    # thresh: IOU阈值

    # 请在此添加代码,获取坐标位置以及置信度
    ########## Begin ##########
    xmin = boxes[:, 0]
    ymin = boxes[:, 1]
    xmax = boxes[:, 2]
    ymax = boxes[:, 3]
    scores = boxes[:, 4]
    ########## Begin ##########
    # print(xmin, ymin, xmax, ymax, scores)
    # 计算每个框的面积
    # 那为什么要加1操作呢?因为图片像素最小是1,而数组是0。
    areas = (xmax - xmin + 1) * (ymax - ymin + 1)
    # print(areas)
    # 获取得分以排序

    # print(scores)
    # 请在此添加代码,argot默认从小到大排序,[::-1]实现翻转,获取索引index
    ########## Begin ##########
    index = scores.argsort()[::-1]

    ########## End ##########     
         
    # print(index)
    # 4.保留结果集,返回输出保留下来的Bbox最终结果
    result = []

    while index.size > 0:
        i = index[0]                          # index中存储Bbox按分排序后的索引,所以第一个就是得分最高的Bbox索引,直接保留
        result.append(i)

        # 两个框的左上角坐标x取大值,右下角坐标x取小值,小值-大值+1==相交区域的长度
        # 两个框的左上角坐标y取大值,右下角坐标y取小值,小值-大值+1==相交区域的高度
        x11 = np.maximum(xmin[i], xmin[index[1:]])
        y11 = np.maximum(ymin[i], ymin[index[1:]])
        x22 = np.minimum(xmax[i], xmax[index[1:]])
        y22 = np.minimum(ymax[i], ymax[index[1:]])

        # 计算相交面积,当两个框不相交时,w和h必有一个为0,面积也为0
        w = np.maximum(0, x22 - x11 + 1)
        h = np.maximum(0, y22 - y11 + 1)

        overlaps = w * h

        ious = overlaps / (areas[i] + areas[index[1:]] - overlaps) # index[1:]从下标1开始取到列表结束 最高分的面积加其余的面积

        idx = np.where(ious <= thresh)[0]
        # 因为index是从1开始的,加1
        index = index[idx + 1]
    print(result)
    return result


def plot_bbox(bboxs, c='k'):
    x1 = bboxs[:, 0]
    y1 = bboxs[:, 1]
    x2 = bboxs[:, 2]
    y2 = bboxs[:, 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(" nms")


if __name__ == '__main__':
    plt.figure(1)
    ax1 = plt.subplot(1, 2, 1)  # 定义子图,把NMS前和NMS后的绘制在一起
    ax2 = plt.subplot(1, 2, 2)

    plt.sca(ax1)
    plot_bbox(boxes, 'k')  # before nms
    # 接收平台的IoU阈值
    k = float(input())
    res = nms(boxes, thresh=k)
    plt.sca(ax2)
    plot_bbox(boxes[res], 'r')  # after nms
    plt.savefig('src/step1/img1/figure.jpg')
    plt.show()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值