Day 14: 目标检测 (Object Detection)
摘要:不仅要问“图里有什么?(Classification)”,还要问“它在哪里?(Localization)”。目标检测是自动驾驶和安防的核心技术。本文将带你梳理从 Two-stage (Faster R-CNN) 到 One-stage (YOLO) 的演进路线,并彻底搞懂 IOU、NMS 和 Anchor 这些核心概念。
1. 核心概念扫盲
在讲模型之前,必须先懂这三个术语。
1.1 IOU (Intersection over Union)
- 含义:交并比。用来衡量两个框重叠程度的指标。
- 公式:IoU = 交集面积 并集面积 \text{IoU} = \frac{\text{交集面积}}{\text{并集面积}}IoU=并集面积交集面积
- 用途:
- 训练时:区分正负样本。PASCAL VOC 默认阈值为 0.5(人眼感觉框得还行的阈值)。现在 COCO 标准更严,会计算 AP@0.5:0.95(要求极高)。
- 测试时:用来去重(NMS)。
- Loss 计算:现在常用
1 - IoU或 CIoU 作为回归损失。
1.2 NMS (Non-Maximum Suppression)
- 问题:模型可能会对着同一只猫预测出 10 个框,每个框都挺准。我们只需要保留最好的那一个。
- 算法流程:
- 把所有框按置信度从高到低排序。
- 选出得分最高的框 A,把它当作“最终赢家”。
- 把剩下所有框里,和 A 的 IoU 超过阈值(如 0.5)的框全部删掉(因为它们和 A 重叠度太高,大概率是重复预测)。
- 循环:现在 A 搞定了,剩下的框里选个分最高的 B 当新老大,重复步骤 3,直到所有框都被处理完。
1.3 Anchor (锚框)
- 痛点:直接预测框的坐标( x , y , w , h ) (x, y, w, h)(x,y,w,h)很难收敛,因为框的长宽变化太大了。
- 解决:预先设定好一堆固定大小的参考框 (Anchor)(比如长的、方的、扁的)。
- 模型不预测绝对坐标,只预测相对偏移量 (Offset)。
- “在那个长条形的 Anchor 基础上,稍微变宽一点点”,这样模型更容易学。
2. Faster R-CNN (Two-stage 王者)
Two-stage 的意思是检测分两步走:先找哪里可能有物体,再精细判断是什么。
2.1 RPN (Region Proposal Network)
- 任务:RPN 是一个“筛选器”。它在图上均匀撒下成千上万个 Anchor,只关心**“这里有没有物体”**(二分类),不关心具体是猫还是狗。
- 输出:它会选出几千个可能包含物体的框,称为Proposals。
2.2 ROI Pooling
- RPN 选出来的框大小不一(有的 20x20,有的 100x50)。
- 但后面的分类网络需要固定输入(比如 7x7)。
- ROI Pooling:把特征图上对应区域“抠”出来,强制池化成固定的7 × 7 7 \times 77×7大小。
3. YOLO (You Only Look Once)
One-stage 的代表,主打快。它把检测问题变成了一个端到端的回归问题。
3.1 核心思想:网格划分 (Grid)与分包责任制
YOLO 的核心在于它不需要 RPN 那样的预选框过程,而是直接把图切成S × S S \times SS×S个网格(比如7 × 7 7 \times 77×7)。
“中心点”规则:
- 规则:如果一个物体(比如狗)的几何中心点落在了某个网格里,这个网格就全权负责预测这只狗。
- 通俗理解:这就好比“分包责任制”。为了防止多个格子抢着预测同一只狗(导致重复框),YOLO 强制规定:只有中心点落脚的那个地盘的主人,才是这只狗的唯一负责人。
- 旁边的格子:即使压到了狗的尾巴,只要中心点不在它那儿,它就只负责预测背景(或者预测中心点在它那儿的其他物体)。
3.2 预测具体是怎么做的?
每个网格会直接输出一个长长的向量,包含:
- B 个框的坐标:( x , y , w , h ) (x, y, w, h)(x,y,w,h)。
- 置信度 (Confidence):这格子里有物体的概率× \times×预测框的 IoU。
- C 个类别的概率:是猫的概率、是狗的概率…
3.3 YOLO vs Faster R-CNN:两种流派的本质对决
| 特性 | Faster R-CNN (Two-stage) | YOLO (One-stage) |
|---|---|---|
| 核心逻辑 | 先筛选,后精修。RPN 负责找框,Head 负责分类。 | 一步到位。网格直接回归出框和类别。 |
| 预测方式 | 基于 Anchor 机制,对每个 Anchor 做二分类 + 回归。 | 基于 Grid 机制,每个网格负责中心点落在其中的物体。 |
| 速度 | 慢(需要运行 RPN 和 Head 两次网络)。 | 快(只需要运行一次 CNN)。 |
| 为什么这么设? | 追求极致的准确率。分两步走能过滤掉绝大部分背景,让 Head 专注于难分类的样本。 | 追求极致的速度和全局视野。网格机制简单粗暴,利用 CNN 的全局感受野。 |
思考:Faster R-CNN 能不能也用网格?其实 RPN 本质上也是在特征图的每个点(网格)上生成 Anchor,但它只做简单的二分类。如果 RPN 直接把分类也做了,那它就变成了类似 YOLO/SSD 的 One-stage 检测器了。
4. FPN (Feature Pyramid Network)
这是解决多尺度检测(大物体、小物体同时存在)的神器。
- 问题:
- 深层特征图(小图):语义强(知道是猫),但分辨率低(看不清位置,小物体消失)。
- 浅层特征图(大图):分辨率高(细节丰富),但语义弱(不知道是啥)。
- 解决:自顶向下的融合
- 上采样 (Upsample):把深层的小图放大(比如 2 倍),让它和浅层的大图一样大。
- 元素级相加 (Element-wise Add):把放大后的深层图(有语义)和浅层图(有细节)加起来。
- 效果:这就好比把一张“模糊的彩色图”叠加在“清晰的黑白轮廓图”上,得到了一张既有语义又有细节的特征图,对小物体检测极其友好。
5. 损失函数 (Loss Function)
检测任务的 Loss 通常由三部分组成:L = L c l s + L o b j + L b o x L = L_{cls} + L_{obj} + L_{box}L=Lcls+Lobj+Lbox
- 分类 Loss (L c l s L_{cls}Lcls):预测类别的准确度(通常用交叉熵)。
- 置信度 Loss (L o b j L_{obj}Lobj):
- 正样本(网格有物体):希望置信度趋近 1(或真实 IoU)。
- 负样本(网格是背景):希望置信度趋近 0。
- 回归 Loss (L b o x L_{box}Lbox):框准不准?
- 早期:用 MSE(均方误差)算( x , y , w , h ) (x,y,w,h)(x,y,w,h)的差值。
- 现代:直接用 IoU 相关 Loss(如CIoU Loss),因为它直接优化重叠度,且考虑了中心点距离和长宽比。
6. 代码实践:计算 IOU
importtorchdefbox_iou(box1,box2):""" 计算两个框的 IoU box1: [N, 4] (x1, y1, x2, y2) box2: [M, 4] (x1, y1, x2, y2) Returns: [N, M] """# 1. 计算交集 (Intersection)# max(x1), max(y1)lt=torch.max(box1[:,None,:2],box2[:,:2])# min(x2), min(y2)rb=torch.min(box1[:,None,2:],box2[:,2:])# 宽高 = rb - lt,如果负数则说明没重叠,设为0wh=(rb-lt).clamp(min=0)inter=wh[:,:,0]*wh[:,:,1]# [N, M]# 2. 计算并集 (Union)area1=(box1[:,2]-box1[:,0])*(box1[:,3]-box1[:,1])area2=(box2[:,2]-box2[:,0])*(box2[:,3]-box2[:,1])# Union = A + B - Intersectionunion=area1[:,None]+area2-interreturninter/union7. 总结
- Faster R-CNN:两步走,RPN 提建议,Head 做精修。精度高,适合打比赛。
- YOLO:一步到位,网格直接预测。速度快,适合工业落地。
- FPN:让模型同时看清蚂蚁和大象。
- IoU/NMS:检测任务的基石算法。
参考资料
- Faster R-CNN Paper
- YOLOv3 Paper