☰
QEMU仿真ARM64环境跑通YOLOv5s:RK3588部署前的关键演练
2026/9/29 1:23:21 网站建设 项目流程

如果你的香橙派5(RK3588)已经烧好了Ubuntu 20.04,但还没想好怎么把YOLOv5s部署上去,我强烈建议你先别急着在板子上折腾,先在PC端用模拟器把整个推理链路仿真跑通。这不是浪费时间,而是我在RK3588上踩过太多环境坑之后总结出来的习惯:很多部署报错根本不是代码问题,而是依赖、系统库、Python环境不一致导致的,这类问题在PC模拟器里更容易暴露和定位。

这篇文章会完整记录我在x86电脑上搭建ARM64 Ubuntu 20.04模拟环境、安装YOLOv5s依赖、跑通推理并输出检测结果的整个过程。全程不碰真板卡,所有操作在PC上完成。内容适合三类人:刚入手香橙派或RK3588开发板、想提前熟悉部署流程的初学者;有Linux基础但没跑过YOLOv5的开发者;以及在真机上反复折腾失败、想换个思路的人。你能从里面拿到的,是一套可以照着敲的步骤和几条只有实际踩过坑才写得出来的经验。

1. 模拟器仿真跑YOLOv5s,到底图什么

先说清楚一个容易误解的点:PC端模拟器的价值从来不是“模拟出RK3588的性能”,而是“模拟出和RK3588一致的系统环境”。RK3588是ARM64架构处理器,我们的真机系统是ARM64版Ubuntu 20.04,那么在x86电脑上用QEMU虚拟出一台ARM64机器,装上同样版本的Ubuntu,跑YOLOv5s时遇到的所有依赖问题、代码问题和配置问题,都会提前暴露一次。等这些问题在PC上解决了,真机部署就是一次干净的执行,而不是边查边试。

1.1 仿真能帮你验证什么

第一,验证Python环境和系统依赖链。YOLOv5s虽然本身代码不复杂,但它的依赖面很宽:PyTorch、OpenCV、NumPy、Pillow、matplotlib等等。这些包在ARM64的Ubuntu 20.04上安装时可能出现各种问题,比如某个库的wheel不兼容、缺少系统级动态库。这些问题和硬件本身没关系,但在真机上排查会非常痛苦,因为板子上的终端控制台、网络环境、输出方式都不如PC方便。在QEMU仿真环境里,你可以用完整的桌面级调试手段去处理它们。

第二,验证YOLOv5s代码链路。下载源码、准备权重、执行推理、读取输出结果,这一整套流程的输入输出与硬件无关,仿真环境里能跑通,真机上同样能跑通。更实际的好处是,你可以在仿真环境里放心地改参数、试不同的输入源、看detect.py的日志格式,即使把环境搞坏了也无所谓,重建一个镜像重新来过就行。真机上你敢这么折腾,一旦系统崩溃可能就是重新烧写,半小时起步。

第三,验证模型权重可用性。下载的yolov5s.pt是否完整、能否被当前版本的YOLOv5源码正确加载、推理能不能正常输出目标框,这些问题在仿真环境里跑一次就有答案。网上很多部署疑难帖的根子其实是权重文件损坏或版本不匹配,但用户往往先去怀疑硬件,走了大弯路。

1.2 仿真验证不了什么

仿真环境无法帮助你验证RK3588的NPU推理路径。香橙派5上的RK3588自带的NPU理论算力有6 TOPS,部署YOLOv5s标准做法是把PyTorch模型转换成RKNN格式,然后用NPU加速推理。QEMU模拟的只是CPU,里面没有NPU,所以它跑的是纯CPU版本PyTorch推理,性能和流程都只是“能用”的水平。

这引出一个重要判断:仿真跑通只能证明“代码、依赖、权重”三者OK,不等于真机就能直接跑。真机部署时还需要处理模型转换、NPU驱动、rknn runtime环境,这些是仿真环境覆盖不到的部分。但反过来,如果你在仿真环境里都跑不通,那基本可以断定问题出在代码或依赖层面,而不是硬件,这对于缩小排查范围极有价值。

1.3 为什么选择QEMU而不是安卓模拟器

日常大家说的雷电模拟器、夜神模拟器、MuMu模拟器,本质是Android系统模拟器,它们模拟的是ARM/ARM64 Android环境,拿来做YOLOv5s的Linux推理开发完全不对路。我们要的是一个能跑ARM64版Ubuntu 20.04、可以任意安装Python包和系统库的完整虚拟环境,QEMU是开源社区里最成熟的方案,支持全系统模拟,正好满足需求。

另一个原因是QEMU能把ARM64虚拟机做成一个文件,随时备份、随时回滚。我在整个RK3588部署过程中会反复修改环境,QEMU的snapshot能力让我可以放心大胆地折腾,出了问题一键恢复到干净状态。这个工作流在真板卡上是做不到的。

2. 用QEMU搭一个ARM64 Ubuntu 20.04虚拟机

QEMU的安装和使用在PC上有几个固定套路,我直接把我验证过的步骤写出来。需要说明的是,下面涉及的命令都是基于Ubuntu x86_64宿主机的操作,如果你用的是其他Linux发行版,包管理器换成对应的就行。

2.1 宿主机的QEMU组件安装

先更新系统软件源,然后安装qemu-system-arm和qemu-efi-aarch64。命令行如下:

sudo apt update sudo apt install -y qemu-system-arm qemu-efi-aarch64

qemu-system-arm这个包在Ubuntu源里对应的是ARM架构模拟器,里面包含了qemu-system-aarch64可执行文件。qemu-efi-aarch64则是ARM64虚拟机的UEFI固件,没有它虚拟机没办法从磁盘正常引导系统。装完之后验证一下:

qemu-system-aarch64 --version ls /usr/share/qemu-efi-aarch64/QEMU_EFI.fd

如果能看到QEMU版本号,并且QEMU_EFI.fd文件存在,说明基础组件已经就位。这里有个很容易忽略的点:光装qemu-system-arm不够,很多人启动虚拟机时卡在“找不到EFI固件”,就是因为漏装了qemu-efi-aarch64。

2.2 准备系统镜像和虚拟磁盘

Ubuntu 20.04的ARM64服务器版镜像,去官方源或者国内镜像站下载ubuntu-20.04.6-live-server-arm64.iso。这个镜像约1GB左右,我用的是live-server版本,它的安装程序会引导你完成分区和用户配置,比较直观。

虚拟磁盘用QEMU自带的工具创建:

qemu-img create -f raw rk3588-sim.img 30G

磁盘大小我建议至少30G。为什么不是20G?因为我第一次用20G试过,装完系统、Python依赖和YOLOv5之后,磁盘剩余空间只剩下不到2G,跑推理时apt的缓存又把空间挤爆,频繁出现No space left on device。30G虽然略大,但给虚拟磁盘预留了一些缓冲区,省去扩容的麻烦。

2.3 第一次启动并完成Ubuntu 20.04安装

启动命令是整个环境搭建的核心,我给出一个自己验证过的完整版本:

qemu-system-aarch64 \ -M virt \ -cpu cortex-a72 \ -smp 4 \ -m 4096 \ -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \ -drive file=rk3588-sim.img,format=raw,if=virtio \ -cdrom ubuntu-20.04.6-live-server-arm64.iso \ -device virtio-net-pci,netdev=net0 \ -netdev user,id=net0,hostfwd=tcp::2222-:22 \ -nographic

简单解释几个关键参数。-M virt指定使用ARM的通用虚拟化平台,这是QEMU对ARM64支持最成熟的一个硬件模型;-cpu cortex-a72选CPU型号,cortex-a72虽然在QEMU里也算不上新,但它兼容性最稳,如果你的QEMU版本比较新(7.x以上)直接指定cortex-a76也可以;-smp 4分配4个虚拟CPU核心,-m 4096分配4GB内存,这两个数值在仿真环境里已经足够跑YOLOv5s。-nographic把控制台输出重定向到当前终端,不用另外开图形窗口,SSH远程操作也更顺手。

如果你发现终端里输出一片黑或者卡住,先别急,按一次回车,有时候grub菜单在等待输入。安装过程跟在真机上装Ubuntu Server一模一样:选语言、配置网络(默认DHCP即可)、磁盘分区选“使用整个磁盘”、创建用户名和密码、等待安装结束。整个安装过程大约20分钟,取决于你电脑的CPU性能。

安装完成后,把-cdrom参数去掉再启动一次,这次系统会从虚拟磁盘正常引导。登录账户,执行uname -m,如果输出aarch64,恭喜你,一台ARM64虚拟机已经跑起来了。

2.4 系统初始化:SSH端口映射与磁盘空间

重新启动虚拟机时建议保留hostfwd=tcp::2222-:22这个参数,它的作用是把宿主机的2222端口映射到虚拟机的22端口,这样就能在PC上直接执行ssh 用户名@127.0.0.1 -p 2222连接虚拟机。

第一次进入系统后,先做两件事。第一,安装SSH服务端;第二,更新软件源。

sudo apt update sudo apt install -y openssh-server sudo systemctl enable --now ssh sudo apt upgrade -y

这里有个坑需要提醒:user模式的QEMU网络,hostfwd映射只对TCP生效,而且不要试图在虚拟机里主动访问宿主机,反过来由宿主机SSH进虚拟机才是正常打开方式。

磁盘空间这块,装完升级之后马上用df -h看一眼。如果发现根分区使用率已经过半(20G磁盘很容易这样),建议删掉apt缓存并清理pip的缓存文件,后面安装YOLOv5依赖时会省出不少空间:

sudo apt clean

3. 把YOLOv5s在仿真环境里跑通

系统环境就绪后,接下来的任务就是安装Python依赖、获取YOLOv5源码、下载权重、执行推理。这一节的内容和真机部署时操作几乎相同,所以每一步我都写清楚原因,方便你后面平移到板卡上。

3.1 安装Python虚拟环境和推理依赖

Ubuntu 20.04系统自带的Python 3.8可以直接用,但为了避免污染系统Python,我建议创建虚拟环境。YOLOv5官方文档也推荐这么做,因为PyTorch的依赖版本比较敏感,虚拟环境隔离后在真机上复用同一套配置会更省心。

sudo apt install -y python3-pip python3-venv git wget python3 -m venv yolov5-venv source yolov5-venv/bin/activate pip install --upgrade pip

虚拟环境激活后,再安装PyTorch CPU版本。在ARM64 Ubuntu上,PyTorch官方提供aarch64的wheels,直接指定CPU版索引安装即可:

pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu

注意不要装CUDA版,因为仿真环境里没有NVIDIA GPU,装了CUDA版不仅体积大,还可能在import时报错。装完验证一下:

python -c "import torch; print(torch.__version__); print(torch.zeros(1).device)"

能正常输出版本号,说明PyTorch安装成功。如果此时遇到libGL.so.1之类的报错,先执行sudo apt install -y libgl1 libglib2.0-0,这是OpenCV的运行时依赖,无桌面环境的系统经常会缺。

3.2 拉取YOLOv5源码并准备模型与测试图

在虚拟环境激活的状态下,克隆YOLOv5仓库然后安装依赖:

git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt

requirements.txt里面包含OpenCV、Pillow、matplotlib、seaborn、pandas等依赖,在真机上同样需要执行这一步。安装过程在QEMU模拟环境里会比较慢,尤其是opencv-python的编译安装可能要等十来分钟,如果国内网络慢可以给pip换用国内源(比如清华、阿里镜像源)。

模型权重从YOLOv5官方仓库下载:

wget https://github.com/ultralytics/yolov5/releases/download/v6.0/yolov5s.pt -P weights/ ls -lh weights/yolov5s.pt

正常情况这个文件大小约14MB。如果你下载的权重小于10MB,十有八九是下载不完整,后续推理时会报错。YOLOv5仓库自带测试图片data/images/bus.jpg,拿来当第一个推理样本足够了,后面你想换真实图片随时替换。

3.3 第一次推理:命令与预期输出

在虚拟环境激活、且当前目录在yolov5文件夹内的前提下,执行:

python detect.py --weights weights/yolov5s.pt --source data/images/bus.jpg --project runs/detect --name sim_test

QEMU模拟环境下的CPU性能有限,推理一张640x640的图片可能要一分钟左右,这是正常的。只要看到类似这样的日志输出,就说明整条链路已经跑通:

image 1/1 /path/to/yolov5/data/images/bus.jpg: 640x480 4 persons, 4 buses, 1 truck Speed: 20.0ms pre-process, 45.0ms inference, 5.0ms NMS per image at shape (1, 3, 640, 640)

3.4 理解detect.py的输入输出约定

很多人在这一步跑通后就不再深究,直接跳到真机部署,这是不对的。detect.py虽然只是YOLOv5的官方推理脚本,但它的输入输出约定在后续真机部署和二次开发中会反复用到。

输入侧,--source参数支持单张图片、图片目录、视频文件、摄像头设备号和RTSP流地址,这个能力在边缘设备部署时极其常用。输出侧,标注过的图片保存在runs/detect/sim_test/目录下,同时加上--save-txt参数会在相同目录生成检测结果的txt文件,每行格式是class x_center y_center width height confidence,这种格式可以直接被后续的数据处理流程解析。

还有一个容易被忽略的参数是--img,默认值640。这决定了模型推理时的输入分辨率,修改它会直接影响检测效果和推理速度。在仿真环境里建议固定640,因为RK3588部署时NPU往往也是按固定分辨率做优化,养成固定的输入尺寸习惯,后面转模型时就不用反复调整。

4. 仿真阶段最常见的坑与排查经验

我在这套流程里踩过不少坑,有些还是重复踩。下面挑几个最典型的写出来,每条都给了现象、根因和解决方式,希望你能一次避开。

现象根因解决方式
ImportError: libGL.so.1找不到无桌面环境的Ubuntu缺少OpenCV依赖的图形库安装libgl1和libglib2.0-0
RuntimeError: Half not implemented on CPU在模拟环境用了--half参数CPU推理不支持FP16,去掉--half
No space left on device虚拟磁盘被系统缓存占满apt clean、pip cache purge、删除无用文件
SSH连接被拒绝虚拟机里没装或没启动openssh-serversudo apt install openssh-server并enable
QEMU启动无输出缺少EFI固件检查qemu-efi-aarch64是否正确安装

4.1 两类最容易出现的“半路报错”

第一类是缺少系统级动态库,典型就是libGL.so.1。这个报错几乎每个在Server版Ubuntu上装OpenCV的人都会遇到,根因是python-opencv的wheel依赖系统图形库,而这在带桌面的Ubuntu里是自带的、在Server版里则没有。处理方式很简单,装两个包就行。如果还遇到libgthread-2.0.so.0找不到,再补一个libglib2.0-0。

第二类是PyTorch算子的平台限制,典型就是上面表格里的Half精度报错。YOLOv5的detect.py里有一个--half选项,在有CUDA的环境下可以开启FP16推理来提速。但在QEMU模拟的纯CPU环境下,PyTorch的CPU后端没有实现half精度的卷积算子,一跑就会报错。解决办法是去掉--half参数。这一点在真机RK3588上也需要注意,因为NPU的FP16支持程度和PyTorch并不一致,这在后面转RKNN模型时会体现得更明显。

4.2 推理慢到像死机:先学会看证据再下结论

第一次在QEMU模拟器里跑YOLOv5s的人,大概率会被推理耗时吓到。我在cortex-a72模拟CPU上跑640x640的图,单张推理要70秒以上,加上模型加载的时间,整个命令可能三五分钟都看不到新输出,这时候很多人会直接Ctrl+C,以为是死机了。

我的建议是不要急着中断,先并行开一个终端看资源占用。在虚拟机里执行top,观察CPU使用率,如果多个核心都在高占用,说明进程在正常计算;如果CPU几乎为空,再考虑是不是报错卡住了。判断链路是否通了,还有一个辅助技巧:第一次跑推理时在命令里加--nosave参数,可以减少磁盘IO,让日志输出更纯粹,看到检测日志后再正常跑完整输出。

4.3 环境问题和代码问题的排查顺序

跑YOLOv5s失败时,我习惯按下面的顺序排查,能省很多时间:

第一步,验证Python环境本身。执行python -c "import torch; import cv2; print('ok')",如果这一步都失败,说明依赖没装好,优先处理虚拟环境和库缺失问题。

第二步,验证权重文件。检查weights/yolov5s.pt是否存在,文件大小是否正常。权重不对或损坏会直接导致模型加载报错,对比一下文件大小能快速发现异常。

第三步,验证代码调用。执行Python并加载模型,确认forward能正常跑通,如果这一步OK,再考虑是不是输入图片路径、参数设置等其他人为因素。

这个排查顺序本质上是从依赖层到代码层再到输入数据层,往下逐层确认。在真机RK3588上遇到问题,我同样沿用这个顺序,先排除环境再怀疑硬件,避免把时间浪费在错误方向上。

5. 仿真跑通之后,距离RK3588真机部署还差什么

这是全篇最重要的一节。仿真跑通会给你很大的信心,但真机部署并不能直接复用仿真环境里的一切。我要把两者的技术差异讲清楚,避免你用错误的预期去操作真机。

5.1 PyTorch推理和RKNN NPU推理的技术差异

仿真环境里用的是PyTorch直接加载yolov5s.pt权重推理,模型格式是PyTorch的序列化权重,计算图由PyTorch运行时解释执行。而RK3588真机上跑YOLOv5s,标准路线是先把PyTorch模型导出为ONNX,再用瑞芯微官方的rknn-toolkit2工具转换成RKNN格式。这个RKNN格式是专门为麒麟NPU定义的模型格式,推理时调用的是rknn runtime的C/Python API,而不是PyTorch。

这里面的逻辑差异体现在两个层面。模型层面,RKNN转换过程中通常会做量化,也就是把FP32权重转成INT8或FP16,这会带来一定的精度损失,需要在转换后验证检测效果。代码层面,你不再调用torch.load()和model(),而是写一段类似这样的流程:初始化RKNN、加载RKNN模型、处理输入图像、调用推理接口、解析输出结果。这些在仿真环境里都学不到,但当你已经理解YOLOv5的预处理、NMS和后处理逻辑后,学习RKNN API的难度会大幅下降。

5.2 真机性能和数据链路与仿真环境的差异

性能差异是最直观的。RK3588的NPU理论算力约6 TOPS,跑YOLOv5s这种小模型,经过量化后单帧推理耗时通常在几十毫秒级别,能做到实时或准实时处理视频流。而QEMU模拟器的CPU推理单帧要几十秒,性能差了不止两个数量级。所以在仿真环境里不要关注FPS,这个数值没有参考意义。

数据链路也存在差异。仿真环境里你用的是普通Python环境,通过OpenCV读取本地图片;真机部署时,你很可能需要接入MIPI摄像头、USB摄像头或者RTSP流,最后还可能用FFmpeg做视频推流。这些链路在QEMU虚拟机里很难完整模拟。我的习惯是,把仿真环境当作“算法逻辑验证场”,把视觉输入输出链路的调试验证放到真机上做,两个环境各司其职,反而比单靠一台设备更高效。

5.3 从本文可以直接平移到真机的部分和需要重写的部分

直接把经验用上,不必重来一遍的包括这几块:YOLOv5源码的目录结构、detect.py的常用参数含义、预处理和后处理逻辑、模型输出的解析思路。这些在真机写推理脚本时还会用到。

需要重写或重新适配的有三块:模型权重格式(.pt到.onnx再到.rknn)、推理执行引擎(PyTorch换成RKNN runtime)、输入输出绑定(本地图片换成摄像头或视频流)。建议真机部署时不要凭记忆操作,先回到仿真环境里验证模型转换后的推理接口是否和预期一致。

另外说一个我自己的做法:把仿真环境始终保持可运行状态,不随意改动。后面调RKNN转换脚本、写输出解析代码时,我还会回到这个环境里,用PyTorch推理的结果作为标准答案,去对照RKNN推理的输出,确认量化带来的精度损失在可接受范围内。这种两边对照的方式,比直接在板子上盯着数字猜测要可靠得多。这套“PC模拟器先行、真机后验”的开发节奏,到现在我还在用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询