4. NMS 阈值选择策略:IoU 阈值对检测结果的影响

聊到 NMS,最绕不开的就是那个 IoU 阈值。很多新手觉得这就是个固定值,设个 0.5 万事大吉。嗯,我刚开始也这么干过,结果被现实狠狠教育了一顿。

说白了,IoU 阈值决定了「两个框到底算不算重复」。阈值设高了,框就留得多,容易产生误检;设低了,框被砍得太狠,漏检就来了。这中间的平衡,才是调优的精髓。

核心观点: IoU 阈值没有万能值,它必须跟你的任务、数据、模型一起调。

4.1 IoU 阈值的工作原理

先简单回顾一下。NMS 的流程是这样的:

  1. 把所有检测框按置信度从高到低排序。
  2. 选置信度最高的框,保留它。
  3. 计算这个框跟剩下所有框的 IoU。
  4. 如果 IoU 大于你设定的阈值,就把那个框干掉。
  5. 重复,直到所有框都被处理过。

你看,阈值就是那个「生杀大权」的开关。阈值越大,容忍度越高,框越不容易被干掉。

我的习惯: 我一般先看数据集的标注特点。如果目标密集且相互遮挡,我会把阈值往高调;如果目标稀疏且独立,阈值可以低一些。

4.2 不同 IoU 阈值的效果对比

我在一个行人检测项目里做过对比实验,结果非常直观。这里用表格展示一下:

IoU 阈值 mAP@0.5 mAP@0.75 误检率 漏检率 典型场景
0.3 72.1% 45.3% 低 高 稀疏目标、高精度要求
0.5 78.6% 52.1% 中 中 通用场景、默认值
0.7 81.2% 56.8% 高 低 密集遮挡、小目标
0.9 76.5% 48.9% 极高 极低 几乎不抑制、易误检

看到没?阈值从 0.3 升到 0.7,mAP 在涨,但误检率也在涨。为什么会这样?因为阈值高了,很多本该被抑制的重复框留了下来,它们虽然跟真实框重叠度高,但位置有偏差,拉低了定位精度。

我曾经踩过的坑: 在一个密集人群计数任务里,我把 IoU 阈值设到 0.8,结果一个行人被检测出五六个框,误检率直接爆炸。后来才发现,密集场景下阈值不能超过 0.65。

4.3 如何选择合适的阈值

选阈值不是拍脑袋,得看你的评价指标和业务需求。我总结了一套选择策略:

4.3.1 根据评价指标选

  • 如果看重 mAP@0.5: 阈值可以设高一点(0.6-0.7),因为 mAP@0.5 对定位精度要求不高,多留几个框反而能提高召回。
  • 如果看重 mAP@0.75: 阈值得设低一点(0.4-0.5),因为高 IoU 要求框必须贴得准,重复框会拉低分数。
  • 如果看重 F1-Score: 建议在验证集上扫一遍阈值,从 0.3 到 0.8,步长 0.05,选 F1 最高的那个。

4.3.2 根据目标密度选

  • 稀疏场景(每张图 1-5 个目标): 阈值 0.4-0.5 就够了,框少,不容易误抑制。
  • 中等密度(每张图 5-20 个目标): 阈值 0.5-0.6,这是最常用的区间。
  • 密集场景(每张图 20+ 个目标): 阈值 0.6-0.7,甚至更高。但要注意,阈值超过 0.7 后误检率会飙升,需要配合置信度阈值一起调。

4.3.3 根据模型能力选

  • 高精度模型(mAP > 80%): 框的质量高,可以放心用低阈值(0.4-0.5),不会漏检。
  • 低精度模型(mAP < 60%): 框的质量差,建议用高阈值(0.6-0.7),宁可多留几个框,也别漏掉目标。
我的建议: 别只盯着一个阈值。在实际部署中,我会在验证集上跑一个阈值扫描,画出 mAP 随阈值变化的曲线,选那个「拐点」——也就是 mAP 开始下降前的那个值。

4.4 阈值选择的完整流程

下面这张图是我自己总结的阈值选择流程,每次调参我都会走一遍:

IoU 阈值选择流程图 开始调参 确定评价指标(mAP/F1) 分析目标密度(稀疏/密集) 验证集阈值扫描(0.3-0.8) 选择拐点阈值 注意事项 • 稀疏目标:0.4-0.5 • 中等密度:0.5-0.6 • 密集目标:0.6-0.7 • 高精度模型:0.4-0.5

4.5 实际调参案例

拿我最近做的一个工业缺陷检测项目来说。检测目标是 PCB 板上的微小焊点,每张图有 30-50 个目标,相互之间挨得很近。

一开始我用默认的 0.5 阈值,结果漏检率高达 15%。后来我把阈值调到 0.65,漏检率降到 5%,但误检率从 2% 升到了 8%。

怎么办?我做了两件事:

  1. 提高置信度阈值: 从 0.25 提到 0.4,把那些低置信度的误检框过滤掉。
  2. 加了一个小 trick: 对 IoU 超过 0.8 的框,直接取置信度最高的那个,其他的全部干掉。这相当于在 NMS 之后又做了一层硬过滤。

最终结果:漏检率 4%,误检率 3%,F1 从 0.82 提升到 0.91。

总结一下: IoU 阈值不是孤立的,它必须跟置信度阈值、模型能力、数据特点一起考虑。没有银弹,只有反复实验。

4.6 常见误区

  • 误区一: 阈值越高越好。错!阈值高了,误检率会失控。
  • 误区二: 所有类别用同一个阈值。错!不同类别的目标大小、密度不同,应该分开调。
  • 误区三: 只在训练集上调。错!一定要在验证集上做阈值扫描,训练集上的结果没有参考价值。
我曾经犯过的错: 在一个多类别检测任务里,我把所有类别的 IoU 阈值都设成 0.6。结果「汽车」类表现很好,但「行人」类漏检严重。后来才发现,行人目标小且密集,需要更高的阈值。从那以后,我都是按类别单独调阈值。

好了,这一章的内容就到这里。阈值选择是个细活,多跑几次实验,多看看验证集上的可视化结果,你慢慢就会找到感觉。