算法面试(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 用"距离惩罚"更聪明 ------

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

相关推荐
cfc12435706312 小时前
bazel编译
人工智能·机器学习
create173 小时前
IntelliJ IDEA 等软件如何与 AI 编程工具(Cursor、Windsurf、Qoder等)实现互相跳转
java·ide·人工智能·intellij-idea
兔兔爱学习兔兔爱学习3 小时前
大模型之bert变种
人工智能·深度学习·bert
DuHz3 小时前
Phi-3 技术报告:手机本地运行的高能力语言模型——论文阅读
论文阅读·人工智能·语言模型·自然语言处理·智能手机
苏纪云3 小时前
算法<java>——排序(冒泡、插入、选择、归并、快速、计数、堆、桶、基数)
java·开发语言·算法
滋滋不吱吱3 小时前
栈的进阶篇
数据结构·算法·leetcode
科技峰行者3 小时前
阿里云无影发布首个Agentic Computer形态的个人计算产品
人工智能·阿里云·ai·agent
YQ_ZJH3 小时前
Java List列表创建方法大总结
java·开发语言·数据结构·算法·list
Absinthe_苦艾酒3 小时前
golang基础语法(五)切片
开发语言·算法·golang