萍乡市网站建设_网站建设公司_H5网站_seo优化
2025/12/26 14:31:19 网站建设 项目流程

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控制实现联动响应。随着国产芯片生态逐步成熟,类似的端侧智能方案将越来越多地出现在工厂、社区和城市大脑之中。

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

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

立即咨询