如何实现 YOLO 模型的实时性能
扫描二维码
随时随地手机看文章
在资源有限的边缘设备(例如 4GB 的 Jetson Orin Nano)上部署现代对象检测模型时,总是要在准确性与速度之间进行权衡。虽然像 ultralytics 这样的 Python 框架非常适合用于训练,但在推理过程中它们往往会引入较大的开销。
在这个项目中,我尝试突破 Jetson Orin Nano 的性能限制,放弃了使用 Python,转而采用纯 C++ 语言并结合 NVIDIA TensorRT 进行实现。我的目标有两个方面:
•实现 YOLO 模型的实时性能(帧率超过 30 帧/秒)。
•将新发布的 YOLOv26 与稳定的 YOLOv8 进行对比测试,以查看“端到端”架构在严格的 TensorRT 环境中是否依然适用。
挑战:在边缘计算领域,Python 与 C++ 的较量
我在 Jetson Orin Nano(4GB 内存)上进行的 Python 代码初步测试遇到了瓶颈。内存使用量很高,而 Python 的全局解释器锁(GIL)加上其他开销使得保持稳定的高帧率变得困难。为了解决这个问题,我构建了一个自定义的 C++ 推理管道,该管道负责处理:
•媒体输入/输出:OpenCV(在可能的情况下启用硬件加速)。
•预处理:CUDA 函数(缩放、归一化、CHW 转换)。
•推断:TensorRT 引擎(16 位浮点精度)
•后处理:NMS 和坐标映射的 C++ 实现。
深入探究:YOLOv26 的“奥秘”
该项目的核心实验之一是尝试部署实验性的 YOLOv26 算法。然而,我遇到了一个重大难题:置信度不一致问题。
虽然 YOLOv8 在转换为 TensorRT 时表现完美,但 YOLOv26 在 C++ 中却出现了边界框漂移和置信度分数不准确的问题。为了解其原因,我分析了这两个模型的 ONNX 图(与 YOLOv10 进行对比)。
模型架构差异
YOLOv10 / v8(优化版):ONNX 导出包含完整的后处理子图(TopK 和 Gather 操作)。输出形状通常为 1x300x6,能够实现真正的端到端无 NMS 的推理。
YOLOv26(默认导出):导出的 v26 模型输出尺寸为 1x84x8400。它缺少内置的端到端后处理子图。
结论:v26 版本所宣传的“无 NMS 处理”功能依赖于特定的 Python 侧处理方式或特定的导出参数,而这些参数目前尚未成为标准配置。在纯 TensorRT C++ 环境中,这种转而采用传统输出格式的做法导致与标准后处理流程的兼容性出现问题。
注意:为了保证该项目代码发布的稳定性,我已将 YOLOv8n 设为默认模型,因为它能提供最稳定的工业级性能。
性能基准测试
我针对三种不同的配置对推理流程进行了测试。测试结果清楚地表明,在边缘硬件上,C++ TensorRT 方法具有明显的优势。
1. Mac Mini(M 系列芯片)
CPU 推理:约 21.4 帧每秒
MPS(GPU)推理:约 20.5 帧每秒
要点:在 macOS 系统中,MPS 后端的即时帧率较高,但存在同步延迟问题,导致其视频流的平均帧率低于 CPU 的帧率。
MPS(GPU)推理:约 20.5 帧每秒
洞察:在 macOS 系统上,MPS 后端的即时帧率较高,但存在同步延迟问题,导致其视频流的平均帧率低于 CPU。
2. Jetson Orin Nano (Python + ONNX)
ONNX 运行时:约 16.0 帧每秒
Python 运行时环境和 ONNX 解释过程所产生的开销限制了其性能。
ONNX 运行时:约 16.0 帧每秒 由于 Python 运行时和 ONNX 解释过程的存在,其开销限制了性能。
3. Jetson Orin Nano (C++ + TensorRT)- 胜利者
视频推理(不显示画面):33.2 帧每秒
延迟:约 12 毫秒(端到端)
吞吐量:约 90 帧每秒(使用 trtexec 进行的原始基准测试)
通过改用 C++ 和 TensorRT,与在相同硬件上使用 Python 实现相比,我们的性能提升了约 100%,这使得其能够适用于实时机器人应用。
如何运行代码
步骤 1:导出模型
您可以使用我的脚本将 YOLOv8 模型导出为 ONNX 格式。请注意,我们使用 opset=18 以实现最大程度的兼容性。
Python
第 2 步:构建引擎
使用 trtexec 工具将 ONNX 模型转换为高度优化的 TensorRT 引擎(对于 Orin Nano 来说,建议使用 FP16 精度)。
Bash
第 3 步:编译并运行
导航至 C++ 项目目录,并使用 CMake 进行构建。
Bash
未来工作
虽然当前的系统运行着 YOLOv8 没有出现任何问题,但解决 YOLOv26 的导出问题将是接下来的工作重点。我计划:
•检查自定义的 ONNX 导出脚本,以强制包含 v26 版本中的 TopK 层。
•将这个感知模块整合到一个 ROS 2 节点中,用于我的 RoboCup 救援模拟项目。
•如果您对嵌入式人工智能的前沿领域感兴趣,欢迎自行克隆该代码库并进行贡献!
本文编译自hackster.io





