RK3588平台YOLOv5模型训练与部署指南
详解在RK3588平台上搭建YOLOv5训练环境的完整流程,涵盖Anaconda环境隔离、NPU兼容性处理、labelimg数据标注及XML转YOLO格式的转换脚本。重点解决SILU与ReLU激活函数的适配问题,并实现数据集自动划分与目录管理,为边缘端部署提供可靠支持。
RK3588平台YOLOv5模型训练与部署实战
在智能摄像头、工业质检和边缘安防等场景中,如何将高效的AI目标检测能力落地到国产芯片上,是当前许多开发者关注的焦点。RK3588作为瑞芯微推出的旗舰级SoC,集成了高达6TOPS算力的NPU,为本地化视觉推理提供了强大支撑。然而,从PyTorch模型训练到最终在设备端稳定运行,并非一键导出那么简单——尤其是面对YOLOv5这类主流但结构复杂的模型时,激活函数兼容性、格式转换异常、推理性能瓶颈等问题常常让人止步不前。
本文将以实际工程视角出发,带你完整走通一条基于RK3588的YOLOv5端到端开发路径:从环境搭建开始,经过数据准备、模型训练、ONNX优化,再到RKNN转换与板端部署,每一步都结合真实踩坑经验给出解决方案。我们特别推荐使用 Miniconda-Python3.9镜像 构建轻量可复现的开发环境,避免依赖冲突导致的“本地能跑,换机就崩”问题。
整个流程中最关键的一环,其实是开发环境的设计逻辑。很多团队在项目初期直接用系统Python安装一堆包,结果不同项目间版本打架,后期难以迁移。而Miniconda的优势在于它像一个“沙盒”,每个项目独立运行,互不影响。相比Anaconda动辄几百MB的体积,Miniconda仅包含conda和Python解释器,启动快、占用小,非常适合AI开发这种对依赖管理要求高的场景。
以当前主流框架为例,PyTorch 1.12+对ONNX的支持更完善,但又要求Python ≥3.7且 ≤3.10;CUDA 11.7对应的torch版本也必须精确匹配。如果不用虚拟环境,很容易出现pip install torch后发现装错了版本的情况。因此,第一步永远是创建干净的虚拟环境:
conda create -n yolov5-rk3588 python=3.9 -y
conda activate yolov5-rk3588
激活成功后终端会显示 (yolov5-rk3588) 前缀,说明你现在处于隔离环境中。接下来可以安全地安装核心依赖:
# 安装支持CUDA 11.7的PyTorch
pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu117
# 克隆适配RK3588的YOLOv5分支(重要!)
git clone https://github.com/airockchip/yolov5.git
cd yolov5
pip install -r requirements.txt
这里有个极易被忽视的关键点:不能使用Ultralytics官方的YOLOv5仓库。原因在于其主干网络广泛使用的SiLU(Swish)激活函数,在RK3588的NPU上并不受原生支持,会导致后续转换时报错 Unsupported layer: Swish。Rockchip官方维护的 airockchip/yolov5 分支已将这些层替换为ReLU,同时内置了针对RKNN Toolkit的预处理脚本,极大提升了部署成功率。
如果你有GPU可用,建议通过以下命令验证CUDA是否正常工作:
import torch
print(torch.cuda.is_available()) # 应返回 True
print(torch.__version__)
若返回False,请检查驱动或重装PyTorch。训练阶段启用GPU可显著缩短迭代周期,尤其是在处理大规模数据集时。
进入模型训练前,首先要解决的是数据问题。没有高质量标注,再强的架构也只是空中楼阁。我们推荐使用图形化工具 LabelImg 进行手动标注:
pip install labelimg
labelimg
打开工具后,设置图像目录(如 datasets/images/),并将标签保存路径指向 datasets/labels/。注意选择 PascalVOC (.xml) 格式输出,这是目前最通用的标注标准之一。
每张图片对应一个.xml文件,记录目标类别和边界框坐标。例如:
<annotation>
<filename>car_001.jpg</filename>
<size>
<width>640</width>
<height>480</height>
</size>
<object>
<name>car</name>
<bndbox>
<xmin>100</xmin>
<ymin>80</ymin>
<xmax>300</xmax>
<ymax>200</ymax>
</bndbox>
</object>
</annotation>
但YOLOv5训练需要的是归一化的 .txt 标签格式:class_id center_x center_y width height。为此,我们可以编写一个自动转换脚本:
import os
import xml.etree.ElementTree as ET
classes = ['car', 'person', 'bike'] # 自定义类别列表
def convert(size, box):
dw = 1. / size[0]
dh = 1. / size[1]
x = (box[0] + box[1]) / 2.0
y = (box[2] + box[3]) / 2.0
w = box[1] - box[0]
h = box[3] - box[2]
return x*dw, y*dh, w*dw, h*dh
def convert_annotation(image_id):
in_file = open(f'datasets/annotations/{image_id}.xml', encoding='utf-8')
out_file = open(f'datasets/labels/{image_id}.txt', 'w')
tree = ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)
for obj in root.iter('object'):
cls = obj.find('name').text
if cls not in classes:
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text),
float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
bb = convert((w,h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
# 创建必要目录
os.makedirs('datasets/images/train', exist_ok=True)
os.makedirs('datasets/images/val', exist_ok=True)
os.makedirs('datasets/labels/train', exist_ok=True)
os.makedirs('datasets/labels/val', exist_ok=True)
# 批量转换所有XML文件
for file in os.listdir('datasets/annotations'):
if file.endswith('.xml'):
name = os.path.splitext(file)[0]
convert_annotation(name)
执行后,所有标注将转为YOLO所需格式。记得按比例划分训练集与验证集(建议8:2),否则容易过拟合。
接下来是模型配置环节。按照YOLOv5规范组织目录结构:
yolov5/
├── data/
│ └── custom.yaml
├── datasets/
│ ├── images/
│ │ ├── train/
│ │ └── val/
│ └── labels/
│ ├── train/
│ └── val/
其中 custom.yaml 内容如下:
train: ../datasets/images/train
val: ../datasets/images/val
nc: 3
names: ['car', 'person', 'bike']
一切就绪后即可启动训练:
python train.py \
--img 640 \
--batch 16 \
--epochs 100 \
--data data/custom.yaml \
--weights yolov5s.pt \
--cfg models/yolov5s.yaml \
--name yolov5s_rk3588
几个实用提示:
- 若显存不足,可降低--batch至8或改用yolov5n;
- 训练过程中的loss曲线和mAP可在runs/train/yolov5s_rk3588/中查看;
- 最终生成的最优权重为best.pt,可用于后续导出。
当得到满意的best.pt模型后,下一步就是将其部署到RK3588上。由于该平台使用专有的 RKNN Toolkit 推理引擎,我们必须先将模型转为.rknn格式。
首先导出ONNX中间表示:
python export.py \
--weights runs/train/yolov5s_rk3588/best.pt \
--include onnx \
--img 640 \
--batch 1
务必注意:
- 输入尺寸固定为静态shape(batch=1);
- ONNX Opset应不低于11;
- 若遇到不支持的操作符(如Slice),需在代码中手动替换为Split等等价结构。
然后在RK3588开发板或Linux主机上安装RKNN Toolkit2:
pip install rknn_toolkit_lite2
编写转换脚本 convert_rknn.py:
from rknn.api import RKNN
rknn = RKNN()
# 设置输入归一化参数
rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], target_platform='rk3588')
ret = rknn.load_onnx(model='best.onnx')
if ret != 0:
print('Load ONNX failed!')
exit(ret)
# 构建模型(若需INT8量化,设do_quantization=True并提供校准集)
ret = rknn.build(do_quantization=False)
if ret != 0:
print('Build RKNN failed!')
exit(ret)
# 导出最终模型
rknn.export_rknn('yolov5s.rknn')
rknn.release()
运行脚本即可生成yolov5s.rknn,准备好推送到设备端。
部署阶段通常通过SSH连接RK3588开发板完成:
ssh firefly@192.168.1.100
# 默认密码通常是 fa
上传模型文件:
scp yolov5s.rknn firefly@192.168.1.100:/home/firefly/models/
在开发板上编写推理脚本 infer.py:
import cv2
import numpy as np
from rknnlite.api import RKNNLite
rknn = RKNNLite()
ret = rknn.load_rknn('yolov5s.rknn')
if ret != 0:
print('Load RKNN failed!')
exit(ret)
ret = rknn.init_runtime(core_mask=RKNNLite.NPU_CORE_AUTO)
if ret != 0:
print('Init runtime failed!')
exit(ret)
# 图像预处理
img = cv2.imread('test.jpg')
img = cv2.resize(img, (640, 640))
input_data = img[np.newaxis, :, :, ::-1].astype(np.float32) / 255.0
# 执行推理
outputs = rknn.inference(inputs=[input_data])
print("Output shape:", [o.shape for o in outputs])
# 简单后处理示意
pred = outputs[0]
# 此处可接入解码逻辑:过滤低置信度框、NMS去重等
print("Inference completed.")
rknn.release()
运行后预期输出类似:
Output shape: [(1, 25200, 85)]
Inference completed.
这表明模型已在NPU上成功加载并完成一次前向传播。
在实际调试过程中,以下几个问题是高频出现的:
| 问题 | 原因 | 解决方案 |
|---|---|---|
Unsupported layer: Swish |
使用了SiLU激活函数 | 改用Rockchip分支或手动替换为ReLU |
| ONNX导出失败 | 动态shape或不支持op | 固定输入尺寸,禁用自动形状推断 |
| 推理速度慢 | 未启用多核NPU | 设置core_mask=RKNNLite.NPU_CORE_0_1_2 |
| mAP偏低 | 数据量少或过拟合 | 加强数据增强、调整学习率策略 |
一些进阶优化建议值得尝试:
- INT8量化:在开启do_quantization=True的前提下,使用少量校准图像(约100~200张)进行校准,推理速度可提升2~3倍;
- 分辨率权衡:将输入从640×640降至416×416,虽牺牲部分精度,但帧率明显上升,适合实时性要求高的场景;
- 流水线设计:结合OpenCV多线程读图与NPU异步推理,实现“边取图、边推理”,提高整体吞吐量。
这条从训练到部署的完整链路,不仅适用于YOLOv5,也为其他模型迁移到RK3588平台提供了参考模板。更重要的是,它强调了一种工程思维:环境可复现、流程可追踪、问题可定位。当你不再被“为什么昨天还能跑今天就不行”困扰时,才能真正专注于算法本身的价值创造。
未来你可以在此基础上拓展更多应用,比如接入RTSP视频流做连续检测,或是结合GPIO控制实现联动响应。随着国产芯片生态逐步成熟,类似的端侧智能方案将越来越多地出现在工厂、社区和城市大脑之中。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)