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

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 这两个魔法,也成了他手中的秘密武器,帮助他在图像处理的战场上屡战屡胜哦 你是不是也觉得它们很神奇呀?快来和阿强一起,用它们解决你的图像处理难题吧


http://www.kler.cn/a/542209.html

相关文章:

  • 5-R循环
  • 关于arm
  • 基于Kotlin中Flow扩展重试方法
  • java和vue开发的图书馆借阅管理系统小程序
  • 免费在腾讯云Cloud Studio部署DeepSeek-R1大模型
  • 循环神经网络学习01——transformer:输入部分-嵌入层位置编码
  • extern关键字和 extern “C“ 的作用
  • 【算法】动态规划专题⑪ —— 区间DP python
  • 构建资源池化与降本增效
  • Linux服务管理操作命令-systemctl命令
  • ZZNUOJ(C/C++)基础练习1091——1100(详解版)⭐
  • JavaScript设计模式 -- 单例模式
  • ADB详细教程
  • 【leetcode】双指针:移动零 and 复写零
  • C++ STL容器之list的使用及复现
  • 使用 POI-TL 和 JFreeChart 动态生成 Word 报告
  • 2.11寒假作业
  • FTP服务端搭建:“文件”存储破烂站
  • 评估多智能体协作网络(MACNET)的性能:COT和AUTOGPT基线方法
  • 第36天:安全开发-JavaEE应用第三方组件Log4j日志FastJson序列化JNDI注入
  • FastExcel + Java:打造高效灵活的Excel数据导入导出解决方案
  • 高等代数笔记—线性变换
  • MyBatis-Plus-Join (MPJ) 框架介绍
  • PostCSS和PurgeCSS如何具体应用于我的项目?
  • Vue事件处理 - 事件修饰符
  • 什么是Java虚拟机(JVM)?它的作用是什么?