算法面试(5)------NMS(非极大值抑制)原理 Soft-NMS、DIoU-NMS 是什么?

  • 操作系统:ubuntu22.04
  • IDE:Visual Studio Code
  • 编程语言:C++11

这是一个目标检测领域的核心后处理问题,也是面试高频考点。我们从基础 NMS 原理 → 缺陷 → 改进版(Soft-NMS、DIoU-NMS) 三层递进,彻底讲透!

一、NMS(Non-Maximum Suppression,非极大值抑制)原理

✅ 核心思想:

"只保留置信度最高的框,抑制与其高度重叠的其他框。"

🧩 为什么需要 NMS?

目标检测模型(如 YOLO、Faster R-CNN)会在多个位置、多个尺度预测同一个目标,产生大量冗余框。NMS 用于去重,保留最优框。

📈 NMS 算法步骤(经典 Greedy-NMS):

假设你有一组检测框:boxes = [box1, box2, ..., boxN],每个框有 (x1, y1, x2, y2, score, class)

  • 按类别分组 → 对每个类别单独做 NMS
  • 按置信度排序 → 从高到低:score[0] > score[1] > ...
  • 循环选择:
    • 选当前最高分框 box_i,加入最终结果
    • 计算 box_i 与剩余所有框的 IoU(交并比)
    • 删除所有与 box_i 的 IoU > threshold(如 0.5)的框
  • 重复步骤 3,直到无框可选

⚙️ IoU 计算公式:

bash 复制代码
IoU = Area(Intersection) / Area(Union)

🖼️ 举个栗子 🌰:

你检测到 5 个"狗"的框,置信度分别为:0.95, 0.9, 0.8, 0.7, 0.6

  • 选 0.95 的框 → 计算它和剩下 4 个框的 IoU
  • 假设 0.9 和 0.8 的框 IoU > 0.5 → 删除
  • 剩下 0.7 和 0.6 → 选 0.7 → 计算 IoU → 删除 0.6(如果重叠)
  • 最终保留:0.95 和 0.7 的框

二、经典 NMS 的缺陷

  • "一刀切"抑制:

    • 只要 IoU > 阈值,不管置信度多高,一律删除 → 可能误删正确框
    • 🌰 两个挨着的同类物体(如两匹并排的马),高分框可能抑制另一个高分框!
  • 只考虑重叠,不考虑位置质量:

    • 两个框 IoU 高,但一个定位准,一个定位偏 → 应该保留更准的,但 NMS 只看分数
  • 阈值敏感:

    • 阈值高 → 漏删(冗余框多)
    • 阈值低 → 误删(漏检)

三、改进版 1:Soft-NMS(2017)

论文:Improving Object Detection With One Line of Code

✅ 核心思想:

不直接删除重叠框,而是"降低其置信度",让它们在后续排序中自然被淘汰。

🧩 算法步骤:

  • 同样按置信度排序
  • 选最高分框 M,加入结果
  • 对每个剩余框 bi:
    • 计算 IoU(M, bi)
    • 不删除,而是衰减其置信度:
bash 复制代码
 # 线性衰减(原始论文)
    if IoU > threshold:
        score_bi = score_bi * (1 - IoU)

    # 高斯衰减(更常用)
    score_bi = score_bi * exp(-IoU² / sigma)
  • 重新按新分数排序,重复

✅ 优势:

  • 保留更多可能正确的框(尤其密集目标)
  • 减少"高分框误删高分框"的问题
  • 只需改一行代码!

📉 缺点:

  • 不能完全解决定位不准的问题
  • 衰减策略需调参(sigma)

四、改进版 2:DIoU-NMS(2020)

论文:Distance-IoU Loss: Faster and Better Learning for Bounding Box Regression

✅ 核心思想:

在 NMS 阶段,不仅看 IoU,还看两个框"中心点距离" ------ 定位更准的框应该被保留!

🧩 DIoU 公式回顾:

bash 复制代码
DIoU = IoU - (ρ² / c²)


其中:
- ρ² = 中心点欧式距离的平方
- c² = 包围两个框的最小闭包矩形的对角线长度平方

→ DIoU 越大,表示两个框重叠高 + 中心点越近 → 越相似

🔄 DIoU-NMS 做法:

在 NMS 的抑制判断中,用 DIoU 替代 IoU:

python 复制代码
if DIoU(box_i, box_j) > threshold:
    delete box_j

或者更常见的是:

用 DIoU 作为排序或加权依据,结合置信度

例如 YOLOv5/v7 中的 DIoU-NMS:

python 复制代码
# 用 DIoU 加权分数,再排序
score_j = score_j * (1 - DIoU(box_i, box_j))  # DIoU越大,惩罚越大

✅ 优势:

  • 抑制时考虑定位质量(中心点距离)
  • 对遮挡、密集目标更友好
  • 与 DIoU Loss 配套使用,端到端优化

🆚 五、三种 NMS 对比表

方法 核心机制 优点 缺点 适用场景
NMS IoU > 阈值 → 直接删除 简单高效 误删高分框,密集目标差 通用,实时系统
Soft-NMS IoU > 阈值 → 衰减分数 保留更多正确框,密集目标好 需调参,计算略增 医疗、遥感、密集检测
DIoU-NMS 用 DIoU 衡量相似度 → 抑制 考虑定位质量,更合理 依赖 DIoU 计算 高精度检测(YOLOv5/v7 默认)

📌 YOLOv8 默认使用 CIoU-NMS(类似 DIoU,增加长宽比约束),进一步优化定位。

💡 六、面试加分回答(STAR 法则)

"在我们的密集人流检测项目中,使用传统 NMS 导致相邻行人框被误删,漏检率达 12%。改用 Soft-NMS

后,通过高斯衰减保留重叠高分框,漏检率降至 5%。后续升级 YOLOv7 后,采用

DIoU-NMS,综合考虑重叠度和中心点距离,漏检率进一步降至 2%,且无额外调参。"

✅ 总结一句话:

NMS 用 IoU 去重,Soft-NMS 用"衰减分数"更温柔,DIoU-NMS 用"距离惩罚"更聪明 ------

三者演进的核心是从"暴力删除"到"智能筛选"。

相关推荐
abcefg_h13 小时前
链表算法---基本算法操作(go语言版)
算法·链表·golang
小O的算法实验室13 小时前
2022年IEEE TITS SCI2区TOP,基于切线交点和目标引导策略的无人机自主路径规划,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
机器之心13 小时前
全球第二、国内第一!最强文本的文心5.0 Preview一手实测来了
人工智能·openai
FreeCode14 小时前
LangChain1.0智能体开发:运行时(Runtime)
人工智能·langchain·agent
柳安忆14 小时前
【论文阅读与项目复现】Hypothesis Generation with Large Language Models
论文阅读·人工智能·语言模型
汉克老师14 小时前
CCF--LMCC大语言模型能力认证官方样题(第一赛(青少年组)第二部分 程序题 (26--30))
人工智能·语言模型·自然语言处理·lmcc
Mr_Oak14 小时前
【multi-model】moco系列&SimCLR&BEiT
人工智能·深度学习·神经网络·算法·计算机视觉·transformer·对比学习
小白跃升坊14 小时前
信息检索类智能体构建范式
人工智能·ai·全文检索·智能体
广州服务器托管14 小时前
WIN11.26H1.27982.1中简优化版 45进程(2025.11.8)
运维·人工智能·计算机网络·云计算·可信计算技术
FreeCode14 小时前
LangChain1.0智能体开发:安全防护机制
人工智能·langchain·agent