共计 1614 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
在 21 届智能车竞赛中,人工智能赛题要求参赛车辆在复杂环境下实时检测交通标志、障碍物等目标。传统的目标检测模型(如 Faster R-CNN、YOLOv3)在 Jetson Nano 等边缘设备上运行时,面临两大核心问题:

- 高延迟:原始模型计算量庞大,导致推理速度低于 10FPS,无法满足实时性要求(竞赛要求≥25FPS)
- 内存瓶颈:模型参数量大,边缘设备显存(通常 4GB)容易被撑爆,引发 OOM 错误
技术选型
针对边缘设备的性能限制,我们对轻量化模型进行了横向对比测试:
| 模型 | 输入尺寸 | mAP@0.5 | 推理时延(ms) | 内存占用(MB) |
|---|---|---|---|---|
| YOLOv5s | 640×640 | 0.89 | 45 | 680 |
| MobileNetV3 | 320×320 | 0.82 | 28 | 210 |
| SSD-MobileNetV2 | 320×320 | 0.85 | 22 | 180 |
最终选择 SSD-MobileNetV2 的核心考量:
- 精度损失可控(相比 YOLOv5s 仅下降 4% mAP)
- 推理速度提升 2 倍,满足实时性硬指标
- 支持 TensorRT 原生加速,优化空间更大
核心实现
TensorRT 优化步骤
-
导出 ONNX 模型
# 转换 PyTorch 模型到 ONNX 格式 torch.onnx.export( model, dummy_input, "model.onnx", opset_version=11, input_names=["image"], output_names=["scores", "boxes"] ) -
生成 TensorRT 引擎(关键参数注释)
# FP16 量化 + 层融合优化 trtexec --onnx=model.onnx \ --saveEngine=model_fp16.trt \ --fp16 \ --workspace=2048 # Jetson Nano 推荐值
ROS 节点设计
采用多线程流水线架构提升吞吐量:
class DetectionNode:
def __init__(self):
# 独立线程处理检测任务
self.detector_thread = Thread(target=self.run_detection)
self.image_queue = Queue(maxsize=3) # 防止堆积
def image_callback(self, msg):
"""ROS 订阅回调(注意线程锁)"""
with self.lock:
self.image_queue.put(msg)
def run_detection(self):
while not rospy.is_shutdown():
img_msg = self.image_queue.get()
# 执行 TensorRT 推理...
性能优化
输入分辨率对比测试
| 分辨率 | FPS | mAP@0.5 | GPU 显存占用 |
|---|---|---|---|
| 320×240 | 38 | 0.83 | 1.2GB |
| 640×480 | 24 | 0.87 | 2.8GB |
最终选择 384×288 作为平衡点(32FPS@0.85mAP)
内存泄漏检测
使用 valgrind 定位问题:
valgrind --tool=memcheck \
--leak-check=full \
--show-leak-kinds=all \
./detection_node
避坑指南
- ROS 多线程安全
- 所有共享变量必须加锁(特别是 OpenCV 的 Mat 对象)
-
避免在回调函数中执行耗时操作
-
TensorRT 版本兼容
- 引擎文件 (.trt) 与 TensorRT 版本强相关
- 推荐在部署设备上直接生成引擎
扩展思考
迁移到 RK3588 平台的注意事项:
- 需要重新编译 TensorRT 插件(NPU 支持不同)
- 调整线程池大小(8 核 CPU 可并行处理更多任务)
- 利用 RKNN-Toolkit 进行 INT8 量化
整套方案已开源在 GitHub(链接见文末),包含:
– 训练好的 SSD-MobileNetV2 模型
– 完整的 ROS 功能包
– 性能测试脚本
通过这次竞赛实践,我们验证了在资源受限环境下实现实时目标检测的可行性方案。关键点在于:模型轻量化、计算图优化、以及合理的系统架构设计。这些经验同样适用于工业质检、无人机避障等边缘 AI 场景。
正文完
发表至: 未分类
近一天内
