NMS与Soft NMS算法解析与numpy实现

news2024/12/23 11:34:21

1. NMS算法

1.1 什么是NMS算法

NMS全称为Non Maximum Suppression,中文意思是非极大值抑制,字面意思就是不是极大值的元素被抑制掉,其实就是筛选出局部最大值得到最优解。NMS算法被广泛运用于目标检测算法处理网络输出的边界框。

1.2 为什么在目标检测中要使用NMS算法

在目标检测中如果不是用NMS算法,则网络的输出结果就会向如下图所示,许多预测框都框住了目标,但是这些框并不是我们都想要的,我们想要的是其中框出来最好的那一个预测框。此时,我们就需要利用NMS算法去筛选出最适合的预测框。

在这里插入图片描述

1.3 在目标检测中怎么样使用NMS算法

我们以检测人脸为例,在目标检测中使用NMS算法的流程:

  1. 首先,需要通过置信度阈值消除小于阈值的预测框,比如阈值为0.5,如图下图所示,得到过滤后的预测框。

在这里插入图片描述

  1. 将所有的预测框的置信度降序排列,得到置信度最大的预测框,如下图红色框:

在这里插入图片描述

  1. 再设置一个IOU阈值,所谓IOU就是两个框面积的交并比,遍历其余的框,如果和当前最高分框的IOU大于一定阈值,我们就将框删除,如下图所示。

在这里插入图片描述

  1. 再重复1、2、3步骤,得到最终的结果。

在这里插入图片描述

Python代码如下:
代码来自:https://github.com/rbgirshick/fast-rcnn/blob/master/lib/utils/nms.py


import numpy as np

def nms(dets, thresh):
	# ------------------------------------ #
	# 获取所有预测框的左上角x1, y1、右上角x2, y2以及置信度scores
	# ------------------------------------ #
    x1 = dets[:, 0]
    y1 = dets[:, 1]
    x2 = dets[:, 2]
    y2 = dets[:, 3]
    scores = dets[:, 4]
	# ------------------------------------ #
	# 获取所有预测框的面积
	# ------------------------------------ #
    areas = (x2 - x1 + 1) * (y2 - y1 + 1)
    # ------------------------------------ #
	# 所有预测框降序排列(保存的是下标)
	# ------------------------------------ #
    order = scores.argsort()[::-1]
    
	# ------------------------------------ #
	# keep为最后计算保留下来预测框的下标
	# ------------------------------------ #
    keep = []
    while order.size > 0:
    	# ------------------------------------ #
    	# 取出置信度值最大的下标
    	# ------------------------------------ #
        i = order[0]
        keep.append(i)
        
        # ------------------------------------ #
    	# 计算IOU
    	# ------------------------------------ #
        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 = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        ovr = inter / (areas[i] + areas[order[1:]] - inter)
		# ------------------------------------ #
    	# 过滤小于IOU阈值的边界框
    	# ------------------------------------ #
        inds = np.where(ovr <= thresh)[0]
        # ------------------------------------ #
        # ovr 数组的长度比 order 数组少一个,这里将所有下标后移一位
        # ------------------------------------ #
        order = order[inds + 1]

    return keep

2. Soft NMS算法

2.1 什么是Soft NMS算法

Soft NMS是对NMS的优化算法,它在不增加额外参数的情况下且只需要对NMS算法进行简单的改动就能提高AP。该Soft-NMS算法在标准数据集PASCAL VOC2007(较R-FCN和Faster-RCNN提升1.7%)和MS-COCO(较R-FCN提升1.3%,较Faster-RCNN提升1.1%)上均有提升。

Soft NMS的主要思想

如下图所示,假设重叠的阈值为 0.5,图 中当黑框与红框比较时,两者之间的IoU为0.51,则红框将被删除,即使置信度高于许多其他 IoU 较小的框。因此,如果有两个并排的对象,则其中一个将被消除,这会降低模型的精度。

NMS与Soft NMS都有一个共同点,都是从置信度最大的框开始逐渐迭代的。

在这里插入图片描述

因此,Soft NMS则不再是直接将大于重叠的阈值的框删除,而是根据重叠程度衰减框的置信度得分,再根据设定的置信度阈值,去除小于置信度阈值的框。

改变置信度的方法有两种:

  1. 线性法

如下公式:
其中, i o u ( M , b i ) iou(M, b_i) iou(M,bi)代表最大置信度得分的框 M M M与第 i i i个框 b i b_i bi的IOU, N t N_t Nt代表重叠的阈值, s i s_i si代表第 i i i个框的置信度得分 s i s_i si

在这里插入图片描述

通过分析可以得出,当重叠的IOU增大时,置信度得分确实得到线性的下降。

  1. 高斯法

如下公式:
其中: i o u ( M , b i ) iou(M, b_i) iou(M,bi)代表最大置信度得分的框 M M M与第 i i i个框 b i b_i bi的IOU, σ \sigma σ为一个可设定的常数, s i s_i si代表第 i i i个框的置信度得分 s i s_i si

在这里插入图片描述

通过分析可以得出,当重叠的IOU增大时,置信度得分确实下降了。

如下图是原论文中Soft NMS在R-FCN中 N t N_t Nt σ \sigma σ的变化对AP的影响。

在这里插入图片描述

2.2 代码实现:

参考代码:https://github.com/DocF/Soft-NMS/blob/master/soft_nms.py

import numpy as np



def py_cpu_softnms(dets, sc, Nt=0.3, sigma=0.5, thresh=0.001, method=2):
    """
    py_cpu_softnms
    :param dets:   boexs 坐标矩阵 format [y1, x1, y2, x2]
    :param sc:     每个 boxes 对应的分数
    :param Nt:     iou 交叠门限
    :param sigma:  使用 gaussian 函数的方差,根据需要设置
    :param thresh: 最后的分数门限
    :param method: 使用的方法
    :return:       留下的 boxes 的 index
    """

    # indexes concatenate boxes with the last column
    N = dets.shape[0]
    indexes = np.array([np.arange(N)])
    dets = np.concatenate((dets, indexes.T), axis=1)

    # the order of boxes coordinate is [y1,x1,y2,x2]
    y1 = dets[:, 0]
    x1 = dets[:, 1]
    y2 = dets[:, 2]
    x2 = dets[:, 3]
    scores = sc
    areas = (x2 - x1 + 1) * (y2 - y1 + 1)

    for i in range(N):
        # intermediate parameters for later parameters exchange
        tBD = dets[i, :].copy()
        tscore = scores[i].copy()
        tarea = areas[i].copy()
        pos = i + 1

        #
        if i != N-1:
            maxscore = np.max(scores[pos:], axis=0)
            maxpos = np.argmax(scores[pos:], axis=0)
        else:
            maxscore = scores[-1]
            maxpos = 0
        if tscore < maxscore:
            dets[i, :] = dets[maxpos + i + 1, :]
            dets[maxpos + i + 1, :] = tBD
            tBD = dets[i, :]

            scores[i] = scores[maxpos + i + 1]
            scores[maxpos + i + 1] = tscore
            tscore = scores[i]

            areas[i] = areas[maxpos + i + 1]
            areas[maxpos + i + 1] = tarea
            tarea = areas[i]

        # IoU calculate
        xx1 = np.maximum(dets[i, 1], dets[pos:, 1])
        yy1 = np.maximum(dets[i, 0], dets[pos:, 0])
        xx2 = np.minimum(dets[i, 3], dets[pos:, 3])
        yy2 = np.minimum(dets[i, 2], dets[pos:, 2])

        w = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        ovr = inter / (areas[i] + areas[pos:] - inter)

        # Three methods: 1.linear 2.gaussian 3.original NMS
        if method == 1:  # linear
            weight = np.ones(ovr.shape)
            weight[ovr > Nt] = weight[ovr > Nt] - ovr[ovr > Nt]
        elif method == 2:  # gaussian
            weight = np.exp(-(ovr * ovr) / sigma)
        else:  # original NMS
            weight = np.ones(ovr.shape)
            weight[ovr > Nt] = 0

        scores[pos:] = weight * scores[pos:]

    # select the boxes and keep the corresponding indexes
    inds = dets[:, 4][scores > thresh]
    keep = inds.astype(int)

    return keep

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/95803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【HTML基础篇002】HTML之form表单超详解

文章目录 &#x1f304;一、form表单是什么 &#x1f304;二、form表单的属性 &#x1f304;三、input中的各种Type属性值 &#x1f304;四、标签 &#x1f304;一、form表单是什么 表单是一个包含表单元素的区域。表单用于向服务器传输数据&#xff0c;从而实现用户与Web服…

jsp+ssm计算机毕业设计潮流服饰网店平台【附源码】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JSPSSM mybatis Maven等等组成&#xff0c;B/S模式 Mave…

第十四届蓝桥杯集训——if——配套用法示例

第十四届蓝桥杯集训——if——配套用法示例 目录 第十四届蓝桥杯集训——if——配套用法示例 方法1 方法2 其它指数幂 输入一个数n&#xff0c;判断n是否是2的指数。 n的取值范围(0>n<)​​​​ 题目看着很简单&#xff0c;其实在比较小的数上还是挺容易做的&…

CARIS11.4基本使用流程及其bug解决

今天博主介绍一下CARIS11.4的基本流程以及它的界面bug。 一、CARIS11.4的基本流程 如果以前用过CARIS9&#xff0c;不用看帮助说明&#xff0c;你摸索一段时间也能掌握CARIS11.4的使用流程。相比CARIS9&#xff0c;CARIS11.4的主要功能基本不变&#xff0c;增加了生成变分辨率…

毕业设计 - java web 进销存管理系统的设计与实现【源码+论文】

文章目录前言一、项目设计1. 模块设计系统需要具备以下功能2. 实现效果二、部分源码项目源码前言 今天学长向大家分享一个 java web 项目: 进销存管理系统的设计与实现 一、项目设计 1. 模块设计 系统需要具备以下功能 ⑴一般企业人员的计算机知识掌握的不多&#xff0c;因…

Android studio profiler中的Shallow size和retained sizes是什么意思

这个文章说得非常好&#xff1a;https://www.yourkit.com/docs/java/help/sizes.jsp#:~:textYourKit%20Java%20Profiler%20is%20capable%20of%20measuring%20shallow,the%20number%20and%20types%20of%20%20its%20fields. Shallow size&#xff1a;用于存储一个对象的内存大小…

【Python机器学习】聚类算法任务,评价指标SC、DBI、ZQ等系数详解和实战演示(附源码 图文解释)

需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 一、聚类任务 设样本集S{x_1,x_2,…,x_m}包含m个未标记样本&#xff0c;样本x_i(x_i^(1),x_i^(2),…,x_i^(n))是一个n维特征向量。 聚类在分簇过程的任务是建立簇结构&#xff0c;即要将S划分为k&#xff08;有的聚类算法…

你不知道的 Git 技巧:如何实现核心代码保护

大家好&#xff0c;我是 shixin。 前段时间完成了一个核心代码保护的功能&#xff0c;目标是在关键代码被修改及时同步给其他人&#xff0c;避免没经过 review 就上线导致问题&#xff0c;提示的效果图如下&#xff1a; 在实现的过程中&#xff0c;用到一些平时使用不多的 Git…

微服务框架 SpringCloud微服务架构 多级缓存 48 多级缓存 48.8 查询Redis 缓存

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 多级缓存 文章目录微服务框架多级缓存48 多级缓存48.8 查询Redis 缓存48.8.1 OpenResty的Redis模块48 多级缓存 48.8 查询Redis 缓存 48.8…

spring切入点函数

切入点函数&#xff1a;用于执行切入点函数 1.execution 1.最为重要的切入点函数&#xff0c;功能最全 2.可以执行方法切入点表达式&#xff0c;可以执行类切入点表达式&#xff0c;可以执行包切入点表达式 弊端&#xff1a;书写比较麻烦 2.args 1.作用&#xff1a;主要用…

原创10个python自动化化案例,一口一个高效办公!

以下为我的自动化办公代码&#xff0c;有需要的同学建议点赞收藏并熟读背诵&#xff01;&#xff08;持续更新&#xff09; 1.自动化批量调整word中含有关键词句子的样式 就随便拿一段我在网上找到的文字来做例子&#xff1a; 若关键词为“资金”&#xff0c;则处理后的word…

CentOS不再维护,跃跃欲试AlmaLinux

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&#x1f61…

CSS基础总结(三)盒子模型

文章目录 一、概述 二、组成 1. 边框&#xff08;border&#xff09; 2.内边距&#xff08;padding&#xff09; 3.外边距&#xff08;margin&#xff09; 三、阴影 1.盒子阴影 2.文字阴影 四、综合案例 1.新浪导航栏 2.京东商品模块 一、概述 所谓 盒子模型&#xff1a…

Kubernetes自定义监控指标——Prometheus Adapter实战演练

1、概述 kubernetes的监控指标分为两种&#xff1a; Core metrics(核心指标)&#xff1a;从 Kubelet、cAdvisor 等获取度量数据&#xff0c;再由metrics-server提供给 kube-scheduler、HPA、 控制器等使用。 Custom Metrics(自定义指标)&#xff1a;由Prometheus Adapter提供…

小伙伴们-GO-带你揭开Linux的神秘面纱

文章目录1、Linux的神秘面纱2、Linux操作系统优秀特质3、Linux操作系统应用领域4、解刨-linux系统结构5、带你一探Linux系统-满血复活的启动过程6、Linux 骨架-文件系统与目录结构6.1、Linux 文件系统概览6.2 、linux/unix 文件系统-奠基石6.2.1、 硬盘存储小知识6.2.2、 inode…

重写Nacos服务发现:多个服务器如何跨命名空间,访问公共服务?

一、问题背景 在开发某个公共应用时&#xff0c;笔者发现该公共应用的数据是所有测试环境&#xff08;假设存在 dev/dev2/dev3&#xff09;通用的。 这就意味着只需部署一个应用&#xff0c;就能满足所有测试环境的需求&#xff1b;也意味着所有测试环境都需要调用该公共应用…

LLVM浅析

LLVM的探索 编译器的作用就是将源码编译成可以运行的程序。 终端按顺下敲入 vim hello.py python hello.py vim hello.c clang hello.c ./a.out vim main.m #imclude<stdio.h> int main(int argc, char *argv[]){printf("hello word!"); };LLVM概述 从写代码…

【Python天气预报系统】又要降温,这个冬天你准备好棉衣秋裤了吗?看了不后悔系列之Python打造智能天气预报系统,爆赞。

前言 鼎鼎大名的南方城市长沙很早就入冬了&#xff0c;街上各种大衣&#xff0c;毛衣&#xff0c;棉衣齐齐出动。 这段时间全国各地大风呜呜地吹&#xff0c;很多地方断崖式降温。瑟瑟发抖.jpg 虽然前几天短暂的温度回升&#xff0c;但肯定是为了今天的超级降温&#xff0c;…

毕业设计 - 基于java web的城市公交查询系统的设计与实现【源码+论文】

文章目录前言一、项目设计1. 模块设计2. 实现效果二、部分源码项目工程前言 今天学长向大家分享一个 java web 毕业设计项目: 基于java web的城市公交查询系统的设计与实现 一、项目设计 1. 模块设计 系统功能的划分方式可以分成很多种类&#xff0c;但是我按照界面流程将它…

“人生搜索引擎” # Rewind

你想找什么东西&#xff0c;只需要在搜索引擎上输入关键词&#xff0c;它就会把“相关记忆”给你提取出来。这也就是 Rewind 这款搜索引擎想解决的问题。Rewind 给自身的定义是&#xff1a;The Search Engine For Your Life也就是你人生的搜索引擎&#xff0c;它声称能快速搜索…