深入浅出理解目标检测的NMS非极大抑制
一、参考资料
物体检测中常用的几个概念迁移学习、IOU、NMS理解
目标定位和检测系列(3):交并比(IOU)和非极大值抑制(NMS)的python实现
Pytorch:目标检测网络-非极大值抑制(NMS)
二、非极大抑制(NMS)相关介绍
1. NMS的概念
非极大抑制(non maximum suppression, NMS),顾名思义就是抑制不是极大值的元素,搜索局部的极大值。在最近几年常见的物体检测算法(包括rcnn、sppnet、fast-rcnn、faster-rcnn等)中,最终都会从一张图片中找出很多个可能是物体的矩形框,然后为每个矩形框为做类别分类概率。
就像下面的图片一样,定位一个车辆,最后算法就找出了一堆的方框,我们需要判别哪些矩形框是没用的。
所谓非极大值抑制,先假设有6个矩形框,根据分类器类别分类概率做排序,从小到大分别属于车辆的概率分别为A<B<C<D<E<F。
- 从最大概率矩形框F开始,分别判断A、B、C、D、E与F的重叠度IOU是否大于某个设定的阈值;
- 假设B、D与F的重叠度超过阈值,那么就扔掉B、D;并标记第一个矩形框F,是我们保留下来的;
- 从剩下的矩形框A、C、E中,选择概率最大的E,然后判断A、C与E的重叠度,重叠度大于一定的阈值,那么就扔掉;并标记E是我们保留下来的第二个矩形框;
- 重复这个过程,找到所有被保留下来的矩形框。
2. YOLO中的NMS
对于每一个种类的概率,比如Dog,我们将所有98个框按照预测概率从高到低排序(为方便计算,排序前可以剔除极小概率的框,也就是把它们的概率置为0),然后通过非极大抑制NMS方法,继续剔除多余的框:
NMS方法在这里如何运行呢?首先因为经过了排序,所以第一个框是概率最大的框(下图橘色)。然后继续扫描下一个框跟第一个框,看是否IOU大于0.5:
的确IOU大于0.5,那么第二个框是多余的,将它剔除:
继续扫描到第三个框,它与最大概率框的IOU小于0.5,需要保留:
继续扫描到第四个框,同理需要保留:
继续扫描后面的框,直到所有框都与第一个框比较完毕。此时保留了不少框。
接下来,以次大概率的框(因为一开始排序过,它在顺序上也一定是保留框中最靠近上一轮的基础框的)为基础,将它后面的其它框于之比较。
如比较第4个框与之的IOU:
IOU大于0.5,所以可以剔除第4个框:
总之在经历了所有的扫描之后,对Dog类别只留下了两个框:
这时候,或许会有疑问:明显留下来的蓝色框,并非Dog,为什么要留下?因为对计算机来说,图片可能出现两只Dog,保留概率不为0的框是安全的。不过的确后续设置了一定的阈值(比如0.3)来删除掉概率太低的框,这里的蓝色框在最后并没有保留,因为它在20种类别里要么因为IOU不够而被删除,要么因为最后阈值不够而被剔除。
上面描述了对Dog种类进行的框选择。接下来,我们还要对其它19种类别分别进行上面的操作。最后进行纵向跨类的比较(为什么?因为上面就算保留了橘色框为最大概率的Dog框,但该框可能在Cat的类别也为概率最大且比Dog的概率更大,那么我们最终要判断该框为Cat而不是Dog)。判定流程和法则如下:
得到最终的结果:
三、相关经验
1. NMS代码实现
NMS的算法步骤如下:
# INPUT:所有预测出的bounding box (bbx)信息(坐标和置信度confidence), IOU阈值(大于该阈值的bbx将被移除)
for object in all objects:(1) 获取当前目标类别下所有bbx的信息(2) 将bbx按照confidence从高到低排序,并记录当前confidence最大的bbx(3) 计算最大confidence对应的bbx与剩下所有的bbx的IOU,移除所有大于IOU阈值的bbx(4) 对剩下的bbx,循环执行(2)和(3)直到所有的bbx均满足要求(即不能再移除bbx)
需要注意的是,NMS是对所有的类别分别执行的。举个栗子,假设最后预测出的矩形框有2类(分别为cup, pen),在NMS之前,每个类别可能都会有不只一个bbx被预测出来,这个时候我们需要对这两个类别分别执行一次NMS过程。
我们用python编写NMS代码,假设对于一张图片,所有的bbx信息已经保存在一个字典中,保存形式如下:
predicts_dict: {"cup": [[x1_1, y1_1, x2_1, y2_1, scores1], [x1_2, y1_2, x2_2, y2_2, scores2], ...], "pen": [[x1_1, y1_1, x2_1, y2_1, scores1], [x1_2, y1_2, x2_2, y2_2, scores2], ...]}
即目标的位置和置信度用列表储存,每个列表中的一个子列表代表一个bbx信息。
详细的代码如下:
import numpy as np
def non_max_suppress(predicts_dict, threshold=0.2):"""implement non-maximum supression on predict bounding boxes.Args:predicts_dict: {"stick": [[x1, y1, x2, y2, scores1], [...]]}.threshhold: iou thresholdReturn:predicts_dict processed by non-maximum suppression"""for object_name, bbox in predicts_dict.items(): #对每一个类别的目标分别进行NMSbbox_array = np.array(bbox, dtype=np.float)## 获取当前目标类别下所有矩形框(bounding box,下面简称bbx)的坐标和confidence,并计算所有bbx的面积x1, y1, x2, y2, scores = bbox_array[:,0], bbox_array[:,1], bbox_array[:,2], bbox_array[:,3], bbox_array[:,4]areas = (x2-x1+1) * (y2-y1+1)#print("areas shape = ", areas.shape)## 对当前类别下所有的bbx的confidence进行从高到低排序(order保存索引信息)order = scores.argsort()[::-1]print("order = ", order)keep = [] #用来存放最终保留的bbx的索引信息## 依次从按confidence从高到低遍历bbx,移除所有与该矩形框的IOU值大于threshold的矩形框while order.size > 0:i = order[0]keep.append(i) #保留当前最大confidence对应的bbx索引## 获取所有与当前bbx的交集对应的左上角和右下角坐标,并计算IOU(注意这里是同时计算一个bbx与其他所有bbx的IOU)xx1 = np.maximum(x1[i], x1[order[1:]]) #当order.size=1时,下面的计算结果都为np.array([]),不影响最终结果yy1 = np.maximum(y1[i], y1[order[1:]])xx2 = np.minimum(x2[i], x2[order[1:]])yy2 = np.minimum(y2[i], y2[order[1:]])inter = np.maximum(0.0, xx2-xx1+1) * np.maximum(0.0, yy2-yy1+1)iou = inter/(areas[i]+areas[order[1:]]-inter)print("iou =", iou)print(np.where(iou<=threshold)) #输出没有被移除的bbx索引(相对于iou向量的索引)indexs = np.where(iou<=threshold)[0] + 1 #获取保留下来的索引(因为没有计算与自身的IOU,所以索引相差1,需要加上)print("indexs = ", type(indexs))order = order[indexs] #更新保留下来的索引print("order = ", order)bbox = bbox_array[keep]predicts_dict[object_name] = bbox.tolist()predicts_dict = predicts_dictreturn predicts_dict
2. 行人检测中的NMS
论文阅读【FCOS】_Rock的博客-CSDN博客_fcos论文
如果两个人靠得很近,将很难确定NMS的阈值,太大则会导致误检多,太小导致漏检多。
相关文章:

深入浅出理解目标检测的NMS非极大抑制
一、参考资料 物体检测中常用的几个概念迁移学习、IOU、NMS理解 目标定位和检测系列(3):交并比(IOU)和非极大值抑制(NMS)的python实现 Pytorch:目标检测网络-非极大值抑制(NMS) …...

HbuilderX报错“Error: Fail to open IDE“,以及运行之后没有打开微信开发者,或者运行没有反应的解决办法
开始 问题:HbuilderX启动时,打开微信开发者工具报错"Error: Fail to open IDE",以及运行之后没有打开微信开发者,或者运行没有反应的解决办法! 解决办法: 按照步骤一步一步完成分析,除非代码报错,否则都是可以启动的 第一步:检查HbuildX是否登录账号 第二步:检查微信…...
【Go 快速入门】基础语法 | 流程控制 | 字符串
文章目录 基础语法值变量常量运算符指针new 和 make 区别 字符串byte 和 rune 类型 流程控制for 循环If else 分支switch 分支 基础语法 项目代码地址:02-basicgrammar 值 基本类型值 Go 最基础的数据类型,比如整型、浮点型、布尔型。 复合类型值 …...

腾讯云轻量应用Ubuntu服务器如何一键部署幻兽帕鲁Palworld私服?
幻兽帕鲁/Palworld是一款2024年Pocketpair开发的开放世界生存制作游戏,在帕鲁的世界,玩家可以选择与神奇的生物“帕鲁”一同享受悠闲的生活,也可以投身于与偷猎者进行生死搏斗的冒险。而帕鲁可以进行战斗、繁殖、协助玩家做农活,也…...
Redis的SDS你了解吗?
初识SDS: Redis的String和其他很多编程语言中的语义相似,它能够表达3种值的类型: 1.字符串 2.整数 3.浮点数 三种类型根据具体场景由Redis完成相互之间的自动转换,并且根据需要选取底层的承载方式,Redis内部&#x…...
C#中常见的软件设计模式及应用场景
文章目录 前言1、单例模式 (Singleton)1.1 详细说明1.2 应用场景示例 2、工厂模式 (Factory Method)2.1 详细说明2.2 应用场景示例 3、观察者模式 (Observer)3.1 详细说明3.2 应用场景示例 4、策略模式 (Strategy)4.1 详细说明4.2 应用场景示例 5、适配器模式 (Adapter)5.1 详细…...
字符串相关函数和文件操作
文章目录 1. C/C 字符串概述1.1 字符串常量1.2 字符数组 2. 字符串函数2.1 拷贝赋值功能相关函数(覆盖)2.1.1 strcpy2.1.2 strncpy2.1.3 memcpy2.1.4 memmove2.1.5 memset2.1.6 注意小点2.1.7 【函数区别】 2.2 追加功能相关函数2.2.1 strcat2.2.2 strnc…...
【c++学习】数据结构中的栈
c栈 栈代码用线性表实现栈用链表实现栈 栈 栈:先进后出 只对栈顶元素进行操作,包括新元素入栈、栈顶元素出栈和查看栈顶元素(只支持对栈顶的增、删、查)。 代码 下述代码实现了栈及其接口 包括对栈顶的增、删、查以及查看栈的大…...

新建react项目,react-router-dom配置路由,引入antd
提示:reactrouter6.4版本,与reactrouter5.0的版本用法有区别,互不兼容需注意 文章目录 前言一、创建项目二、新建文件并引入react-router-dom、antd三、配置路由跳转四、效果五、遇到的问题六、参考文档总结 前言 需求:新建react项…...

Transformer and Pretrain Language Models3-6
Pretrain Language Models预训练语言模型 content: language modeling(语言模型知识) pre-trained langue models(PLMs)(预训练的模型整体的一个分类) fine-tuning approaches GPT and BERT(…...
Linux系统中编写bash脚本进行mysql的数据同步
一、为何要用脚本做数据同步 (一)、问题 我们的视频监控平台云服务器,需要向上级的服务器定期同步一些数据表的数据,前期做了个程序,可以实现同步。但是,现在数据库的结构改了,结果又需要该程序…...

光耦驱动继电器电路图大全
光耦驱动继电器电路图(一) 注: 1U1-1脚可接12V,也可接5V,1U1导通,1Q1导通,1Q1-30V,线圈两端电压为11.7V. 1U1-1脚不接或接地,1U1不通,1Q1截止,1…...

【AI量化分析】小明在量化中使用交叉验证原理深度分析解读
进行交叉验证好处 提高模型的泛化能力:通过将数据集分成多个部分并使用其中的一部分数据进行模型训练,然后使用另一部分数据对模型进行测试,可以确保模型在未见过的数据上表现良好。这样可以降低模型过拟合或欠拟合的风险,提高模…...

2024最新版Visual Studio Code安装使用指南
2024最新版Visual Studio Code安装使用指南 Installation and Usage Guide for the Latest Visual Studio Code in 2024 By JacksonML Visual Studio Code最新版1.85已经于2023年11月由其官网 https://code.visualstudio.com正式发布,这是微软公司2024年发行的的最…...

接口请求重试八种方法
请求三方接口需要加入重试机制 一、循环重试 在请求接口的代码块中加入循环,如果请求失败则继续请求,直到请求成功或达到最大重试次数。 int retryTimes 3; for(int i 0;i < retryTimes;i){try{//请求接口的代码break;}catch(Exception e){//处理…...

【Linux 基础】常用基础指令(上)
文章目录 一、 创建新用户并设置密码二、ls指令ls指令基本概念ls指令的简写操作 三、pwd指令四、cd指令五、touch指令六、rm指令七、mkdir指令八、rmdir 指令 一、 创建新用户并设置密码 ls /home —— 查看存在多少用户 whoami —— 查看当前用户名 adduser 用户名 —— 创建新…...

【RT-DETR有效改进】EfficientFormerV2移动设备优化的视觉网络(附对比试验效果图)
前言 大家好,我是Snu77,这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进,内容持续更新,每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本,同时修改内容也支持Re…...

《动手学深度学习(PyTorch版)》笔记4.4
注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过。…...

Linux/Academy
Enumeration nmap 首先扫描目标端口对外开放情况 nmap -p- 10.10.10.215 -T4 发现对外开放了22,80,33060三个端口,端口详细信息如下 结果显示80端口运行着http,且给出了域名academy.htb,现将ip与域名写到/et/hosts中,然后从ht…...

windows .vscode的json文件配置 CMake 构建项目 调试窗口中文设置等
一、CMake 和 mingw64的安装和环境配置 二、tasks.json和launch.json文件配置 tasks.json {"version": "2.0.0","options": {"cwd": "${workspaceFolder}/build"},"tasks": [{"type": "shell&q…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...