目标检测实战:从 R-CNN 到 YOLO——不仅要认出是什么,还要找到在哪里

· 约 5 分钟 ·
本文目录(8 节)

图像分类回答”这张图里是什么”,目标检测回答”图里有哪些物体、分别在哪”——输出是一组边界框(bounding box)加类别。自动驾驶找车辆和行人、工业质检找缺陷、人脸识别第一步找人脸(人脸识别篇 里的 YuNet 就是检测器),全是它的应用。

前置阅读:深度学习课程 04:CNN 图像分类( backbone 与卷积基础)。

三个绕不开的核心概念

IoU(交并比):预测框和真值框的交集面积除以并集面积,衡量框得多准:

IoU=∣A∩B∣∣A∪B∣IoU = \frac{|A \cap B|}{|A \cup B|}

通常 IoU > 0.5 算”检测到了”。训练时它是回归目标的一部分,评估时它是判定对错的标准。

NMS(非极大值抑制):模型对同一个物体往往输出一堆重叠框,NMS 留下分数最高的、删掉和它 IoU 超过阈值的其余框——去重的标准流程。调参时 conf(置信度阈值)和 IoU 阈值要一起调:conf 定”多肯定才算检出”,IoU 阈值定”多重叠算同一个”。

mAP(平均精度均值):检测任务的权威指标。按置信度排序预测结果,画出每个类别的 PR 曲线、算 AP(曲线下面积),再对所有类别求平均。mAP@0.5 是 IoU 阈值 0.5 下的结果,COCO 基准还常用 mAP@[.5:.95](多阈值平均,更严格)。看论文和榜单时务必确认说的是哪个口径,两者差 20 个点很正常。

Anchor:检测的”候选框先验”

早期 YOLO 和 Faster R-CNN 都是 anchor-based:在每个特征图位置预置若干不同长宽比的锚框,模型学习”锚框要往哪调、里面是什么”。Anchor 的尺寸分布要匹配数据——标注框普遍偏窄高(行人)就该配窄高锚。YOLOv5 起引入 auto-anchor 自动聚类数据里的框尺寸;YOLOv8 之后转向 anchor-free,直接预测中心点到四边的距离,少了一组超参,训练更省心。面试被问 anchor 时讲清这条演进线即可。

两阶段 vs 单阶段:两条演进路线

两阶段(R-CNN 家族):第一阶段提候选区域(可能含物体的一两千个框),第二阶段对每个区域分类和精修。Faster R-CNN 用 RPN(区域建议网络)把候选生成也变成可学习的,精度高但速度慢,适合离线高精度场景。R-CNN → Fast R-CNN → Faster R-CNN 的演进主线是”不断把慢步骤搬进网络共享计算”:Fast 共享了卷积特征,Faster 共享了候选生成。

单阶段(YOLO / SSD):直接在特征图上密集预测所有位置的框和类别,一次前向出结果。牺牲一点精度换数量级的速度,实时场景(视频流、机器人)的唯一选择。YOLO 从 v1 到 v8+ 的迭代,主线是anchor 机制的简化、多尺度特征的强化(FPN/PAN)和训练策略的工程化,精度和两阶段的差距早已抹平。

一句话记忆:两阶段”先找再看”,单阶段”边看边找”。工程选型默认从 YOLO 起步,精度不够再考虑两阶段或更大的 YOLO 型号。

YOLO 实战:训练自己的检测器

ultralytics 把 YOLO 的工程体验做到了极致:

# pip install ultralytics
from ultralytics import YOLO

# 1. 预训练模型直接推理
model = YOLO("yolov8n.pt")
results = model("street.jpg")
for box in results[0].boxes:
    print(box.cls, box.conf.item(), box.xyxy.tolist())

# 2. 在自己的数据上微调
# 数据格式:images/ + labels/(YOLO txt:class x_center y_center w h,归一化)
model = YOLO("yolov8n.pt")
model.train(
    data="my_dataset.yaml",    # 声明训练/验证集路径与类别名
    epochs=100,
    imgsz=640,
    batch=16,
)

数据格式是最常见的卡点:YOLO 标注是每行一个物体的 txt 文件,坐标全部归一化到 [0,1]。从 LabelImg/CVAT 等标注工具导出时选对格式。

训练的实战要点

先抽样把标签画回原图,再讨论模型结构:框坐标是像素还是归一化值、类别编号是否从约定起点开始、缩放与翻转是否同步修改框?这些错误未必导致训练崩溃,却会让模型持续学习错误的位置。

  • 从预训练权重微调,不要从头训练——检测任务数据需求大,微调几百张图就能出可用模型,从头训练需要几万张起步。
  • 数据增广就是检测的半条命:马赛克(mosaic)、随机裁剪、色彩抖动是 YOLO 默认开启的。小物体多的场景注意增广别把目标裁没了。
  • 模型尺寸按延迟预算选:n/s/m/l/x 五档。边缘设备用 n,服务器追精度用 l/x。先测延迟再定型号,不要反过来。
  • 评估看 mAP 也看单类 AP:整体 mAP 掩盖小样本类别的失效,和分类任务看宏 F1 一个道理。

踩坑排查

症状原因处理
训练 loss NaN学习率过大/标注坐标越界降 lr;校验标注在 [0,1] 内
一个物体出多个框NMS 阈值不当调 conf/iou 阈值
小物体全漏检输入分辨率太低/anchor 不匹配提 imgsz;用 P2 小目标层
验证 mAP 高上线差训练/线上数据分布不同检查分辨率、光照、场景差异
标注工具导出格式错导出成 VOC/COCO 而非 YOLO转换脚本统一格式
推理慢型号过大/没半精度换小档型号;FP16/ONNX 导出

练习

  1. 用预训练 YOLO 在 10 张街景图上推理,统计各类别检出数与平均置信度。
  2. 标注 50 张自定义数据并微调,对比微调前后在验证集上的 mAP。
  3. 系统扫描 conf 阈值 [0.1, 0.9],画出精确率-召回率权衡曲线。
  4. 导出 ONNX 模型,对比 PyTorch 与 ONNX 推理的单张耗时。

面试常问

Q:IoU、NMS、mAP 分别解决什么? IoU 度量框的重合质量,是训练回归和评估判定的基础;NMS 解决同一物体多框重复;mAP 综合 PR 曲线衡量检测器在不同置信度下的整体水平。

Q:两阶段和单阶段检测器的本质区别? 两阶段先显式生成候选区域再逐个分类回归,精度优先;单阶段在特征图上密集锚点直接预测,速度优先。工程默认单阶段(YOLO 系),精度敏感且离线可用两阶段。

Q:小目标检测为什么难,怎么改进? 小目标在深层特征图上信息丢失严重。改进:提高输入分辨率、加浅层检测头(P2)、针对性增广(复制粘贴小目标)、用 FPN 多尺度融合。

Q:检测任务怎么做数据增广? 几何(翻转/缩放/裁剪——注意同步变换标注框)、色彩(HSV 抖动)、马赛克拼接(四图合一,丰富背景与尺度)、MixUp。增广必须同步更新标注坐标,这是检测增广和分类增广的关键区别。


下一篇相关阅读:图像生成:GAN、VAE 与 Diffusion 入门。

💬 评论

这套方案在哪一步卡住了?也欢迎补充你的实现方式或踩坑经验。

正在连接评论服务,首次访问可能需要几秒…