当前位置: 首页 > news >正文

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;}
}

代码解析:

  1. 整理候选框和得分:首先,NMS 会把每个候选框的得分和索引组合在一起,就像给每个候选框小精灵贴上一个带有分数的名牌。然后,按照得分的高低给它们排好队,分数高的排在前面,这样最优秀的候选框就站在了最前面啦。接着,创建一个 selected 数组,用来标记哪些候选框已经被选中,哪些要被淘汰。
  2. 挑选最优候选框:从得分最高的候选框开始,把它标记为选中,放入 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;}
}

代码解析:

  1. 准备工作:SoftNMS 也会使用 ComputeIoU 计算候选框之间的重叠度。它把得分存储在 scoreList 中,准备开始调整这些得分。
  2. 温柔的调整:对于每个候选框,如果它的得分超过 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非极大值抑制

嘿&#xff0c;你知道吗&#xff1f;阿强最近可忙啦&#xff01;他正在处理一个超级棘手的问题呢&#xff0c;就好像在一个混乱的战场里&#xff0c;到处都是乱糟糟的候选框&#xff0c;这些候选框就像一群调皮的小精灵&#xff0c;有的重叠在一起&#xff0c;让阿强头疼不已。…...

kamailio关于via那点事

如果kamailio作为代理服务器&#xff0c;在转到目的路由时 不删除原始的via信息 会造成信息泄露 如果 Kamailio 作为代理服务器&#xff08;SIP Proxy&#xff09;在转发 SIP 请求时不删除原始的 Via 信息&#xff0c;这确实可能会造成信息泄露。 &#x1f4cc; 为什么不删除 …...

[MFC] 使用控件

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

【探索未来科技】2025年国际学术会议前瞻

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

使用wpa_supplicant和wpa_cli 扫描wifi热点及配网

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

Sealos的k8s高可用集群搭建

Sealos 介绍](https://sealos.io/zh-Hans/docs/Intro) Sealos 是一个 Go 语言开发的简单干净且轻量的 Kubernetes 集群部署工具&#xff0c;能很好的支持在生产环境中部署高可用的 Kubernetes 集群。 Sealos 特性与优势 支持离线安装&#xff0c;工具与部署资源包分离&#…...

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中&#xff08;即内核内存buffer&#xff09;&am…...

【openresty服务器】:源码编译openresty支持ssl,增加service系统服务,开机启动,自己本地签名证书,配置https访问

1&#xff0c;openresty 源码安装&#xff0c;带ssl模块 https://openresty.org/cn/download.html &#xff08;1&#xff09;PCRE库 PCRE库支持正则表达式。如果我们在配置文件nginx.conf中使用了正则表达式&#xff0c;那么在编译Nginx时就必须把PCRE库编译进Nginx&#xf…...

如何将网站提交百度收录完整SEO教程

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

【STM32】ADC|多通道ADC采集

本次实现的是ADC实现数字信号与模拟信号的转化&#xff0c;数字信号时不连续的&#xff0c;模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法&#xff0c;使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时&#xff0c;0~ 3.3v(模拟信…...

蓝桥杯算法日记|贪心、双指针

3412 545 2928 2128 贪心学习总结&#xff1a; 1、一般经常用到sort&#xff08;a&#xff0c;an&#xff09;&#xff1b;【a[n]】排序&#xff0c;可以给整数排&#xff0c;也可以给字符串按照字典序排序 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里的模型&#xff0c;主要是由以下原因导致&#xff1a; Ollama 服务未正确暴露给 Docker 容器或客户端模型未正确下载或名称不匹配网络配置或权限问题 排查以上问题的思路首先排查ollama服务是否启动&#xff0c;然后再看端口号 使…...

速度超越DeepSeek!Le Chat 1100tok/s闪电回答,ChatGPT 4o和DeepSeek R1被秒杀?

2023年&#xff0c;当全球科技界还在ChatGPT引发的AI狂潮中沉浮时&#xff0c;一场来自欧洲的"静默革命"正悄然改变游戏规则。法国人工智能公司Mistral AI推出的聊天机器人Le Chat以"比ChatGPT快10倍"的惊人宣言震动业界&#xff0c;其背后承载的不仅是技术…...

JVM速成=。=

JVM跨平台原理 跨平台&#xff1a;一次编译&#xff0c;到处运行 本质&#xff1a;不同操作系统上运行的JVM不一样&#xff0c;只需要把java程序编译成一份字节码文件&#xff0c;JVM执行不同的字节码文件。 Java是高级语言&#xff0c;提前编译一下&#xff08;变成字节码文件…...

Packer 手动修复安装腾讯云插件

文章目录 Packer [腾讯云插件文档](https://developer.hashicorp.com/packer/integrations/hashicorp/tencentcloud) 提供的版本&#xff1a;v1.2.0&#xff0c;目前 Packer 构建镜像时&#xff0c;不支持现有2种[硬盘类型](https://www.tencentcloud.com/zh/document/product/…...

学习总结三十

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

开发完的小程序如何分包

好几次了&#xff0c;终于想起来写个笔记记一下 我最开始并不会给小程序分包&#xff0c;然后我就各种搜&#xff0c;发现讲的基本上都是开发之前的小程序分包&#xff0c;可是我都开发完要发布了&#xff0c;提示我说主包太大需要分包&#xff0c;所以我就不会了。。。 好了…...

Flutter PIP 插件 ---- Android

在 Flutter Android 应用中实现画中画功能 画中画(Picture-in-Picture, PiP)模式允许您的应用在一个固定在屏幕角落的小窗口中运行,同时用户可以与其他应用进行交互。本指南将介绍如何在 Flutter Android 应用中实现画中画功能,包括其局限性和解决方案。 项目地址 flutter_p…...

【20250211】字符串:459.重复的子字符串

#方法一&#xff1a;暴力求解法 # class Solution: # def repeatedSubstringPattern(self, s): # n len(s) # substr "" # #只重复一次不算“重复多次” # if n < 1: # return False # else: # …...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 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 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

Python 训练营打卡 Day 47

注意力热力图可视化 在day 46代码的基础上&#xff0c;对比不同卷积层热力图可视化的结果 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…...