恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
树莓派5部署YOLOv5实战:从Ubuntu到ONNX Runtime的六关全记录
首页
资讯中心
/
树莓派5部署YOLOv5实战:从Ubuntu到ONNX Runtime的六关全记录
树莓派5部署YOLOv5实战:从Ubuntu到ONNX Runtime的六关全记录
发布时间:2026/10/5 8:30:46
上个月我把一块树莓派 5 带进了车间。车间主任盯着那块巴掌大的主板看了几秒抛出一句“就这能跑咱们训练的那个 YOLOv5”我没多解释插上电源、接好摄像头让模型开始识别产线上工人是否戴好安全帽。检测框稳稳地跟着人走主任点了头。但从“方案能跑”到“真能在车间里稳定用”中间我卡了整整六个环节每个都是实打实的坑。这篇就把这六件事从头到尾捋清楚包括 Ubuntu 安装、模型部署、供电散热、现场运维这些最容易被低估的细节。1. 为什么是树莓派 5而不是工控机或 Jetson1.1 这个车间项目到底要解决什么问题车间原来的质检方式靠人工目检人总有疲劳的时候漏检率不低。领导想上一套视觉检测但预算卡得死动辄一两万的工控机方案根本批不下来。项目需求其实很简单单路摄像头跑一个自己训练的安全帽检测模型实时在显示器上标注结果异常时输出信号。这个需求放到工业视觉里属于轻量场景不需要高帧率也不需要多路并发。关键是稳定、便宜、可维护。于是我把目光落在了单板计算机上。对比之后树莓派 5 的性价比成了最大优势——8GB 版本不到千元算力比树莓派 4 提升明显而且社区资料多到发指遇到问题几乎都能搜到答案。1.2 树莓派 5 的硬件底子够不够用树莓派 5 用的是 BCM2712 芯片四核 Cortex-A76 架构主频 2.4GHz相比树莓派 4 那套 A72 核心单核性能和内存带宽都有明显提升。8GB 内存版本跑 YOLOv5s 级别的模型内存完全不是瓶颈。我手上这块是 8GB 版本实测跑起来内存占用在 2GB 左右余量很充裕。其实一开始我也纠结过 Jetson 系列但 Jetson Orin Nano 虽然算力更强价格翻了好几倍而且供货不稳定。工控机加独立显卡的方案性能最强但体积大、功耗高、噪声大放在车间产线旁边本身就违和。树莓派 5 的定位正好卡在“能跑、便宜、够用”三个点上所以最终选它做验证部署。等你真的验证完再决定要不要升级更贵的算力平台这个路径是稳妥的。1.3 车间环境下的选型约束车间不是办公室温度高、粉尘多、电压波动大还经常没有显示器。选型的时候除了看芯片算力还要看接口是否齐全。树莓派 5 有千兆网口、双频 Wi-Fi、两个 USB 3.0、一个 CSI 摄像头接口还有个 PCIe 2.0 扩展口后面要接固态硬盘也方便。这些接口看起来普通但放在现场就是命根子。千兆网口保证远程传输检测图片不卡CSI 接口能直接接高质量摄像头USB 3.0 可以挂移动硬盘做本地存储。真到现场部署的时候你会发现多一个靠谱的千兆网口比多几十 GFLOPS 算力更管用。2. 第一关Ubuntu 24.04 装进树莓派 5没想象的那么简单2.1 为什么选 Ubuntu而不是 Raspberry Pi OS树莓派官方系统 Raspberry Pi OS 也很稳定但我训练 YOLOv5 的服务器是 UbuntuPython 环境、依赖库版本都是围绕 Ubuntu 生态配置的。在树莓派上使用 Ubuntu可以最大限度保持训练环境和部署环境的软硬件一致性避免“本地好好的上设备就崩”的经典惨案。树莓派 5 目前官方支持 Ubuntu 22.04 和 24.04 LTS。我选的是 24.04 Server 版本注意不是 Desktop。车间现场不需要桌面环境Server 版省掉 GNOME 那一大坨内存和 CPU 开销所有的交互都通过 SSH 完成资源全部留给推理程序。这一点看起来小实际影响很大。桌面版开机就吃 600MB 内存风扇呼呼转Server 版安静得多。2.2 烧录系统与首次启动的实操过程烧录工具直接用 Raspberry Pi Imager官方工具不用折腾 balenaEtcher。Imager 里选择 Ubuntu 24.04 Server会自动配置用户账户和 SSH还能预先设置 Wi-Fi非常省事。SD 卡建议用 A2 速度等级的 32GB 以上树莓派 5 的 SD 卡槽性能比前代好不少A2 卡实测读写稳定。系统烧好后插卡开机第一次启动要等几分钟Ubuntu 会自动扩容根分区。这一步有同学会卡住——等半天以为死机了其实是在做磁盘初始化耐心等即可。首启完成后我用另一台电脑 SSH 登录第一件事就是更新系统sudo apt update sudo apt upgrade -y这一步会拉取好几百个软件包建议在网络空闲时段做。树莓派 5 网口是千兆的实测下载速度能跑满几百 Mbps整个过程十几分钟搞定。2.3 装完系统后必做的三件小事第一件事是固定 IP。车间网络环境里 DHCP 分配不可控设备重启后 IP 变了远程连不上就是灾难。Ubuntu 24.04 用 Netplan 管理网络我直接编辑/etc/netplan/目录下的配置文件给有线网口设了静态地址network: version: 2 ethernets: eth0: dhcp4: false addresses: - 192.168.1.88/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: [192.168.1.1]第二件事是关掉不需要的系统服务。命令行执行systemctl list-units --typeservice --staterunning检查像 whoopsie 这类错误报告服务可以直接禁用。车间环境不需要那些花哨的崩溃报告。第三件事是给系统装基础工具git、curl、htop、screen少了哪个后面都要临时补。3. 第二关aarch64 架构下的 YOLOv5 依赖坑全在 ARM 生态里3.1 PyTorch 在 ARM64 上意外地好装树莓派 5 的 CPU 是 ARMv8.2-A 架构对应的软件生态是 aarch64。很多人在这一步心里打鼓觉得 ARM 上装 PyTorch 会很麻烦。其实不然PyTorch 官方在 PyPI 上早就提供了 aarch64 的预编译 wheel直接 pip 安装就行不需要从源码编译。cd /home/your_user python3 -m venv yolov5-env source yolov5-env/bin/activate pip install torch torchvision装完用 Python 验证一下 CUDA 是肯定没有的但 CPU 版本的 tensor 计算正常。实测树莓派 5 的四个 A76 大核跑矩阵运算比树莓派 4 快了近一倍这完全归功于芯片架构升级。不过要注意PyTorch 只是基础计算框架真正让 YOLOv5 跑起来的是它那套依赖体系。3.2 YOLOv5 仓库的依赖清单不能盲装YOLOv5 官方仓库的requirements.txt里包含很多库但直接一条pip install -r requirements.txt会出问题。首先是 OpenCVpip 默认装的opencv-python在 aarch64 上可用但处理摄像头时对 V4L2 的支持经常出幺蛾子。我后来改用opencv-python-headless因为树莓派上跑服务不需要 GUI 窗口headless 版本体积更小依赖冲突也少。其次是 protobuf 版本。新版 YOLOv5 对 protobuf 版本有严格要求装高了不行、装低了也不行直接导致import torch的时候报错。我的解决方法是先装protobuf3.20.3再装其他依赖这个版本是经过官方验证的。依赖装完并不代表万事大吉。aarch64 架构下很多预编译包没有官方 wheel比如一些图像处理库会 fallback 到源码编译一旦编译就开始“喝咖啡”。我的经验是耐心等别中断编译。中断一次下次重来来回折腾更浪费时间。3.3 OpenCV 编译的典型坑与替代方案如果你碰到 OpenCV 编译多半是opencv-python的 aarch64 wheel 版本覆盖不全。有两条路一是用 apt 装系统级 OpenCVsudo apt install python3-opencv好处是 V4L2 摄像头支持默认开启坏处是和 pip 虚拟环境里的 Python 可能对不上。我最后用的方案是 pip 装opencv-python-headless4.9.0.80再补装libcamera-dev和python3-libcamera来支持 CSI 摄像头。检测这个坑是否踩了最简单的办法是跑一下python3 -c import cv2; print(cv2.__version__)如果 import 成功再尝试python3 -c import cv2; cap cv2.VideoCapture(0); print(cap.isOpened())VideoCapture打开失败基本就是 V4L2 驱动问题。在 Ubuntu 上还要检查摄像头设备节点是否被权限限制把自己加到video用户组sudo usermod -aG video $USER这步不做CSI 摄像头死活打不开还以为是硬件坏了。4. 第三关把自己训练的 YOLOv5 模型部署进树莓派 5重点在格式转换4.1 直接跑 best.pt 会慢到怀疑人生训练环境里验证模型用的是 PyTorch 原生推理GPU 秒回。但树莓派 5 只有 CPU直接torch.load(best.pt)再跑推理YOLOv5s 在 640×640 输入下每帧要 800 毫秒到 1 秒根本没法定量检测。问题不在模型本身而在 PyTorch 的推理流程太“重”——图结构、算子调度、张量分配都有额外开销。所以部署的第一步就是把 PyTorch 模型转换成推理框架能直接调用的格式。我选择的是 ONNX Runtime它是跨平台的推理引擎对 ARM CPU 有优化而且在树莓派上能利用上 NEON 指令集推理效率比原生 PyTorch 高不少。还有一个重要原因是ONNX 格式的模型是可迁移的将来换 Jetson 或更高性能平台同一个模型文件还能用。4.2 用官方脚本导出 ONNX 文件YOLOv5 官方仓库里提供了export.py导出 ONNX 基本是一行命令的事cd yolov5 python export.py --weights /path/to/best.pt --include onnx --opset 12 --simplify导出前需要把 onnx 和 onnxsim 库装好。命令里的--simplify参数很关键它会用 onnxsim 对图结构做简化去掉一些冗余的 reshape 和 transpose 节点这些节点在推理时纯粹是浪费算力。导出后得到一个best.onnx大概十几 MB比原来的 PyTorch 权重文件小得多。在服务器上导出后用 scp 把模型传到树莓派scp best.onnx user192.168.1.88:/home/user/yolov5/4.3 在树莓派上用 ONNX Runtime 跑推理ONNX Runtime 的安装同样有现成的 aarch64 wheelpip install onnxruntime然后写推理脚本。YOLOv5 导出的 ONNX 模型输出的是三个尺度的检测头需要做后处理包括解码、置信度筛选、NMS。这个后处理代码不复杂但容易写错我先给个骨架import cv2 import numpy as np import onnxruntime as ort session ort.InferenceSession( best.onnx, providers[CPUExecutionProvider] ) input_name session.get_inputs()[0].name def preprocess(img): img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img cv2.resize(img, (640, 640)) img img.astype(np.float32) / 255.0 img np.transpose(img, (2, 0, 1))[None] return img def postprocess(outputs, conf_thres0.25, iou_thres0.45): # 根据模型输出的三个尺度节点做拼接解码 # 叠加坐标还原、置信度筛选、cv2.dnn.NMSBoxes 去重 pass cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break input_data preprocess(frame) outputs session.run(None, {input_name: input_data}) boxes postprocess(outputs) for box in boxes: x1, y1, x2, y2, conf box cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imshow(detect, frame) if cv2.waitKey(1) 0xFF ord(q): break这个脚本先跑起来在办公室和实验室里调试不会有大问题但放到车间就不只是代码的事了。先记住这一点后面第五关会专门讲现场运行。4.4 提速三板斧量化、输入尺寸、线程数ONNX Runtime 默认跑 fp32 精度推理速度实测 640×640 输入在 350 到 450 毫秒之间作为检测系统勉强能接受。但车间里要留出摄像头采集、画面显示、结果判断的余量我的目标是单帧控制在 200 毫秒以内。第一板斧是 INT8 量化。onnxruntime 提供动态量化和静态量化两种方式对 YOLOv5 这类目标检测模型静态量化效果更好需要一批校准图片。由于我训练模型时保留了验证集图片直接用它做校准数据集量化脚本大致是这样from onnxruntime.quantization import quantize_static, QuantType, CalibrationDataReader class DataReader(CalibrationDataReader): def __init__(self, images, input_name): self.images images self.input_name input_name self.idx 0 def get_next(self): if self.idx len(self.images): return None img self.images[self.idx] self.idx 1 return {self.input_name: img} quantize_static( model_pathbest.onnx, quantized_model_pathbest_int8.onnx, calibration_data_readerDataReader(cal_images, input_name), quant_formatQuantType.QInt8, )量化后模型文件又小了一半速度直接从 400 毫秒拉到 150 到 200 毫秒左右而且树莓派 5 的 CPU 对 int8 算子有额外优化效果立竿见影。第二板斧是输入尺寸。640×640 是训练时的默认输入但对固定机位的车间场景摄像头位置和检测目标的大小相对稳定我把输入降到 416×416速度又能快一半。代价是远距离小目标的召回率下降这个要通过现场实测权衡。第三板斧是给 ONNX Runtime 设置线程数。树莓派 5 是四核处理器但系统里还有其他服务全开 4 线程推理反而会导致系统卡顿。我把它限制到 3 线程推理时间只多了 20 毫秒但系统整体响应顺畅了。经过这三板斧最终效果是416×416 输入 INT8 量化单帧推理稳定在 90 到 130 毫秒之间基本可以做到 7 到 8 FPS满足车间安全帽检测这种实时性要求不高的场景。5. 第四关车间里的供电、散热与摄像头全是硬条件5.1 供电5V 最难的不是功率够不够是压降树莓派 5 官方推荐 5V/5A 的 27W 电源。在办公室实验室随便找个手机充电器都能跑但进车间就不行。产线旁边经常是 24V 工业电源直接从那里取电需要 DC-DC 降压模块。我一开始图省事用了一个 5V 3A 的旧电源结果系统开机后频繁出现闪电图标CPU 直接降频推理速度慢了整整一半。后来用示波器一量发现是线材压降问题。USB-C 线长了线阻大负载一高末端电压就掉到 4.6V 左右。解决办法是换短粗线并改用质量过硬的 5V/5A 电源。如果要从 24V 工业电源取电选 DC-DC 降压模块时要注意输出纹波劣质模块在高负载下输出的纹波会直接影响 CPU 稳定性。实测下来用官方电源最省心别折腾那些来路不明的适配器。5.2 散热不装风扇半小时就给你降频树莓派 5 的性能提升是有代价的BCM2712 满载功耗比树莓派 4 高不少。车间环境温度白天能到 30℃ 以上裸跑 YOLOv5 推理CPU 温度十分钟飚到 82℃触发降频后推理帧率肉眼可见地掉。刚上墙那会我没装风扇结果第二天去现场看整块散热片烫得不敢碰。解决方案是上主动散热。我用的官方 Active Cooler 散热器铝合金散热片加一个小鼓风机安装简单效果明显。实测满载运行温度稳定在 55℃ 左右降频基本不再发生。车间粉尘大每两周拆下来用压缩空气吹一次灰这个维护频率要有意识不然灰尘堵住风道散热器效果大打折扣。5.3 摄像头选型与固定曝光设置摄像头我用的是树莓派官方 Camera Module 3走 CSI 接口延迟低不容易受 USB 带宽波动影响。USB 摄像头在车间里最大的问题是线缆长距离传输容易受电磁干扰而 CSI 排线短方案更可靠。Camera Module 3 用 libcamera 驱动在 Ubuntu 24.04 上需要安装libcamera-apps和相应内核驱动。装完测试rpicam-hello --list-cameras能识别到相机再继续下一步。检测系统里我用 OpenCV 打开摄像头设置分辨率 1280×720、帧率 15对安全帽检测已经足够。车间灯光环境有个隐藏坑自动曝光。车间里灯光经常有频闪自动曝光会让画面亮度不停跳动模型误检率也跟着上升。我在代码里把曝光和白平衡全部固定cap cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) cap.set(cv2.CAP_PROP_FPS, 15) cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.25) # 1 表示关闭自动曝光 cap.set(cv2.CAP_PROP_EXPOSURE, 120) cap.set(cv2.CAP_PROP_AUTO_WB, 0.25)固定曝光后检测结果稳定了很多不再随车间灯光波动乱跳。6. 第五关无人值守现场稳定运行比模型精度更重要6.1 SSH 远程管理和静态 IP 的兜底方案车间里的树莓派没有显示器也没有键盘鼠标所有维护全靠 SSH。这意味着网络连接就是生命线。我之前已经配置了静态 IP但静态 IP 有个风险——如果局域网内地址冲突设备直接失联。一年的值守经验告诉我树莓派 SSH 连不上80% 是 IP 冲突或网线松动。建议哪怕是千兆网口的场景也把串口调试功能留着万一网络断了还能通过串口救回来。我额外做了一个小工具脚本开机后自动把当前 IP 写到指定的共享目录。这样就算忘了静态 IP 配置也能在管理机上看一眼设备到哪里去了。6.2 systemd 守护进程 硬件看门狗双保险就算网络没问题程序也有跑飞的时候。检测程序一旦卡死现场没人帮你点重启。所以我把推理程序写成了 systemd 服务配置了自动重启[Unit] DescriptionYOLOv5 Detection Service Afternetwork.target [Service] Typesimple Useryour_user WorkingDirectory/home/your_user/yolov5 ExecStart/home/your_user/yolov5-env/bin/python /home/your_user/yolov5/run_detection.py Restartalways RestartSec5 [Install] WantedBymulti-user.targetRestartalways保证进程退出了能自动拉起来。但程序假死比如卡在一个死循环里systemd 管不了这就要靠看门狗。树莓派 Broadcom 芯片内部有硬件看门狗在/boot/config.txt里加一行dtoverlaywatchdog然后启用内核看门狗服务sudo systemctl enable watchdog sudo systemd-tmpfiles --create --prefix /dev/watchdog配置好后系统如果长时间无响应硬件看门狗会强制重启。这套组合拳下来我连续测试过三次模拟崩溃最短 10 秒自动恢复完全不需要人到现场。6.3 日志与状态可视化无人值守不代表不闻不问。我把检测程序里的关键信息全部打到日志文件然后用一个简单的journalctl查看服务状态。同时把检测结果里的报警图片直接存到指定目录车间其他电脑通过网络共享就能看到当天报警记录。为了在车间现场有个直观反馈我还在树莓派上接了一个发光二极管检测到异常时通过 GPIO 点亮。这个小设计很朴素但现场工人非常买账看到灯亮就知道设备在干活。7. 第六关模型迭代和现场数据回流部署只是开始7.1 部署前先想好怎么采数据模型部署并不是终点。训练时的数据集和车间现场的真实场景之间必然有分布差异。如果不在现场持续收集数据模型精度只会随着环境变化越来越差。我在检测程序里加了一个“难例挖掘”逻辑当置信度低但目标明显存在或者直接漏检时就把原始帧保存到一个hard_examples目录。这个目录每天定时通过 rsync 同步到办公室服务器作为下一轮训练的素材。rsync -avz --remove-source-files user192.168.1.88:/home/user/yolov5/hard_examples/ /data/hard_examples/这样就形成了一个完整闭环现场采集 → 服务端标注 → 重新训练 → 导出 ONNX → 部署更新。整个过程不需要重新去现场改配置全在办公室远程完成。7.2 迭代一次模型要做的完整动作模型更新时不需要动系统也不需要动服务只需三步在服务器上重新训练导出新的best_int8.onnx用 scp 传到树莓派指定目录覆盖旧模型文件重启服务sudo systemctl restart yolov5-detection.service整个过程一两分钟完成期间检测服务会中断几十秒对车间影响很小。要注意的是每轮迭代后一定要在树莓派上重新做一次推理速度测试因为模型大小变化会直接影响帧率。我见过一次迭代把模型参数量翻倍导致实时性崩掉的例子。8. 最后说实话这六关走完树莓派 5 才真正算“进车间”了整套系统现在在产线上连续跑了一个多月安全帽检测准确率稳定在 96% 左右误报基本集中在灯光骤变的瞬间。回头复盘最费时间的不是模型部署本身而是供电、散热、开机自启、看门狗这些听起来特别“不技术”的事。它们就像水管的接头接不好再强的水泵也出不了水。如果你也准备把树莓派 5 带进车间做视觉检测我的建议是别急着调模型先把环境基础打牢。Ubuntu 装稳、电源换对、散热压住、systemd 服务写好、看门狗打开然后把 ONNX Runtime 的推理流程跑通最后再做精度优化。反过来做你会被现场一堆莫名其妙的问题淹没。树莓派 5 这个东西作为边缘推理硬件是合格的但前提是你要给它一个配得上车间的环境。