4. 目标检测算法实战:YOLO系列、Faster R-CNN、CenterNet、模型训练与调优、ONNX导出与TensorRT部署
目标检测,说白了就是让算法在图像里找到物体,并且框出它的位置。这是自动驾驶感知的基石。你想想看,如果连车、人、障碍物都检测不准,后面的跟踪、预测、规划全白搭。
这一章,我带你过一遍实际项目中用得最多的几种检测算法。不是纯讲理论,而是结合我踩过的坑,聊聊怎么选、怎么训、怎么部署。
4.1 三大流派:Anchor-Based、Anchor-Free、两阶段
先理清脉络。目前主流的目标检测,大致分三类:
- YOLO系列:一阶段,Anchor-Based。速度快,部署友好。我项目里80%的场景首选它。
- Faster R-CNN:两阶段,精度高。但慢。适合离线分析或对精度要求极高的场景。
- CenterNet:一阶段,Anchor-Free。不用预设锚框,对遮挡和小目标有奇效。
怎么选?我个人的习惯是:实时性要求高,选YOLO;精度优先且算力够,选Faster R-CNN;目标尺度变化大或遮挡严重,试试CenterNet。
核心逻辑图:目标检测算法选型决策
4.2 YOLO系列实战:从v5到v8
YOLO现在迭代到v8了,但底层逻辑没变。我目前主力用的是YOLOv8,因为它训练更稳,导出ONNX也更顺。
训练一个YOLO模型,核心就几步:
- 数据准备:标注格式转成YOLO的txt格式。每行:class_id, x_center, y_center, width, height(归一化)。
- 配置文件:yaml文件里写数据集路径、类别数、类别名。
- 训练命令:
yolo train model=yolov8n.pt data=coco128.yaml epochs=100 imgsz=640 - 验证:
yolo val model=runs/train/exp/weights/best.pt data=coco128.yaml
我的经验:训练时imgsz别设太大。640x640够用,再大反而容易过拟合,推理也慢。我曾经在项目里设了1280,结果mAP只涨了0.5%,推理时间翻了一倍。划不来。
4.3 Faster R-CNN:精度天花板
Faster R-CNN分两步:RPN(区域提议网络)先找候选框,再分类+回归。精度确实高,但速度是硬伤。
我一般在两种情况下用它:
- 需要检测极小目标(比如远距离行人)
- 做离线数据挖掘,用高精度模型给自动标注打底
训练时注意:RPN的anchor尺寸一定要根据你的目标分布来调。默认的anchor是针对COCO的,换成自动驾驶场景,车和人的尺度完全不同。
# 调整RPN anchor示例(mmdetection配置)
anchor_generator=dict(
type='AnchorGenerator',
scales=[2, 4, 8], # 根据目标大小调整
ratios=[0.5, 1.0, 2.0],
strides=[4, 8, 16, 32, 64])
4.4 CenterNet:无锚框的另类思路
CenterNet把检测当成关键点估计来做。输出一个热力图,峰值位置就是目标中心。好处是不用调anchor,对遮挡和重叠目标更鲁棒。
但有个坑:CenterNet对下采样倍数很敏感。我试过用stride=4,小目标召回率明显提升,但显存也涨得厉害。需要权衡。
避坑指南:我曾经在CenterNet里直接用默认的Hourglass-104骨干网络,结果训练了三天还没收敛。后来换成DLA-34,速度快了5倍,精度只降了1%。选骨干网络时,别盲目追求大模型。
4.5 模型训练与调优:那些年我踩过的坑
训练模型,说白了就是调参。但有几个关键点,我每次都会检查:
| 参数 | 推荐值 | 我的踩坑记录 |
|---|---|---|
| 学习率 | 0.001 ~ 0.01(带warmup) | 设0.1直接梯度爆炸,loss变NaN |
| Batch Size | 16 ~ 64(看显存) | bs=8时训练震荡,bs=32后稳定 |
| 数据增强 | Mosaic + MixUp + HSV抖动 | 增强太猛,模型学不到真实特征 |
| 早停 | patience=20个epoch | 不设早停,过拟合到怀疑人生 |
还有一个容易被忽略的点:类别不平衡。自动驾驶里,车辆样本远多于行人。我习惯用Focal Loss或者给每个类别设不同的loss权重。
4.6 ONNX导出与TensorRT部署
模型训好了,得上车。ONNX是中间格式,TensorRT是推理引擎。流程很简单:
- PyTorch模型 → ONNX(用torch.onnx.export)
- ONNX → TensorRT引擎(用trtexec或Python API)
- 加载引擎,推理
但这里坑最多。我列几个常见的:
- 动态batch:导出ONNX时设dynamic_axes,否则只能固定batch=1。
- FP16精度:TensorRT支持FP16,但有些算子会掉精度。我习惯先跑一遍FP32,再对比FP16的误差。
- 自定义算子:YOLO的NMS在TensorRT里需要插件。我直接用TensorRT自带的EfficientNMS,省事。
# ONNX导出示例(YOLOv8)
import torch
model = torch.load('best.pt', map_location='cpu')
model.eval()
dummy_input = torch.randn(1, 3, 640, 640)
torch.onnx.export(
model, dummy_input, 'model.onnx',
dynamic_axes={'images': {0: 'batch'}},
opset_version=17,
input_names=['images'],
output_names=['output'])
我的习惯:导出ONNX后,先用onnxruntime跑一遍,确认输出和PyTorch一致。再转TensorRT。这样能快速定位问题,不用等到上车才发现。
嗯,这一章内容不少。从算法选型到训练调优,再到部署落地,每一步都有讲究。你想想看,一个检测模型从论文到实车,中间要过多少关?数据、训练、导出、部署,哪一环出问题,整个感知系统就崩了。
我见过太多团队,模型训得漂漂亮亮,一上TensorRT就崩。或者精度很高,但推理速度不够。所以,从一开始就要想好部署。选算法时,别只看mAP,还要看推理延迟、显存占用、算子兼容性。
这些经验,都是真金白银换来的。希望你能少走弯路。
本章核心要点:
- YOLO适合实时场景,Faster R-CNN适合高精度,CenterNet适合遮挡场景
- 训练时注意学习率、batch size、数据增强的平衡
- ONNX导出要设dynamic_axes,TensorRT部署要验证FP16精度
- 从选型到部署,全链路考虑,别只盯着训练精度
可可精品资料库