3、目标检测基础理论:任务定义、IoU与NMS、Anchor机制、损失函数

各位同学,欢迎来到第三章。从这章开始,我们正式进入目标检测的核心地带。

很多人一上来就撸YOLO代码,结果调参调到怀疑人生。为什么?说白了,就是基础理论没吃透。今天这章,我带你把这四个地基打牢:任务定义、IoU与NMS、Anchor机制、损失函数。这些东西搞明白了,后面写代码你会觉得“哦,原来如此”。

目标检测基础理论知识体系 目标检测基础理论 任务定义 IoU与NMS Anchor机制 损失函数 分类 + 定位 = 检测 去重 & 筛选候选框 预设先验框匹配 回归 + 分类损失

3.1 目标检测任务定义:不只是“找东西”

图像分类,就是给一张图打标签,比如“这是一只猫”。但目标检测要干两件事:分类 + 定位。你得告诉我图里有什么,还得用框把它圈出来。

我习惯把检测任务拆成两个子问题:

  • 分类子任务:判断框里是猫、狗还是背景。
  • 定位子任务:回归出框的四个坐标 (x, y, w, h)。

你想想看,一张监控画面里可能有行人、车辆、自行车。模型得同时输出每个目标的类别和位置。这就是检测和分类最本质的区别。

我的经验: 刚开始做安防项目时,我总把检测当成“高级分类”。后来发现,定位不准比分类错更致命——框偏了,报警就失效了。定位精度,才是检测的灵魂。

3.2 IoU与NMS:检测的“质检员”和“清道夫”

3.2.1 IoU:交并比

IoU,全称Intersection over Union。说白了,就是两个框的重叠程度。

计算公式很简单:

IoU = (A ∩ B) / (A ∪ B)

分子是两个框的交集面积,分母是并集面积。IoU值在0到1之间,越接近1,说明两个框重合得越好。

在项目中,我常用IoU做三件事:

  • 评估检测质量:预测框和真实框的IoU > 0.5,就算检测正确。
  • 正负样本分配:IoU > 0.7的Anchor算正样本,< 0.3的算负样本。
  • NMS去重:IoU > 阈值就干掉一个。
避坑指南: 我曾经在计算IoU时忘了处理边界情况——两个框完全不重叠时,交集为0,IoU=0。但分母不能为0,记得加个极小值epsilon(比如1e-7)。

3.2.2 NMS:非极大值抑制

模型预测时,同一个目标会输出一堆候选框。NMS的作用就是去重,只保留最好的那个。

算法流程其实很直观:

  1. 把所有框按置信度从高到低排序。
  2. 选置信度最高的框,保留它。
  3. 计算它和其他框的IoU,干掉IoU大于阈值(比如0.5)的框。
  4. 重复步骤2-3,直到没有框剩下。

嗯,这里要注意:阈值设得太小,容易漏检;设得太大,又会有重复框。我一般从0.5开始调,根据实际效果微调。

注意: NMS是串行的,在CPU上跑会很慢。YOLO系列用了很多优化,比如在GPU上并行计算IoU矩阵。如果你自己实现,记得考虑性能。

3.3 Anchor机制:给模型“打个样”

Anchor,也叫先验框。为什么需要它?

你想想看,如果让模型直接回归任意形状的框,太难了。模型不知道“框大概长什么样”。Anchor就是预设好的一组框,模型只需要在Anchor的基础上做微调。

YOLOv3/v5用的Anchor是怎么来的?

  • K-means聚类:在训练集上,对所有真实框的宽高做聚类。
  • 9个Anchor:3个尺度 × 3个长宽比,覆盖大、中、小目标。
  • 每个特征图格子:预测3个框,每个框对应一个Anchor。
特征图尺度 感受野 Anchor尺寸(举例) 适合目标
大(13×13) 大 (116,90), (156,198), (373,326) 大目标(车辆)
中(26×26) 中 (30,61), (62,45), (59,119) 中目标(行人)
小(52×52) 小 (10,13), (16,30), (33,23) 小目标(远距离)
我的习惯: 换数据集时,一定要重新聚类Anchor。用COCO的Anchor去检测交通标志,效果会打折扣。我一般写个脚本,跑一遍K-means,把新Anchor写进配置文件。

3.4 损失函数:模型学习的“指挥棒”

损失函数告诉模型:你错在哪,错得有多严重。YOLO的损失函数由三部分组成:

Loss = λcoord * Lossbox + Lossobj + Losscls

3.4.1 定位损失(Loss_box)

早期YOLO用MSE(均方误差),后来换成GIoU、CIoU。为什么?

  • MSE:对尺度敏感,大框和小框的误差量级不一样。
  • GIoU:在IoU基础上,考虑了框不相交时的梯度问题。
  • CIoU:进一步加入中心点距离和长宽比,收敛更快。

我个人推荐用CIoU。在安防场景下,行人框的长宽比变化很大,CIoU能更好地处理这种情况。

3.4.2 置信度损失(Loss_obj)

判断格子内是否有目标。用二值交叉熵(BCE Loss)。

这里有个坑:正负样本极度不平衡。一张图里可能只有几个目标,但背景格子成千上万。YOLO用了Focal Loss的思想,给难分样本更大的权重。

3.4.3 分类损失(Loss_cls)

多标签分类,也是BCE Loss。注意,YOLO对每个类别独立做二分类,而不是Softmax多分类。为什么?因为一个框可能同时属于“行人”和“骑自行车的人”,Softmax会强制互斥。

避坑指南: 我曾经调参时把λcoord设得太大,导致模型只顾着框准位置,分类一塌糊涂。后来我遵循一个原则:定位损失权重是分类损失的5-10倍,但不要超过10倍。

3.5 本章小结

这一章我们聊了四个核心概念:

  • 任务定义:检测 = 分类 + 定位。
  • IoU与NMS:评估重叠度,去重保最优。
  • Anchor机制:预设先验框,降低回归难度。
  • 损失函数:三部分损失,指挥模型学习。

这些理论,是后面所有实战章节的基石。你可能会觉得有点抽象,没关系,等我们开始写代码、跑模型时,你会反复和它们打交道。到时候再回来看这章,会有更深的理解。