树莓派5部署YOLOv5实战:从系统到摄像头的完整流程指南

发布时间:2026/10/2 6:28:27
树莓派5部署YOLOv5实战:从系统到摄像头的完整流程指南 树莓派5进车间听起来就是把一个小盒子往产线边上一放实际动手才发现从系统到摄像头再到模型部署没有一步是顺的。这篇总结记录我把自训练的YOLOv5模型部署到树莓派5上的完整过程围绕六个最卡人的环节展开希望能给准备把边缘设备放进产线环境的你省下几个星期的试错时间。如果你有一点Linux基础想做视觉检测类的小项目或者正在纠结要不要用树莓派当边缘计算节点这篇应该能帮上忙。内容是我自己踩出来的真实经验不是对着官方文档复读后面每个环节都会说清楚为什么这么做以及还有哪些备选方案。1. 六件事是怎么来的以及整体方案选型1.1 为什么是树莓派5车间场景的需求拆解车间里做视觉检测常见的需求无非是产品外观缺陷识别、安全区域人员闯入检测、设备状态灯和仪表读数识别。这类场景不需要训练时那种大算力真正重要的是把模型部署到摄像头旁边做到低延迟、数据不出厂、成本可控。树莓派5相比前几代提升最明显的就是CPU算力和IO能力。BCM2712处理器带四个Cortex-A76核心ARM64架构主频可以跑到2.4GHz左右再配合PCIe接口可以接NVMe固态硬盘做存储加速对于跑一个轻量级YOLOv5模型来说算力是够用的。更重要的是树莓派5能完整支持Ubuntu Server这就解决了驱动和软件生态的问题PyTorch、ONNX Runtime这些机器学习栈在ARM64 Ubuntu上基本都能装上。我一开始也考虑过用Jetson Nano或者二手工控机但最后还是选了树莓派5。原因很现实Jetson Nano官方支持老一点量产功耗高工控机体积大、接口适合固定安装但摄像头接入和GPIO控制反而不如树莓派灵活。树莓派5在性价比和可玩性上比较均衡而且社区资料多遇到问题不至于卡死。1.2 六件事是怎么定下来的项目推进过程中真实卡住我的就是六个环节不是解决办法不够多而是每个环节都需要在“能用”和“好用”之间做取舍系统安装与启动树莓派5上装Ubuntu不是烧录完就能跑第一次启动的引导配置就很折腾散热与供电车间没有空调树莓派5满载发热量不小供电不足还会触发降频摄像头接入与图像采集CSI摄像头的驱动和视频流管道配置跟USB摄像头完全两套逻辑YOLOv5环境搭建与模型转换ARM平台安装PyTorch依赖以及把训练好的模型转成适合推理的格式自训练模型部署从PC训练到树莓派上跑通中间涉及图像预处理、后处理、坐标映射一堆细节性能调优与长期运行单帧推理速度只有几百毫秒时怎么优化到可用水平以及如何让程序开机自启、崩溃自愈。这六件事每件单独看都不难难的是串行推进时每一步都要磨合。下面的内容就按这六件事展开每部分我都会先讲方案选择再讲实现细节最后讲踩过的坑。2. 第一件事Ubuntu安装和系统启动2.1 烧录系统与初次启动的坑树莓派5改进了启动机制不像树莓派4那样随便找个TF卡就能跑稳。我踩到的第一个坑就是TF卡兼容性。普通杂牌卡在高负载下容易丢数据甚至开机后文件系统就损坏。建议选择A2级别的TF卡容量至少32GB或者干脆用官方NVMe HAT接一块SSD。系统镜像我选的是Ubuntu Server 24.04 LTS这个版本对树莓派5支持比较好而且LTS维护周期长适合车间长期运行。烧录用的是Raspberry Pi Imager选择定制版Ubuntu镜像写入TF卡。Imager在写入时会提供两个关键选项一个是WiFi网络配置另一个是启用SSH。初次启动最容易出问题的是用户账户。Ubuntu Server首次启动会走cloud-init初始化默认用户是ubuntu密码是ubuntu第一次登录会强制要求改密码。如果你在Imager里预置了SSH密钥可以跳过密码但如果没有预置要提前在显示器上登录一次。我图省事直接用Imager把SSH公钥放进去这样开机就能远程连。还有一个很隐蔽的坑树莓派5的TF卡插槽旁边有个通过螺丝固定的PCIe接口如果同时用了NVMe HAT并且系统装在NVMe上TF卡里就不能留旧系统文件否则启动时会去读TF卡导致不一致。我一开始TF卡和NVMe各装了一套系统结果反复开不进NVMe后面直接把TF卡分区清空才稳定。2.2 启动后的网络和基础配置系统能正常启动后第一件事就是固定IP。车间网络环境跟办公室不同往往没有DHCP预留树莓派重启后IP变了SSH直接断掉。我的做法是在netplan里配置静态IP。Ubuntu Server的Netplan配置文件在/etc/netplan/下默认文件名可能是50-cloud-init.yaml。编辑前先看一下现有内容确认网卡名称是eth0还是end0。我的配置大致如下network: version: 2 ethernets: eth0: dhcp4: no addresses: - 192.168.10.210/24 routes: - to: default via: 192.168.10.1 nameservers: addresses: - 192.168.10.1改完以后执行sudo netplan apply验证。如果远程操作建议先用ip a确认当前IP再把配置文件里的IP改成目标IP避免改完连不回去。顺便把基础的运维工具装了htop、git、vim、tmux、samba便于从PC传模型文件。传文件的时候小文件我直接跑scp大模型文件会走samba共享省得反复输密码。TFTP和NFS我试过不是不好用是配置起来需要固定的NFS服务端对于单节点部署没必要。3. 第二件事散热和供电车间环境的第一道坎3.1 车间环境的温度与降频问题树莓派5性能提升的代价就是发热量比前代大很多。我刚开始只装了一个被动散热片放在车间里跑YOLOv5模型后CPU温度很快冲到82℃然后系统开始自动降频推理速度从300多毫秒掉到600毫秒体感非常明显。车间环境比家里更严峻灰尘大、夏天没有空调的时候温度高。被动散热完全扛不住主动风扇是必须的。我选的是一个带铜管和涡轮风扇的散热套件装机后温度压在55℃到62℃之间。具体压测方式跑一个持续推理脚本同时用vcgencmd measure_temp看温度。树莓派5上vcgencmd依然能用只是要确认系统里有libraspberrypi-bin这个包。看到温度稳定在60℃左右不涨上去说明散热够了。如果还在缓慢爬升检查风扇方向是不是装反了别用那种没有测速线的静音风扇因为无法判断它有没有转。3.2 供电方案与电流限制供电是树莓派5项目的隐形杀手。树莓派5官方要求5V/5A但实际电流取决于外设摄像头、NVMe SSD、风扇、USB转串口模块都参与分电。我试过用一个5V/3A的旧手机充电器供电系统能开机但负载一高就出现欠压提示在SSH终端里能看到内核日志报bcm2835-power相关警告。另外树莓派5的USB-C口支持PD协议它会把CC引脚拉低来请求5V5A如果你用的充电器不支持协商就只会给5V3A甚至更少。最靠谱的方案是买官方27W电源或者确认是支持5V5A的PD充电器。我用的是支持PD的氮化镓充电器插上以后通过vcgencmd get_config和vcgencmd measure_volts确认核心电压没有异常掉电再跑满载推理脚本验证稳定性。如果供电不足树莓派会自动降低CPU和USB外设性能典型表现是TF卡读写变慢、SSH操作卡顿。我强烈建议在车间场景里加一个测量USB电压电流的小工具能看实时电流省得排查半天找不到原因。4. 第三件事摄像头接入和视频采集4.1 选择CSI摄像头还是USB摄像头车间部署的摄像头选择直接决定了视频流采集成败。我最初用的是USB摄像头插上以后在Ubuntu里识别为video0OpenCV里cv2.VideoCapture(0)也能打开但很快发现两个问题USB摄像头默认输出MJPG或YUYV格式通过USB总线传输会持续占用CPU进行格式转换和帧搬运多分辨率切换不稳定有时候设置CAP_PROP_FRAME_WIDTH为1280会失败实际输出还是640x480摄像头固定角度时USB线的长度和布线在车间走线里是个麻烦事。后来换成树莓派官方摄像头模块V3在树莓派5上走CSI接口直接用libcamera栈视频流通过片上ISP处理几乎不占CPU资源帧率也更稳定。V3摄像头支持最高1080P/50fps低光表现不错适合车间现场。不过要注意树莓派5的CSI接口是15pin跟树莓派4的排线通用但Ubuntu系统默认不一定开启了所有摄像头模式。我装完Ubuntu后先执行sudo libcamera-hello --list-cameras如果返回摄像头信息就说明驱动正常。如果看不到摄像头去检查/boot/firmware/config.txt里的camera_auto_detect1有些定制镜像会把它注释掉。4.2 用libcamera和GStreamer采集视频流用libcamera直接输出视频流很容易但要让YOLOv5推理脚本接收需要把帧送进Python代码。我这里用的是GStreamer管道方式。先安装依赖sudo apt install libgstreamer1.0-0 gstreamer1.0-tools gstreamer1.0-libcamera python3-gi python3-gi-cairo然后在Python里用OpenCV打开GStreamer管道import cv2 pipeline libcamerasrc ! video/x-raw,width640,height640,framerate30/1 ! videoconvert ! video/x-raw,formatRGB ! appsink drop1 cap cv2.VideoCapture(pipeline, cv2.CAP_GSTREAMER)第一版我直接用cap.read()循环发现延迟很高原因是缓冲区排队导致帧陈旧。后来在管道末尾加上drop1即追加appsink drop1强制丢帧让推理脚本只处理最新一帧。延迟从原来的两百多毫秒降到几十毫秒对实时检测非常重要。如果用USB摄像头可以通过cv2.VideoCapture(0)打开但建议设置cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(M,J,P,G)) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 640) cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)不然默认的YUYV格式会让CPU使用率直接拉满。5. 第四件事YOLOv5环境搭建和模型转换5.1 在树莓派上安装PyTorch和OpenCV部署YOLOv5之前要先在树莓派上搭好Python环境。Ubuntu Server默认自带Python 3.12PyTorch和OpenCV都有ARM64 wheel包直接用pip装没问题。我建议创建一个独立的虚拟环境不要用系统全局的pip否则升级依赖时很容易把系统包搞坏python3 -m venv ~/yolo-env source ~/yolo-env/bin/activate pip install --upgrade pip pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install opencv-python-headless numpy onnxruntime onnx这里有个关键选择opencv-python-headless而非opencv-python。树莓派Server版没有GUI如果装了完整OpenCV它会去拉Qt和GTK依赖重量大而且很多版本在ARM上编译有问题。headless版不依赖显示环境完全够用。pip安装过程中可能遇到内存不足的问题尤其是树莓派5 4GB版本。PyTorch的轮子包比较大安装时解压临时文件对内存和交换分区都有压力。如果pip被kill掉可以临时扩大swapsudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile装完以后验证一下python -c import torch; print(torch.__version__) python -c import cv2; print(cv2.__version__)5.2 把自训练的YOLOv5模型转到ONNX直接拿着PyTorch的best.pt在树莓派上推理是我最初的做法结果CPU占用很高单帧要跑到1.2秒根本没法用。后来我把模型转成ONNX再配合ONNX Runtime推理速度提升非常明显。在PC端有GPU或CPU都行的YOLOv5项目里执行导出python export.py --weights best.pt --include onnx --opset 12 --imgsz 640导出后得到best.onnx。这个导出流程会顺带在模型里加入NMS节点但我觉得树莓派端自己处理NMS更可控所以导出时用的官方默认版本然后在推理脚本里手工解析输出。ONNX模型对输入尺寸比较严格训练时如果用640x640推理也尽量保持640x640否则坐标缩放很容易出错。如果你要更快的推理速度可以在导出时把--imgsz 320后面检测精度会打折但帧率能翻倍这个取舍看具体检测目标。把best.onnx传到树莓派上时要注意校验文件完整性。我最初用scp传了三次每次推理都报维度不对最后checksum才发现文件传断了。大文件建议先md5sum校验再放到目标目录。6. 第五件事部署自训YOLOv5模型的完整实现6.1 从PC训练到树莓派推理的路径梳理其实整个部署链路是这样的数据标注 → PC训练YOLOv5 → 导出ONNX → 传到树莓派 → 在树莓派上用ONNX Runtime加载模型 → 摄像头采集 → 预处理 → 推理 → 后处理 → 绘制结果。每一步都要核对尺寸和坐标系。我在树莓派上写推理脚本时最容易出错的地方是图像预处理。YOLOv5官方的推理脚本里有一个letterbox函数它会保持长宽比地缩放图像然后填充灰色边缘到640x640推理完后需要把检测框坐标还原回原始图像尺寸。如果不做letterbox直接resize到640x640检测框在边缘位置会偏移而且小目标漏检严重。6.2 推理脚本核心代码和后处理细节下面这个脚本是我最终稳定的版本简化了类名加载和日志完整代码可以按这个骨架扩展import cv2 import numpy as np import onnxruntime as ort CLASSES [defect, normal] # 换成你自己的类别 CONF_THRESH 0.4 IOU_THRESH 0.45 INPUT_SIZE 640 def letterbox(img, new_shape(INPUT_SIZE, INPUT_SIZE)): shape img.shape[:2] r min(new_shape[0] / shape[0], new_shape[1] / shape[1]) new_unpad (int(round(shape[1] * r)), int(round(shape[0] * r))) dw, dh new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] dw, dh dw // 2, dh // 2 resized cv2.resize(img, new_unpad, interpolationcv2.INTER_LINEAR) top, bottom dh, dh left, right dw, dw canvas cv2.resize(img, (INPUT_SIZE, INPUT_SIZE)) # 简化分支实际用resize再填充 return canvas, r, (dw, dh) session ort.InferenceSession(/home/ubuntu/yolo/best.onnx, providers[CPUExecutionProvider]) input_name session.get_inputs()[0].name cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break img, ratio, pad letterbox(frame) img img[:, :, ::-1].transpose(2, 0, 1) img np.ascontiguousarray(img, dtypenp.float32) img / 255.0 img img[None, ...] outputs session.run(None, {input_name: img})[0] # (1, 25200, 5n) outputs outputs[0] boxes [] scores [] class_ids [] for i, det in enumerate(outputs): score float(det[4]) if score CONF_THRESH: continue # 省略坐标解码和缩放 # 后续接NMS和画框需要留意ONNX输出维度。YOLOv5在640x640输入下输出是[1, 25200, 85]假设一个类别就是[1,25200,6]实际根据类别数变化。25200来自三个特征层80x80、40x40、20x20加起来是640016004008400不对应该是25200因为YOLOv5的锚框每个格子有3个anchor所以80x80x31920040x40x3480020x20x31200合计25200。推理脚本里要固定这个数值如果动态输入导致维数变了后处理循环会直接报错。后处理我直接用了OpenCV的cv2.dnn.NMSBoxes来做非极大值抑制比自己写排序方便但要注意不同OpenCV版本返回值格式有差异新版本返回一个元组不要按旧版本索引去解。7. 第六件事性能调优和长期运行7.1 帧率优化从3帧到16帧的实操记录初始版本在树莓派5 CPU上跑640x640输入onnxruntime单线程推理单帧耗时大概330毫秒加上图像预处理和视频解码实际只能到3FPS。这个速度看静态画面还行但产线上产品一流动起来根本追不上。我按下面的顺序逐项优化把输入尺寸从640降到416单帧推理耗时直接降到180毫秒左右设置onnxruntime的线程数session_options.intra_op_num_threads 4推理耗时降到120毫秒把摄像头分辨率降到640x480通过GStreamer的videoscale在采集阶段就缩放省得在CPU上大幅缩放在推理循环里用OpenCV的cap.grab()和cap.retrieve()分离抓帧和解码让摄像头buffer保持在最新帧用torch的多线程 ONNX Runtime底层已经做了指令集加速NEON优化默认开启不需要额外配置。最终稳定在14到16FPS。如果进一步把输入调到320能到22FPS但小目标检测精度下降太多。7.2 用systemd做服务化和看门狗车间设备不可能每次开机都手动跑脚本必须要做成服务。把推理脚本写到/etc/systemd/system/yolo-inference.service[Unit] DescriptionYOLOv5 Inference Service Afternetwork.target [Service] Typesimple Userubuntu WorkingDirectory/home/ubuntu/yolo ExecStart/home/ubuntu/yolo-env/bin/python /home/ubuntu/yolo/infer.py Restartalways RestartSec5 [Install] WantedBymulti-user.target然后sudo systemctl enable yolo-inference sudo systemctl start yolo-inference sudo systemctl status yolo-inference设置Restartalways之后即使进程崩溃systemd也会在5秒后拉起。我还加了一个简单的健康检查脚本每隔1分钟检查/proc/$PID状态如果连续三次没有响应就重启服务防止模型推理线程假死。车间断电后恢复供电树莓派会重新开机systemd服务自动启动算是做到免维护。8. 常见问题与避坑速查8.1 六件事之外的额外坑项目过程中还有几个不在计划内的坑非常影响进度也列出来首次安装依赖时PyTorch和OpenCV的临时文件占满了根分区。树莓派默认分区只有TF卡的总容量建议在烧录时自定义分区大小或者至少装完后检查df -h。摄像头用GStreamer管道时如果appsink的buffer太大会导致延迟太小会丢帧严重。我用drop1解决但如果在检测结果中看到偶发的空帧可以适当增大max-buffers。用systemd跑Python脚本时环境变量和PATH与手动终端完全不同。直接写ExecStart/home/ubuntu/yolo-env/bin/python是最可靠的别用python这种简写否则会指向系统的python3虚拟环境失效。车间里开机次数多如果用普通TF卡建议开只读挂载或定期备份。我就遇到过一次断电导致文件系统损坏最后重刷系统才恢复。8.2 问题速查表现象原因解决方案SSH能连但推理服务启动失败systemd里没有用虚拟环境pythonExecStart写全路径到venv/bin/python模型推理结果框偏移没有做letterbox或坐标还原错误统一用letterbox并记录pad和ratioCPU温度高、主频上不去被动散热不够、供电不足换主动风扇确认电源支持5V5AOpenCV打不开摄像头Ubuntu驱动或GStreamer依赖缺失先跑libcamera-hello确认驱动再检查GStreamer摄像头延迟高视频缓冲队列堆积在appsink加drop1pip安装被kill内存不足临时扩大swap 2GB断电后文件系统损坏非正常关机启用只读挂载或定期备份我个人在实际项目里的体会是树莓派5作为边缘推理节点是可行的前提是严格按“系统 → 硬件外设 → 环境 → 模型 → 服务化”这个顺序走不要跳步。每一步的坑都集中在环境兼容性和资源限制上提前做好规划和验证就能把大部分问题拦在还没进车间的时候。如果你也要把自训练的YOLOv5模型往树莓派上搬我建议先在小负载下把整个链路跑通再去碰性能上限。最后提醒一点所有参数调优都要以实际场景为准别人能跑通的配置不一定适合你的车间环境多测几组数据再固定下来。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询