1. 为什么环境搭建这一步值得单独拿出来讲
很多人拿到 RK3588 开发板之后,第一反应是直接找现成的 RKNN 模型跑起来看效果。这个思路没错,但实际走一遍就会发现,真正卡住进度的往往不是模型转换本身,而是环境搭建阶段的各种琐碎问题:Python 版本冲突、PyTorch 装不上、ONNX 导出报错、RKNN-Toolkit2 依赖缺失。我在第一次部署 YOLOv5s 的时候,光环境搭建就折腾了将近两天,中间踩的坑足够写一篇避坑指南。
这篇文章是系列的第二篇,专门讲环境搭建与模型获取。核心目标很明确:在一台开发机上准备好完整的模型转换工具链,把 YOLOv5s 的 PyTorch 权重拿到手,并且验证它能正常导出为 ONNX 格式。这一步做完,后面转到 RKNN 就是水到渠成的事。适合的读者是手里有 RK3588 板子、想在 NPU 上跑目标检测模型、但对整个工具链还不太熟悉的开发者。如果你之前只在 PC 上跑过 YOLO,没接触过端侧部署,那这篇内容基本就是照着抄作业的节奏。
整个流程我拆成了三大块:开发机环境准备、YOLOv5s 源码与权重获取、ONNX 导出验证。每一块都会说清楚为什么这么做、有哪些替代方案、以及我实际踩过的坑。环境搭建这件事,看起来是体力活,但里面的选择逻辑其实挺多,选错了后面会反复返工。
2. 开发机环境准备:选对工具链版本比什么都重要
2.1 操作系统与 Python 版本的选择逻辑
开发机用什么系统,这个问题看起来简单,实际上直接影响后面 RKNN-Toolkit2 能不能顺利装上。RKNN-Toolkit2 官方支持的平台是 Ubuntu 18.04 和 Ubuntu 20.04,Python 版本要求 3.6 到 3.8 之间。我一开始图省事用了 Ubuntu 22.04 加 Python 3.10,结果 RKNN-Toolkit2 的 wheel 包直接装不上,报了一堆依赖不兼容的错误。
后来我换了个思路,用 Ubuntu 20.04 作为基础系统,Python 锁定在 3.8。这个组合是经过验证最稳的。如果你手头只有 Windows 机器,可以用 WSL2 装 Ubuntu 20.04,实测下来和原生 Ubuntu 体验基本一致,USB 设备透传也没问题。但要注意 WSL2 的内核版本,太新的内核有时候会导致 RKNN-Toolkit2 的某些依赖编译失败,建议用 WSL2 默认的 Ubuntu 20.04 镜像就行。
Python 环境管理我强烈建议用 conda 或者 miniconda,不要直接用系统自带的 Python。原因很简单:RKNN-Toolkit2 对 numpy、protobuf 这些包的版本有严格要求,系统 Python 里往往已经装了其他版本,混在一起很容易出问题。用 conda 创建一个独立环境,出问题了直接删掉重建,成本很低。
# 创建独立环境 conda create -n rknn_yolov5 python=3.8 conda activate rknn_yolov5 # 验证 Python 版本 python --version # 应该输出 Python 3.8.x这里有个细节值得说一下:为什么是 Python 3.8 而不是 3.6 或 3.7?因为 YOLOv5 的某些依赖(比如最新的 PyTorch 版本)对 Python 最低版本有要求,3.6 已经太老了,很多包不再提供支持。3.8 是一个平衡点,既能满足 RKNN-Toolkit2 的要求,又能兼容较新的 PyTorch。
2.2 PyTorch 安装的版本匹配与常见报错
PyTorch 的安装是环境搭建里最容易出问题的环节。RKNN-Toolkit2 本身不依赖 PyTorch,但我们需要 PyTorch 来加载 YOLOv5s 的权重并导出 ONNX。所以 PyTorch 的版本选择主要考虑两点:一是能正常加载 YOLOv5s 的权重,二是导出的 ONNX 算子集版本要兼容 RKNN 工具链。
我实测下来,PyTorch 1.10 到 1.13 之间的版本都比较稳。太新的版本(比如 2.0 以上)导出的 ONNX 有时候会引入一些 RKNN 不支持的算子,太老的版本又可能缺少某些必要的功能。我最终用的是 PyTorch 1.12.1 加 torchvision 0.13.1,这个组合在 YOLOv5s 导出 ONNX 时没有出现过算子兼容问题。
安装命令根据是否有 GPU 会有所不同。如果你开发机有 NVIDIA 显卡,可以用 CUDA 版本加速推理验证;如果没有,CPU 版本也完全够用,因为导出 ONNX 这个过程本身不需要 GPU。
# CPU 版本安装(推荐,兼容性最好) pip install torch==1.12.1 torchvision==0.13.1 --index-url https://download.pytorch.org/whl/cpu # 如果有 CUDA 11.3,可以用这个 pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 --extra-index-url https://download.pytorch.org/whl/cu113装完之后一定要验证一下:
import torch print(torch.__version__) print(torch.cuda.is_available()) # 没有 GPU 的话输出 False 是正常的这里有个坑我踩过:如果你之前装过其他版本的 PyTorch,pip 可能不会自动卸载旧版本,导致新旧版本混在一起。建议在安装前先执行pip uninstall torch torchvision把旧的清干净,再装新版本。
2.3 ONNX 与 ONNX Runtime 的安装要点
ONNX 和 ONNX Runtime 是两个不同的东西,很多人会搞混。ONNX 是一种模型格式标准,定义了一套算子规范和文件结构;ONNX Runtime 是一个推理引擎,用来加载和运行 ONNX 模型。我们在导出阶段只需要 ONNX 这个包来支持torch.onnx.export的调用,ONNX Runtime 则是用来在开发机上验证导出的模型能不能正常推理。
安装命令很简单:
pip install onnx==1.12.0 onnxruntime==1.12.1版本选择上,ONNX 1.12 对应的算子集版本是 17,这个版本导出的模型在 RKNN-Toolkit2 里兼容性比较好。ONNX Runtime 用 1.12.1 是因为它和 ONNX 1.12 是配套的,版本差太多可能会出现加载模型失败的情况。
验证安装:
import onnx import onnxruntime as ort print(onnx.__version__) print(ort.__version__)如果这两个 import 都没报错,说明基础环境已经就绪了。
2.4 RKNN-Toolkit2 的安装与依赖处理
RKNN-Toolkit2 是瑞芯微官方提供的模型转换工具,负责把 ONNX 模型转成 RK3588 NPU 能执行的 RKNN 格式。这个工具的安装是环境搭建里最麻烦的一步,因为它的依赖比较多,而且对版本很敏感。
首先去瑞芯微的 GitHub 仓库下载对应版本的 RKNN-Toolkit2。注意要选对版本,RK3588 需要的是 RKNN-Toolkit2 1.4.0 或以上版本。下载下来是一个 whl 文件,直接 pip 安装:
pip install rknn_toolkit2-1.4.0-cp38-cp38-linux_x86_64.whl安装过程中最常见的报错是 protobuf 版本冲突。RKNN-Toolkit2 依赖 protobuf 3.20 以下的版本,但很多其他包会装更新的 protobuf。解决办法是先装 RKNN-Toolkit2,再装其他包,或者手动锁定 protobuf 版本:
pip install protobuf==3.19.6还有一个常见问题是 numpy 版本。RKNN-Toolkit2 1.4.0 要求 numpy 低于 1.24,如果系统里装了更新的 numpy,import rknn 的时候会报module 'numpy' has no attribute 'object'之类的错误。直接降级:
pip install numpy==1.23.5验证 RKNN-Toolkit2 是否安装成功:
from rknn.api import RKNN print("RKNN Toolkit2 loaded successfully")如果这行能正常执行,说明环境搭建的核心部分已经完成了。
3. YOLOv5s 源码与权重获取:别小看这一步的版本选择
3.1 YOLOv5 仓库版本的选择与克隆
YOLOv5 的官方仓库更新很频繁,不同版本之间的代码结构和导出逻辑有差异。我建议锁定一个稳定的 tag,不要直接用 master 分支,因为 master 随时可能引入新的改动,导致导出 ONNX 时出现意料之外的问题。
我实测下来,v6.2 和 v7.0 这两个版本比较稳。v6.2 的代码结构更简洁,导出 ONNX 的默认参数对 RKNN 比较友好;v7.0 增加了一些新功能,但核心导出逻辑没变。我最终用的是 v6.2,因为它的export.py脚本参数更少,不容易配错。
git clone https://github.com/ultralytics/yolov5.git cd yolov5 git checkout v6.2克隆下来之后,先别急着装依赖。YOLOv5 的requirements.txt里列了一堆包,但有些版本和我们之前装好的 PyTorch 可能冲突。我的做法是手动安装核心依赖,跳过那些非必要的包:
pip install pyyaml matplotlib opencv-python pillow tqdm注意opencv-python建议装opencv-python-headless版本,尤其是在服务器环境下,避免 GUI 相关的依赖问题。
3.2 权重文件的获取与校验
YOLOv5s 的预训练权重可以从官方 release 页面下载,也可以让脚本自动下载。自动下载的方式很简单,在 YOLOv5 目录下执行:
python -c "import torch; model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)"但这行命令会同时下载仓库代码和权重,有时候网络不稳定会失败。更稳妥的方式是直接下载权重文件:
wget https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5s.pt下载完之后一定要校验文件完整性。我遇到过一次权重文件下载不完整的情况,加载的时候报unexpected EOF错误,排查了半天才发现是文件没下完。校验方法很简单,看文件大小是否在 14MB 左右:
ls -lh yolov5s.pt # 正常应该是 14M 左右如果文件大小明显偏小,重新下载。另外可以用 PyTorch 加载一下,确认没有报错:
import torch model = torch.load('yolov5s.pt', map_location='cpu') print(type(model))正常输出应该是<class 'dict'>或者模型对象,如果报错说明文件有问题。
3.3 权重加载验证与模型结构确认
拿到权重之后,建议先跑一次推理验证,确认模型能正常工作。这一步看起来多余,但实际上能提前发现很多问题,比如权重和代码版本不匹配、依赖包缺失等。
import torch from models.experimental import attempt_load model = attempt_load('yolov5s.pt', map_location='cpu') model.eval() print("Model loaded successfully") print(f"Number of parameters: {sum(p.numel() for p in model.parameters())}")YOLOv5s 的参数量大概在 720 万左右,如果输出的数字差太多,说明权重加载有问题。另外可以打印一下模型的输出层信息,确认检测头是三个尺度:
for name, module in model.named_modules(): if 'detect' in name.lower(): print(name, module)正常情况下应该能看到三个 Detect 层,分别对应 stride 8、16、32 的特征图。这个信息在后面转 ONNX 和 RKNN 的时候会用到,因为 RKNN 需要知道输出节点的名称和数量。
4. ONNX 导出全流程:参数配置与验证方法
4.1 导出脚本的关键参数解读
YOLOv5 自带的export.py脚本可以直接用来导出 ONNX,但默认参数不一定适合 RK3588。我建议手动指定几个关键参数,而不是直接用默认值。
核心参数有这几个:
--weights:指定权重文件路径--img-size:输入图像尺寸,RK3588 上常用 640x640--batch-size:批处理大小,端侧部署一般设为 1--opset:ONNX 算子集版本,建议用 12--include:指定导出格式为 onnx--simplify:是否简化模型,建议开启
导出命令:
python export.py --weights yolov5s.pt --img-size 640 640 --batch-size 1 --opset 12 --include onnx --simplify这里重点说一下--opset 12的选择理由。ONNX 算子集版本越高,支持的算子越多,但 RKNN-Toolkit2 对高版本算子集的支持有限。我试过 opset 13 和 15,导出后在 RKNN 转换阶段都出现过算子不支持的问题。opset 12 是一个比较保守的选择,覆盖了 YOLOv5s 需要的所有算子,同时 RKNN 兼容性最好。
--simplify参数会调用 onnx-simplifier 对模型进行简化,去掉一些冗余的算子。这个步骤能显著减少 RKNN 转换时的报错概率,强烈建议开启。但需要先安装 onnx-simplifier:
pip install onnx-simplifier4.2 导出过程中的常见报错与处理
导出过程中最常见的报错是RuntimeError: Exporting the operator ... to ONNX opset version 12 is not supported。这个错误通常是因为 PyTorch 版本和 opset 版本不匹配导致的。解决办法有两个:一是降低 opset 版本到 11,二是升级 PyTorch 到 1.12 以上。我推荐后者,因为 opset 11 对某些算子的支持不完整。
另一个常见问题是AttributeError: 'Upsample' object has no attribute 'recompute_scale_factor'。这是 PyTorch 1.11 之后引入的一个兼容性问题,YOLOv5 v6.2 的代码没有适配。解决办法是修改models/common.py里的 Upsample 类,把recompute_scale_factor参数去掉,或者直接升级 YOLOv5 到 v7.0。
还有一个坑是导出后的 ONNX 模型输出节点名称。YOLOv5 默认导出的输出节点叫output,但 RKNN 转换时需要明确指定输出节点。我建议在导出时用--output-names参数自定义输出节点名称,方便后面 RKNN 配置:
python export.py --weights yolov5s.pt --img-size 640 640 --batch-size 1 --opset 12 --include onnx --simplify --output-names output0 output1 output24.3 ONNX 模型验证与推理测试
导出完成后,必须验证 ONNX 模型能不能正常推理。这一步能发现很多隐藏问题,比如输出维度不对、算子计算错误等。
import onnx import onnxruntime as ort import numpy as np # 加载模型 onnx_model = onnx.load('yolov5s.onnx') onnx.checker.check_model(onnx_model) print("ONNX model check passed") # 创建推理会话 session = ort.InferenceSession('yolov5s.onnx') # 查看输入输出信息 for inp in session.get_inputs(): print(f"Input: {inp.name}, shape: {inp.shape}, type: {inp.type}") for out in session.get_outputs(): print(f"Output: {out.name}, shape: {out.shape}, type: {out.type}") # 构造随机输入测试 dummy_input = np.random.randn(1, 3, 640, 640).astype(np.float32) outputs = session.run(None, {session.get_inputs()[0].name: dummy_input}) for i, out in enumerate(outputs): print(f"Output {i} shape: {out.shape}")正常情况下,三个输出节点的 shape 应该是[1, 25200, 85]或者类似的格式。25200 是 80x80 + 40x40 + 20x20 三个尺度特征图的预测框总数,85 是 4 个坐标 + 1 个置信度 + 80 个类别概率。如果 shape 不对,说明导出参数有问题,需要回头检查。
4.4 模型轻量化与量化前的准备
虽然这篇文章主要讲环境搭建和模型获取,但既然提到了 ONNX,顺便说一下量化前的准备工作。RK3588 的 NPU 对 INT8 量化支持最好,FP16 也能跑但性能会打折扣。在转 RKNN 之前,需要准备一组校准图片,用来做量化校准。
校准图片的准备原则是:数量不用太多,100 到 200 张就够;内容要覆盖实际部署场景中的典型画面;分辨率不需要和模型输入一致,RKNN 工具会自动处理。我一般从训练集或者实际场景中随机抽一批图片,放到一个文件夹里,后面 RKNN 转换时指定这个文件夹路径就行。
# 校准图片目录结构示例 calibration_images/ ├── img_001.jpg ├── img_002.jpg ├── ... └── img_200.jpg另外,ONNX 模型在量化前最好先做一次简化,去掉不必要的算子。除了前面提到的--simplify参数,还可以用 onnx-simplifier 单独处理:
python -m onnxsim yolov5s.onnx yolov5s_sim.onnx简化后的模型在 RKNN 转换时成功率更高,而且推理速度也会略有提升。
5. 实操中的常见问题与排查技巧
5.1 环境类问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
ImportError: libGL.so.1 | 缺少 OpenCV 系统依赖 | apt install libgl1-mesa-glx |
ModuleNotFoundError: No module named 'rknn' | RKNN-Toolkit2 未安装或环境不对 | 确认 conda 环境已激活,重新安装 whl |
protobuf version conflict | protobuf 版本过高 | pip install protobuf==3.19.6 |
numpy has no attribute 'object' | numpy 版本过高 | pip install numpy==1.23.5 |
torch.onnx.export报算子不支持 | opset 版本不匹配 | 降低 opset 到 12 或升级 PyTorch |
| ONNX 模型加载失败 | 文件下载不完整 | 重新下载,校验文件大小 |
5.2 我踩过的三个典型坑
第一个坑是 conda 环境和系统环境的混淆。我在 conda 环境里装了 RKNN-Toolkit2,但执行脚本的时候忘了激活环境,用的是系统 Python,结果一直报No module named 'rknn'。排查了半天才发现是环境没激活。这个问题的教训是:每次打开新终端,第一件事就是conda activate rknn_yolov5,养成习惯。
第二个坑是 ONNX 导出时的动态轴设置。YOLOv5 的export.py默认会设置动态 batch 轴,但 RK3588 部署时 batch 固定为 1,动态轴反而会导致 RKNN 转换失败。解决办法是在导出时加--dynamic参数的反向操作,或者手动修改导出脚本,把 dynamic_axes 设为 None。我后来直接在导出命令里加了--batch-size 1,并且确认导出的 ONNX 没有动态维度。
第三个坑是权重文件的版本匹配。我有一次用 YOLOv5 v7.0 的代码加载 v6.2 的权重,虽然能加载成功,但推理结果完全不对。原因是两个版本的模型结构有细微差异,权重对不上。后来我统一用 v6.2 的代码和 v6.2 的权重,问题就消失了。所以版本一致性这件事,在模型部署里怎么强调都不为过。
5.3 验证环境是否就绪的完整检查清单
在进入下一步 RKNN 转换之前,建议按这个清单逐项检查:
- conda 环境已激活,Python 版本为 3.8
- PyTorch 能正常 import,版本在 1.10 到 1.13 之间
- ONNX 和 ONNX Runtime 能正常 import
- RKNN-Toolkit2 能正常 import,
from rknn.api import RKNN不报错 - YOLOv5s 权重文件大小正常,能正常加载
- ONNX 模型已导出,
onnx.checker.check_model通过 - ONNX Runtime 推理测试通过,输出 shape 正确
- 校准图片文件夹已准备好,至少有 100 张图片
这八项都确认无误之后,环境搭建和模型获取这一步就算彻底完成了。后面转 RKNN 的时候,如果遇到问题,基本可以排除环境因素,直接聚焦在转换参数和模型结构上。
6. 关于工具链版本锁定的一点个人经验
环境搭建这件事,最怕的就是版本漂移。今天装好的环境,过两个月重新装一遍,可能因为某个包的版本更新了就跑不起来了。我的做法是把所有关键包的版本号记录在一个requirements_lock.txt文件里,下次重建环境的时候直接按这个文件装。
torch==1.12.1 torchvision==0.13.1 onnx==1.12.0 onnxruntime==1.12.1 numpy==1.23.5 protobuf==3.19.6 opencv-python-headless==4.6.0.66这个文件看起来不起眼,但在我后来换开发机、重装系统的时候省了大量时间。直接pip install -r requirements_lock.txt,十分钟就能把环境恢复到位,不用再一个个排查版本冲突。
另外,RKNN-Toolkit2 的 whl 文件建议本地备份一份。瑞芯微的 GitHub 仓库有时候会调整 release 页面,旧版本的 whl 不一定能随时下载到。我习惯把 whl 文件和对应的 ONNX 模型放在同一个目录下,标注好版本号和日期,这样即使过了半年再回头看,也能快速复现当时的环境。
模型获取这一步,权重文件同样建议本地存档。YOLOv5 的 release 页面虽然稳定,但网络问题谁也说不准。我一般会把yolov5s.pt和导出的yolov5s.onnx一起放到项目目录的weights/文件夹下,用 git-lfs 或者直接压缩备份。这样后面做 RKNN 转换、量化、精度对比的时候,随时都能拿到原始文件,不用重新下载。
环境搭建和模型获取是整个部署流程的地基,地基打牢了,后面的转换和调优才能顺利进行。下一篇会讲 RKNN 转换的具体操作,包括量化参数配置、精度对比方法、以及如何在 RK3588 上跑通第一次推理。如果你在环境搭建阶段遇到了这里没提到的问题,大概率是某个依赖包的版本不对,按上面说的版本锁定思路排查一遍,基本都能解决。