【树莓派-YOLOv5/v8实战】从PC端训练到边缘部署:ONNX模型转换与OpenCV推理全流程解析
1. 从零开始:YOLOv5/v8模型训练与ONNX转换
第一次接触YOLO模型部署时,我被各种格式转换和框架适配搞得晕头转向。经过多次实践,我总结出一套适合新手的完整流程。在PC端训练YOLO模型时,建议使用官方推荐的Python 3.8-3.9环境,避免版本兼容性问题。训练完成后,你会得到.pt权重文件,这是部署到边缘设备的起点。
转换ONNX模型时最容易踩的坑是输出层配置。YOLOv5的export.py脚本提供了丰富的参数,但新手往往忽略--dynamic选项。我建议首次转换时使用固定尺寸:
python export.py --weights yolov5s.pt --include onnx --img 640 --batch 1转换完成后,务必用Netron工具检查模型结构。常见的错误包括输出节点缺失、尺寸不匹配等。我曾遇到输出维度为[1,14,8400]的YOLOv8模型,这与传统YOLOv5的[1,25200,85]结构完全不同,需要特殊处理。
2. 树莓派环境配置:避坑指南
树莓派4B虽然性能强大,但armv7l架构的软件生态充满陷阱。我强烈建议使用官方64位系统,32位系统会遇到各种依赖问题。基础环境配置分三步走:
- 系统优化:首先执行
sudo raspi-config,启用摄像头接口、调整显存为128MB,超频至2GHz(需加散热片) - 依赖安装:OpenCV的完整编译需要3小时,直接使用预编译版本更高效:
sudo apt install libopencv-dev python3-opencv pip install onnxruntime==1.9.0 -i https://pypi.tuna.tsinghua.edu.cn/simple- 硬件加速:在
/boot/config.txt中添加:
gpu_mem=256 dtoverlay=vc4-fkms-v3d特别注意CSI摄像头的配置,测试时建议先用VNC远程桌面验证帧率:
import cv2 cap = cv2.VideoCapture(0) print(cap.get(cv2.CAP_PROP_FPS)) # 应显示30fps3. ONNX模型部署实战解析
OpenCV的dnn模块虽然兼容性好,但不同版本对ONNX的支持差异巨大。我的实测数据显示:
| OpenCV版本 | YOLOv5支持 | YOLOv8支持 | 推理速度(640x640) |
|---|---|---|---|
| 4.5.4 | ✓ | × | 850ms |
| 4.7.0 | ✓ | ✓ | 620ms |
| 4.8.0 | ✓ | ✓ | 580ms |
对于YOLOv8的[1,14,8400]输出,需要重写后处理逻辑:
def parse_v8_output(output): output = output[0].transpose() # [8400,14] scores = output[:,4:].max(axis=1) boxes = output[:,:4] classes = output[:,4:].argmax(axis=1) return boxes[scores>0.5], classes[scores>0.5], scores[scores>0.5]常见错误"smallbin double linked list corrupted"通常是内存溢出导致,解决方法是在推理前添加:
import resource resource.setrlimit(resource.RLIMIT_AS, (512*1024*1024, 512*1024*1024))4. 性能优化:从21秒到0.5秒的飞跃
初始部署的21秒推理速度确实令人崩溃,但通过以下优化手段可以显著提升:
模型层面:
- 使用
opset=12导出ONNX(默认opset=9效率低20%) - 添加
--simplify参数运行ONNX优化 - 尝试YOLOv5s6.0版本,其640x640输入比v8的640x480更高效
代码层面:
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) # 4B可尝试DNN_TARGET_OPENCL # 预热推理 for _ in range(3): net.forward()系统层面:
sudo nano /etc/rc.local # 在exit 0前添加 echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor最终我的树莓派4B实现了0.5秒/帧的速度,关键是把OpenCV升级到4.8.0并启用NEON指令集优化。记得在推理循环外预先分配内存:
blob = np.zeros((1,3,640,640), dtype=np.float32) net.setInput(blob) # 预分配输入张量5. 实用调试技巧与替代方案
当ONNX部署遇到顽固错误时,不妨尝试这些备选方案:
方案A:直接运行PyTorch模型
pip install torch==1.8.0 torchvision==0.9.0 -f https://download.pytorch.org/whl/torch_stable.html需要修改模型加载方式:
import torch model = torch.jit.load('yolov5s.torchscript.pt') model.eval()方案B:使用ONNX Runtime
import onnxruntime as ort sess = ort.InferenceSession('model.onnx', providers=['CPUExecutionProvider']) outputs = sess.run(None, {'images': blob})对于实时性要求高的场景,我推荐尝试YOLOv5-Lite的onnx模型,其体积只有1.3MB,在树莓派上能达到15FPS。一个有趣的发现是:使用cv2.UMat代替常规Mat能提升约8%的性能:
img = cv2.UMat(cv2.imread('test.jpg'))最后提醒大家,树莓派推理时最好关闭图形界面(sudo systemctl set-default multi-user.target),这能释放约200MB内存,使推理过程更加稳定。
