非极大值抑制(NMS)

一.概述

  在目标检测中,常会利用非极大值抑制算法(NMS)对生成的大量候选框进行后处理,去除冗余的候选框,得到最具代表性的结果,以提高目标检测的效率。即如下图所示,消除多余的候选框,找到最佳的bbox。

                                                             è¿éåå¾çæè¿°

二.NMS算法详解

NMS算法的核心思想如下:

根据候选框的类别分类概率做排序:A<B<C<D<E<F

  1. 先标记最大概率矩形框F是我们要保留下来的;
  2. 从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU(两框的交并比)是否大于某个设定的阈值,假设B、D与F的重叠度超过阈值,那么就扔掉B、D;
  3. 从剩下的矩形框A、C、E中,选择概率最大的E,标记为要保留下来的,然后判读E与A、C的重叠度,扔掉重叠度超过设定阈值的矩形框

就这样一直重复下去,直到剩下的矩形框没有了,标记完所有要保留下来的矩形框。

注:nms是针对每一个类别分别进行的

三.python代码实现

# coding=utf-8
import numpy as np


def nms(dets, thresh):

    # dets.shape = (n, 5)
    # n代表有n个候选框,5代表每个候选框用5个值表示,即[x1,y1,x2,y2,score]
    # x1.shape = y1.shape = x2.shape = y2.shape = scores.shape = (n, 1)
    x1 = dets[:, 0]  # 第一列,即所有候选框左上角点的x坐标值
    y1 = dets[:, 1]  # 第二列,即所有候选框左上角点的y坐标值
    x2 = dets[:, 2]  # 第三列,即所有候选框右下角点的x坐标值
    y2 = dets[:, 3]  # 第四列,即所有候选框右下角点的y坐标值
    scores = dets[:, 4]  # 第五列,即所有候选框的bbox评分

    # 计算每一个候选框的面积
    # areas.shape = (n, 1)
    areas = (x2 - x1 + 1)*(y2 - y1 + 1)

    # order是按照scores的大小来对整个dets降序排列
    # order中存放的是dets的各行按scores的大小降序排列的索引值
    # order.shape = (n, 1)
    order = scores.argsort()[::-1]

    # 初始化一个空的列表keep,keep中将会存放经过非极大值抑制后留下的候选框在dets中的索引值
    keep = []

    while order.size > 0:  # 循环条件:只要order中还有元素
        # 将i初始化为dets中scores最大值的那一行的索引
        i = order[0]
        # 将i的值存放到keep中
        keep.append(i)
        # 计算当前概率最大矩形框与其他矩形框的相交框的坐标,会用到numpy的broadcast机制,得到的是向量
        xx1 = np.maximum(x1[i], x1[order[1:]])
        yy1 = np.maximum(y1[i], y1[order[1:]])
        xx2 = np.minimum(x2[i], x2[order[1:]])
        yy2 = np.minimum(y2[i], y2[order[1:]])

        # 计算相交框的面积,注意矩形框不相交时w或h算出来会是负数,用0代替
        w = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        # 计算重叠度IOU:重叠面积/(面积1+面积2-重叠面积)
        ovr = inter / (areas[i] + areas[order[1:]] - inter)

        # 找到重叠度不高于阈值的矩形框索引
        inds = np.where(ovr <= thresh)[0]
        # 将order序列更新,由于前面得到的矩形框索引要比矩形框在原order序列中的索引小1,所以要把这个1加回来
        order = order[inds + 1]
    return keep

    # test
if __name__ == "__main__":
    dets = np.array([[30, 20, 230, 200, 1],
                        [50, 50, 260, 220, 0.9],
                        [210, 30, 420, 5, 0.8],
                        [430, 280, 460, 360, 0.7]])
    thresh = 0.35
    keep_dets = nms(dets, thresh)
    print(keep_dets)
    print(dets[keep_dets])

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值