C# OpenCV机器视觉:SoftNMS非极大值抑制
嘿,你知道吗?阿强最近可忙啦!他正在处理一个超级棘手的问题呢,就好像在一个混乱的战场里,到处都是乱糟糟的候选框,这些候选框就像一群调皮的小精灵,有的重叠在一起,让阿强头疼不已。他的任务就是把这些重叠的候选框整理清楚,只留下最优秀的那些,让它们规规矩矩地排好队,为他的图像识别任务服务。
阿强听说了两种神奇的魔法 —— 非极大值抑制(NMS)和软非极大值抑制(SoftNMS),它们可以帮助他解决这个难题。这就像两个神奇的指挥官,能指挥这些候选框小精灵们听从命令,变得井然有序。
一、混乱的候选框战场
想象一下,阿强的图像里有好多候选框,每个候选框都觉得自己是最重要的,都想站在最前面,结果就是它们挤在一起,你压着我,我压着你,就像一堆挤在一起的小方块,乱成了一锅粥。这可不行啊,阿强需要从中挑选出最出色的候选框,不能让它们这样乱哄哄的。
阿强决定使用 OpenCvSharp 来施展魔法,他知道,这两种抑制方法就像两把神奇的扫帚,能把这些混乱的候选框清理干净呢 让我们来看看它们是怎么工作的吧。
二、非极大值抑制(NMS):严格的指挥官
首先登场的是 NMS,这个方法就像一个严格的指挥官,它的原则很简单:只留下最厉害的,把其他重叠的都赶走。
class NMS
{// 定义一个类来存储得分和索引 public class ScoreIndex{public float Score { get; set; }public int Index { get; set; }public ScoreIndex(float score, int index){Score = score;Index = index;}}static List<int> NmsBoxes(List<Rect> boxes, float[] scores, float iouThreshold){List<int> selectedIndices = new List<int>();int n = boxes.Count;// 将得分和索引组合在一起 List<ScoreIndex> indexedScores = new List<ScoreIndex>();for (int i = 0; i < n; i++){indexedScores.Add(new ScoreIndex(scores[i], i));}// 按得分降序排序 indexedScores.Sort((a, b) => b.Score.CompareTo(a.Score));bool[] selected = new bool[n];for (int i = 0; i < n; i++){int currentIndex = indexedScores[i].Index;if (selected[currentIndex]) continue;selectedIndices.Add(currentIndex);selected[currentIndex] = true;for (int j = i + 1; j < n; j++){int compareIndex = indexedScores[j].Index;if (selected[compareIndex]) continue;float iou = ComputeIoU(boxes[currentIndex], boxes[compareIndex]);if (iou > iouThreshold){selected[compareIndex] = true; // 抑制重叠框 }}}return selectedIndices;}static float ComputeIoU(Rect boxA, Rect boxB){// 计算交集 int x1 = Math.Max(boxA.X, boxB.X);int y1 = Math.Max(boxA.Y, boxB.Y);int x2 = Math.Min(boxA.X + boxA.Width, boxB.X + boxB.Width);int y2 = Math.Min(boxA.Y + boxA.Height, boxB.Y + boxB.Height);int interWidth = Math.Max(0, x2 - x1);int interHeight = Math.Max(0, y2 - y1);float interArea = interWidth * interHeight;// 计算并集 float boxAArea = boxA.Width * boxA.Height;float boxBArea = boxB.Width * boxB.Height;float unionArea = boxAArea + boxBArea - interArea;return interArea / unionArea;}
}
代码解析:
- 整理候选框和得分:首先,NMS 会把每个候选框的得分和索引组合在一起,就像给每个候选框小精灵贴上一个带有分数的名牌。然后,按照得分的高低给它们排好队,分数高的排在前面,这样最优秀的候选框就站在了最前面啦。接着,创建一个 selected 数组,用来标记哪些候选框已经被选中,哪些要被淘汰。
- 挑选最优候选框:从得分最高的候选框开始,把它标记为选中,放入 selectedIndices 列表中。然后,检查其他候选框,如果它们和这个选中的候选框重叠度(通过 ComputeIoU 计算)超过了 iouThreshold,就把它们标记为淘汰,就像指挥官说:“你和最优秀的重叠太多啦,你被淘汰啦!”ComputeIoU 函数会计算两个候选框的交并比(IoU),它是判断两个候选框重叠程度的重要指标哦。先找到两个框重叠部分的面积,再算出它们的并集面积,用重叠面积除以并集面积就得到了 IoU 值啦。如果 IoU 值大,说明它们重叠得多,需要处理一下。
三、软非极大值抑制(SoftNMS):温柔的协调者
接下来是 SoftNMS,它可不像 NMS 那么严格啦,它就像一个温柔的协调者,不会直接把重叠的候选框淘汰,而是会给它们一个机会,让它们的分数慢慢降低,变得不那么 “骄傲”。
class NMS
{// Soft-NMS 部分 static void SoftNMSRun(){// 示例候选框(x1, y1, x2, y2) List<Rect> boxes = new List<Rect>{new Rect(50, 50, 50, 50), // 框1 new Rect(55, 55, 50, 50), // 框2(与框1重叠) new Rect(200, 200, 50, 50) // 框3(不重叠) };// 示例得分 float[] scores = new float[] { 0.9f, 0.95f, 0.8f };// Soft-NMS 实现 List<int> selectedIndices = SoftNMS(boxes, scores, 0.5f, 0.3f);// 输出结果 Console.WriteLine("Selected boxes:");foreach (var index in selectedIndices){Console.WriteLine($"Box {index}: {boxes[index]}");}}static List<int> SoftNMS(List<Rect> boxes, float[] scores, float iouThreshold, float scoreThreshold){List<int> selectedIndices = new List<int>();int n = boxes.Count;// 将得分转换为 List List<float> scoreList = new List<float>(scores);for (int i = 0; i < n; i++){if (scoreList[i] > scoreThreshold){selectedIndices.Add(i);for (int j = i + 1; j < n; j++){float iou = ComputeIoU(boxes[i], boxes[j]);if (iou > iouThreshold){// 根据 IoU 衰减得分 scoreList[j] *= (float)Math.Exp(-(iou * iou) / 0.5);}}}}return selectedIndices;}static float ComputeIoU(Rect boxA, Rect boxB){// 计算交集 int x1 = Math.Max(boxA.X, boxB.X);int y1 = Math.Max(boxA.Y, boxB.Y);int x2 = Math.Min(boxA.X + boxA.Width, boxB.X + boxB.Width);int y2 = Math.Min(boxA.Y + boxA.Height, boxB.Y + boxB.Height);int interWidth = Math.Max(0, x2 - x1);int interHeight = Math.Max(0, y2 - y1);float interArea = interWidth * interHeight;// 计算并集 float boxAArea = boxA.Width * boxA.Height;float boxBArea = boxB.Width * boxB.Height;float unionArea = boxAArea + boxB.Area() - interArea;return interArea / unionArea;}
}
代码解析:
- 准备工作:SoftNMS 也会使用 ComputeIoU 计算候选框之间的重叠度。它把得分存储在 scoreList 中,准备开始调整这些得分。
- 温柔的调整:对于每个候选框,如果它的得分超过 scoreThreshold,就先把它加入 selectedIndices 列表。然后,检查其他候选框,如果它们和这个候选框重叠度超过 iouThreshold,不会直接淘汰它们,而是根据重叠程度 iou 来降低它们的得分哦,使用 scoreList[j] *= (float)Math.Exp(-(iou * iou) / 0.5) 这个神奇的公式,就像给它们的分数打个折扣,让它们变得不那么突出啦。
四、实战对比:NMS 和 SoftNMS 的 “战斗”
阿强开始测试啦,他准备了一些候选框,让 NMS 和 SoftNMS 分别施展魔法。
当 NMS 上场时,它会非常严格地挑选候选框,一旦发现重叠的,就毫不留情地淘汰。结果呢,留下来的候选框都是最优秀的,但是有些原本也不错的候选框可能就被彻底淘汰啦,就像一场残酷的淘汰赛。
而 SoftNMS 呢,它会让那些重叠的候选框分数降低,这样它们还有机会哦,也许经过一轮调整,有些候选框虽然分数低了点,但还是能留下来呢。这就像是一场温柔的选拔,给每个候选框一个表现的机会,只是分数会根据它们的表现有所调整。
五、实战检验:谁更厉害?
阿强把两种方法都用在自己的图像识别任务上,发现它们各有千秋哦!
- NMS:优点:处理速度快,能迅速选出最突出的候选框,非常适合那些需要快速得出结果,对准确性要求不是特别高的场景。就像短跑比赛,只选最快的选手,其他选手都被淘汰啦。缺点:可能会过于严格,有些稍微差一点的候选框可能也被误淘汰啦,可能会丢失一些有用的信息哦。
- SoftNMS:优点:更灵活,能保留更多的信息,不会一下子把有重叠的候选框都淘汰,对于一些复杂的图像,能给出更丰富的结果,就像一场综合考核,给每个选手打分,根据表现调整分数,不会轻易放弃任何一个。缺点:计算量会大一点,因为要计算得分的衰减,就像多了一些额外的考核项目,速度会慢一些。
阿强根据不同的任务,开始灵活使用这两种方法啦。有时候他需要快速筛选,就用 NMS;有时候需要更细致的结果,就用 SoftNMS。
“哈哈,有了这两个神奇的方法,我再也不怕候选框小精灵们捣乱啦!” 阿强高兴地说。
从那以后,阿强在图像处理的世界里更加得心应手,他的图像识别任务变得越来越出色,大家都对他刮目相看呢。而 NMS 和 SoftNMS 这两个魔法,也成了他手中的秘密武器,帮助他在图像处理的战场上屡战屡胜哦 你是不是也觉得它们很神奇呀?快来和阿强一起,用它们解决你的图像处理难题吧
相关文章:

C# OpenCV机器视觉:SoftNMS非极大值抑制
嘿,你知道吗?阿强最近可忙啦!他正在处理一个超级棘手的问题呢,就好像在一个混乱的战场里,到处都是乱糟糟的候选框,这些候选框就像一群调皮的小精灵,有的重叠在一起,让阿强头疼不已。…...
kamailio关于via那点事
如果kamailio作为代理服务器,在转到目的路由时 不删除原始的via信息 会造成信息泄露 如果 Kamailio 作为代理服务器(SIP Proxy)在转发 SIP 请求时不删除原始的 Via 信息,这确实可能会造成信息泄露。 📌 为什么不删除 …...

[MFC] 使用控件
介绍如何使用控件,以及如何获取控件中的数值 check Box 添加点击事件,即选中和取消选中触发的事件 第一种方式是按照如下方式第二种方式是直接双击点击进去 void CMFCApplication1Dlg::OnBnClickedCheckSun() {// TODO: 在此添加控件通知处理程序代…...

【探索未来科技】2025年国际学术会议前瞻
【探索未来科技】2025年国际学术会议前瞻 【探索未来科技】2025年国际学术会议前瞻 文章目录 【探索未来科技】2025年国际学术会议前瞻前言1. 第四届电子信息工程、大数据与计算机技术国际学术会议( EIBDCT 2025)代码示例:机器学习中的线性回…...

使用wpa_supplicant和wpa_cli 扫描wifi热点及配网
一:简要说明 交叉编译wpa_supplicant工具后会有wpa_supplicant和wpa_cli两个程序生产,如果知道需要连接的wifi热点及密码的话不需要遍历及查询所有wifi热点的名字及信号强度等信息的话,使用wpa_supplicant即可,否则还需要使用wpa_…...

Sealos的k8s高可用集群搭建
Sealos 介绍](https://sealos.io/zh-Hans/docs/Intro) Sealos 是一个 Go 语言开发的简单干净且轻量的 Kubernetes 集群部署工具,能很好的支持在生产环境中部署高可用的 Kubernetes 集群。 Sealos 特性与优势 支持离线安装,工具与部署资源包分离&#…...
Android和DLT日志系统
1 Linux Android日志系统 1.1 内核logger机制 drivers/staging/android/logger.c static size_t logger_offset( struct logger_log *log, size_t n) { return n & (log->size - 1); } 写的off存在logger_log中(即内核内存buffer)&am…...

【openresty服务器】:源码编译openresty支持ssl,增加service系统服务,开机启动,自己本地签名证书,配置https访问
1,openresty 源码安装,带ssl模块 https://openresty.org/cn/download.html (1)PCRE库 PCRE库支持正则表达式。如果我们在配置文件nginx.conf中使用了正则表达式,那么在编译Nginx时就必须把PCRE库编译进Nginx…...

如何将网站提交百度收录完整SEO教程
百度收录是中文网站获取流量的重要渠道。本文以我的网站,www.mnxz.fun(当然现在没啥流量) 为例,详细讲解从提交收录到自动化维护的全流程。 一、百度收录提交方法 1. 验证网站所有权 1、登录百度搜索资源平台 2、选择「用户中心…...

【STM32】ADC|多通道ADC采集
本次实现的是ADC实现数字信号与模拟信号的转化,数字信号时不连续的,模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法,使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时,0~ 3.3v(模拟信…...
蓝桥杯算法日记|贪心、双指针
3412 545 2928 2128 贪心学习总结: 1、一般经常用到sort(a,an);【a[n]】排序,可以给整数排,也可以给字符串按照字典序排序 2、每次选最优 双指针 有序数组、字符串、二分查找、数字之和、反转字…...
ArcGIS Pro SDK (二十七)自定义许可
ArcGIS Pro SDK (二十七)自定义许可 环境:Visual Studio 2022 + .NET6 + ArcGIS Pro SDK 3.0 文章目录 ArcGIS Pro SDK (二十七)自定义许可1 在Config.xaml中添加扩展配置2 在Module1.cs中实现接口IExtensionConfig1 在Config.xaml中添加扩展配置 <modules><inse…...

通过客户端Chatbox或OpenwebUI访问识别不到本地ollama中的模型等问题的解决
Chatbox和Open WebUI 等无法获取到 Ollama里的模型,主要是由以下原因导致: Ollama 服务未正确暴露给 Docker 容器或客户端模型未正确下载或名称不匹配网络配置或权限问题 排查以上问题的思路首先排查ollama服务是否启动,然后再看端口号 使…...
速度超越DeepSeek!Le Chat 1100tok/s闪电回答,ChatGPT 4o和DeepSeek R1被秒杀?
2023年,当全球科技界还在ChatGPT引发的AI狂潮中沉浮时,一场来自欧洲的"静默革命"正悄然改变游戏规则。法国人工智能公司Mistral AI推出的聊天机器人Le Chat以"比ChatGPT快10倍"的惊人宣言震动业界,其背后承载的不仅是技术…...

JVM速成=。=
JVM跨平台原理 跨平台:一次编译,到处运行 本质:不同操作系统上运行的JVM不一样,只需要把java程序编译成一份字节码文件,JVM执行不同的字节码文件。 Java是高级语言,提前编译一下(变成字节码文件…...
Packer 手动修复安装腾讯云插件
文章目录 Packer [腾讯云插件文档](https://developer.hashicorp.com/packer/integrations/hashicorp/tencentcloud) 提供的版本:v1.2.0,目前 Packer 构建镜像时,不支持现有2种[硬盘类型](https://www.tencentcloud.com/zh/document/product/…...

学习总结三十
下头论文 # P10605 下头论文 题目背景 莲子一直在苦恼关于论文的灵感。她为此花了太多时间,以至于没有时间理会她的伙伴梅莉。 题目描述 一天,莲子发现了一个绝妙的点子,并希望通过实验等过程将其完善。具体来说,她需要依次完成 n…...

开发完的小程序如何分包
好几次了,终于想起来写个笔记记一下 我最开始并不会给小程序分包,然后我就各种搜,发现讲的基本上都是开发之前的小程序分包,可是我都开发完要发布了,提示我说主包太大需要分包,所以我就不会了。。。 好了…...
Flutter PIP 插件 ---- Android
在 Flutter Android 应用中实现画中画功能 画中画(Picture-in-Picture, PiP)模式允许您的应用在一个固定在屏幕角落的小窗口中运行,同时用户可以与其他应用进行交互。本指南将介绍如何在 Flutter Android 应用中实现画中画功能,包括其局限性和解决方案。 项目地址 flutter_p…...
【20250211】字符串:459.重复的子字符串
#方法一:暴力求解法 # class Solution: # def repeatedSubstringPattern(self, s): # n len(s) # substr "" # #只重复一次不算“重复多次” # if n < 1: # return False # else: # …...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...