以 yolov5s-5.0 为例,完整记录 .pt → ONNX → RKNN 的转换、代码修改及 RK3588 平台推理测试。


一、环境与硬件准备

组件 说明
训练好的模型 yolov5s.pt(v5.0)
转换设备 x86_64 架构 Linux(Ubuntu 20.04 + Python 3.8 演示)
部署设备 RK3588 开发板

二、PT → ONNX 转换

1. 修改模型 forward 函数(适配 NPU 导出)

在 YOLOv5 的 models/yolo.py 中找到 Detect 类的 forward 方法,修改如下:

修改前(原始):

def forward(self, x):
    """Processes input through YOLOv5 layers, altering shape for detection: `x(bs, 3, ny, 
nx, 85)`."""
    z = []  # inference output
    for i in range(self.nl):
        x[i] = self.m[i](x[i])  # conv
        bs, _, ny, nx = x[i].shape  # x(bs,255,20,20) to x(bs,3,20,20,85)
        x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
        if not self.training:  # inference
            if self.dynamic or self.grid[i].shape[2:4] != x[i].shape[2:4]:
                self.grid[i], self.anchor_grid[i] = self._make_grid(nx, ny, i)
            if isinstance(self, Segment):  # (boxes + masks)
                xy, wh, conf, mask = x[i].split((2, 2, self.nc + 1, self.no - self.nc - 5), 
4)
                xy = (xy.sigmoid() * 2 + self.grid[i]) * self.stride[i]  # xy
                wh = (wh.sigmoid() * 2) ** 2 * self.anchor_grid[i]  # wh
                y = torch.cat((xy, wh, conf.sigmoid(), mask), 4)
            else:  # Detect (boxes only)
                xy, wh, conf = x[i].sigmoid().split((2, 2, self.nc + 1), 4)
                xy = (xy * 2 + self.grid[i]) * self.stride[i]  # xy
                wh = (wh * 2) ** 2 * self.anchor_grid[i]  # wh
                y = torch.cat((xy, wh, conf), 4)
            z.append(y.view(bs, self.na * nx * ny, self.no))
    return x if self.training else (torch.cat(z, 1),) if self.export else (torch.cat(z, 1), 
x)

修改后(增加环境变量控制):

def forward(self, x):
    z = []  # inference output
    for i in range(self.nl):
        if os.getenv('RKNN_model_hack', '0') != '0':
            x[i] = torch.sigmoid(self.m[i](x[i]))  # conv
  return x

作用:通过环境变量 RKNM_model_hack 控制导出时仅保留 sigmoid 激活后的卷积输出,简化 ONNX 结构。


2. 修改 export.py 脚本

在 export.py 开头增加:

import os
os.environ['RKNM_model_hack'] = 'npu_2'

修改模型输出 shape 获取方式:

修改前:

shape = tuple((y[0] if isinstance(y, tuple) else y).shape)  # model output shape

修改后:

shape = tuple(y[0].shape)  # model output shape

3. 执行 ONNX 导出

python export.py --weights yolov5s.pt --include onnx

得到 yolov5s.onnx 文件。


三、ONNX → RKNN 转换(在 x86 Linux 上完成)

⚠️ 注意:此步骤不能在 RK3588 上执行,需在 x86_64 主机(或虚拟机/WSL)中进行。

1. 创建 Conda 环境(Python 3.8)

conda create -n RKN python=3.8 -y
conda activate RKN

2. 安装 rknn_toolkit2

git clone https://github.com/rockchip-linux/rknn-toolkit2.git
cd rknn-toolkit2
pip install rknn_toolkit2-1.4.0_22dcfef4-cp38-linux_x86_64.whl

测试安装:

from rknn.api import RKNN

3. 修改转换示例脚本

进入示例目录:

cd rknn-toolkit2-1.6.0/rknn-toolkit2/examples/onnx/yolov5
  • 将你的 yolov5s.onnx 放入该目录

  • 修改 test.py 中的模型路径和图片路径

执行转换:

python3 test.py

成功后会生成 .rknn 模型文件。


四、在 RK3588 平台上部署并推理

1. 下载 rknpu2 工具

git clone https://github.com/rockchip-linux/rknpu2
cd rknpu2-master/examples/rknn_yolov5_demo

2. 修改头文件,设定类别数

进⼊到 /rknpu2-master/examples/rknn_yolov5_demo⽂件夹下,修改头⽂件postprocess.h

#define OBJ_CLASS_NUM 2   // 修改为你的数据集类别数

3. 修改标签文件

替换 model/coco_80_labels_list.txt 内容为你的类别名称。

4. 放置模型和测试图片

  • 将 .rknn 文件放到 model/RK3588/ 目录下

  • 将测试图片(如 test.jpg)放到 model/ 目录下

5. 编译并运行

./build-linux_RK3588.sh   # 生成 install 目录
cd install/rknn_yolov5_demo_linux
./rknn_yolov5_demo ./model/RK3588/best.rknn ./model/test.jpg

五、推理性能对比(RK3588 实测)

测试条件:

  • 同一张测试图片

  • 循环推理 10 次取平均

  • 计时范围:预处理 + 推理 + 后处理

  • NPU 单核占用约 30% ~ 44%

模型 模型大小 平均延时
yolov5s-cpu(CPU 推理) 28.5 MB 398 ~ 456 ms
yolov5s-npu(NPU 推理) 8.2 MB 27 ~ 29 ms
yolov8s(CPU 推理) 12.2 MB 224 ~ 240 ms

🚀 NPU 加速效果显著,延时从数百毫秒降至 30ms 以内,模型体积也大幅缩小。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐