用RKNPU2部署YOLOv5目标检测:从模型转换到NMS后处理的完整教程
【免费下载链接】rknpu2项目地址: https://gitcode.com/gh_mirrors/rk/rknpu2
本文带你用RKNPU2(Rockchip NPU 工具链)在 RK3562/RK3566/RK3588 开发板上部署YOLOv5 目标检测模型:从 ONNX 转换 RKNN 模型、RKNN 推理主流程,到 NMS 后处理参数调优,一份完整教程带你快速跑通端侧 AI 检测。
上图为 Demo 自带的测试图片
examples/rknn_yolov5_demo/model/bus.jpg,运行检测后会在原图上画出目标框与置信度。
一、RKNPU2 是什么?为什么用它做目标检测
RKNPU2是 Rockchip(瑞芯微)NPU 的第二代软件栈,核心由两部分组成:
| 组件 | 作用 | 在本项目中的位置 |
|---|---|---|
| rknn-toolkit2 | 模型转换工具(PC 端运行),把 ONNX 转成.rknn模型 | 转换脚本examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx2rknn.py |
| librknn_api | 端侧运行时推理库(板端运行) | runtime/RK3588/Linux/librknn_api/ |
对新手来说,它的优势在于:
- 🎯性能高、功耗低:推理交给 NPU 硬件执行,CPU 几乎不占用,适合边缘盒子、IPC 摄像头等场景;
- 📦流程标准:转换 → 推理 → 后处理三步走,官方 Demo 可直接编译运行;
- 🔌适配广:同一套代码支持 RK3562、RK3566/RK3568、RK3588 及 RV1106 系列芯片,Linux 与 Android 均可运行。
⚠️ 新手注意:由于硬件限制,Demo 默认把 YOLOv5 的后处理部分移到 CPU 实现,且附带模型使用 relu 激活(相比 silu 精度略降、性能大幅提升),详见
examples/rknn_yolov5_demo/README_CN.md。
二、项目结构速览:YOLOv5 Demo 里有什么
Demo 位于examples/rknn_yolov5_demo/,核心文件一览:
examples/rknn_yolov5_demo/ ├── convert_rknn_demo/yolov5/ # ONNX 转 RKNN 的转换脚本 │ ├── onnx2rknn.py # 转换入口 │ ├── onnx_models/yolov5s_relu.onnx │ └── dataset.txt # 量化校准数据集列表 ├── model/ # 各平台预转换好的 .rknn 模型 │ ├── RK3562/ RK3566_RK3568/ RK3588/ │ ├── bus.jpg # 测试图片 │ └── coco_80_labels_list.txt # COCO 80 类标签 ├── src/ │ ├── main.cc # 图片检测主程序 │ ├── main_video.cc # 视频流检测主程序 │ ├── preprocess.cc # letterbox / RGA 缩放预处理 │ └── postprocess.cc # 反量化 + NMS ├── include/ │ ├── postprocess.h # NMS_THRESH、BOX_THRESH 等参数 │ ├── preprocess.h │ └── rga_func.h └── utils/ # MPP 解码/编码、画框工具关键点:模型按芯片平台分目录存放(如model/RK3588/yolov5s-640-640.rknn),运行时按自己板子选择对应目录即可。
三、模型转换:ONNX 转 RKNN 的最快 3 步法
转换脚本为examples/rknn_yolov5_demo/convert_rknn_demo/yolov5/onnx2rknn.py,在 PC 上配合 rknn-toolkit2(版本 ≥ 1.4.0)使用。
1. 修改目标平台参数
打开onnx2rknn.py,将platform改成你的芯片:
platform = 'rk3566' # 可改为 rk356x / rk3588 等2. 确认量化配置
脚本中已给出推荐配置:输入640x640、mean 为 0、std 为 255(即把 0~255 归一化到 0~1),并启用INT8 量化(do_quantization=True+ 校准数据集dataset.txt):
rknn.config(mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], target_platform=platform) ret = rknn.build(do_quantization=True, dataset=DATASET) ret = rknn.export_rknn(RKNN_MODEL_PATH)💡 量化需要校准集(
dataset.txt内为若干图片路径),校准集越贴近真实业务场景,INT8 精度越稳。
3. 执行转换
python onnx2rknn.py生成的.rknn模型输出在rknn_models/目录,拷贝到板端model/<平台>/目录即可使用。
📌 替换自训练模型时的两大坑
- anchor 必须对齐:Demo 后处理硬编码了 YOLOv5 的三组 anchor(见
src/postprocess.cc中anchor0/anchor1/anchor2),换模型不同步修改会导致检测框解析错乱; - 类别数与阈值:COCO 80 类对应
include/postprocess.h中的OBJ_CLASS_NUM 80,自定义类别需同步修改。
四、推理主流程:从图片输入到检测框输出
主程序examples/rknn_yolov5_demo/src/main.cc的完整链路如下,共 5 步:
| 步骤 | 关键 API | 说明 |
|---|---|---|
| ① 初始化 | rknn_init | 加载.rknn模型,创建推理上下文 |
| ② 查询属性 | rknn_query | 获取输入/输出张量的尺寸、格式、量化 scale 与 zero-point |
| ③ 预处理 | letterbox / RGA | 缩放填充到 640x640,默认letterbox保持长宽比 |
| ④ 推理 | rknn_inputs_set→rknn_run→rknn_outputs_get | NPU 执行前向计算 |
| ⑤ 后处理 | post_process | 反量化 + 置信度过滤 + NMS,输出检测框 |
letterbox 预处理参数怎么理解
src/preprocess.cc中的letterbox()按最小缩放比缩放图像并居中补边,避免拉伸变形——这正是 YOLOv5 训练时的预处理方式,直接决定了检测精度。缩放比scale_w/scale_h和补边量pads会传入后处理,用于把预测框映射回原图坐标:
// main.cc 中的调用 letterbox(img, resized_img, pads, min_scale, target_size);若只追求速度不在乎形变,可选
resize模式(走 RGA 硬件加速);追求精度请保持默认letterbox。
五、NMS 后处理详解:如何去掉重复的检测框
这是新手最容易困惑的一环。NPU 输出的是80 个类别 × 每网格数百个候选框的量化张量,必须经过三层"漏斗"才能得到最终结果:
原始输出(约上千候选) ──> 置信度过滤 ──> NMS去重 ──> 最终检测框 (反量化) (BOX_THRESH) (NMS_THRESH)1. 反量化:把 INT8 还原成浮点
量化模型输出的是整型,需按输出属性还原:value = (raw - zp) * scale。scale/zp 来自rknn_query的output_attrs[i].scale / .zp,post_process()内部已自动处理。
2. 两个关键阈值(include/postprocess.h)
#define OBJ_CLASS_NUM 80 // 类别数(COCO) #define NMS_THRESH 0.45 // IOU 阈值:大于该值的重叠框被抑制 #define BOX_THRESH 0.25 // 置信度阈值:低于该值的框直接丢弃- BOX_THRESH(0.25):调高 → 框更少、误检更少,但可能漏检小目标;
- NMS_THRESH(0.45):调低 → 去重更激进,密集小目标场景容易误删;调高 → 保留更多框,但同一目标可能出现重复框。
3. NMS 去重的核心逻辑
src/postprocess.cc中的nms()按置信度降序遍历同类框,用CalculateOverlap()计算两两 IOU,凡 IOU 超过NMS_THRESH的框直接标记删除(order[j] = -1)——这就是经典的Non-Maximum Suppression算法,代码约 40 行,非常适合作为端侧 NMS 的参考实现。
最后,程序在原图上用 OpenCV 画出红色边框与"类别+置信度"文字,结果保存为out.jpg。
六、编译与运行:快速部署到你的开发板
1. 一键交叉编译
修改build-linux_<TARGET_PLATFORM>.sh中的工具链路径TOOL_CHAIN,然后执行脚本即可(编译配置见CMakeLists.txt,已自动链接 RKNN API、OpenCV、RGA、MPP 库):
export TOOL_CHAIN=~/opt/tool_chain/gcc-9.3.0-x86_64_aarch64-linux-gnu/host ./build-linux_RK3588.shAndroid 端则修改ANDROID_NDK_PATH后运行build-android_<TARGET_PLATFORM>.sh。
2. 推送到板端并运行
adb push install/rknn_yolov5_demo_Linux /userdata/ adb shell cd /userdata/rknn_yolov5_demo_Linux/ export LD_LIBRARY_PATH=./lib ./rknn_yolov5_demo model/RK3588/yolov5s-640-640.rknn model/bus.jpg程序会先跑一次单帧输出检测详情,再循环 10 次统计平均耗时(含后处理),例如:loop count = 10 , average run XX ms。
3. 进阶:视频流实时检测
src/main_video.cc支持 H.264/H.265 文件与 RTSP 流(仅 Linux),基于 MPP 硬解码:
./rknn_yolov5_video_demo model/RK3588/yolov5s-640-640.rknn xxx.hevc 265 ./rknn_yolov5_video_demo model/RK3588/yolov5s-640-640.rknn <RTSP_URL> 265⚠️ RK3562 目前仅支持 H.264 视频流;Android 暂不支持 RTSP。
七、常见问题与调优建议
| 问题现象 | 排查方向 |
|---|---|
| 框位置整体偏移/错乱 | anchor 未对齐、letterbox 的pads/scale未传入后处理 |
| 漏检增多 | 调低BOX_THRESH(如 0.15),或更换非量化模型 |
| 同一目标多个框 | 调低NMS_THRESH(如 0.3) |
| 精度明显下降 | 检查量化校准集是否贴合业务场景;确认 std_values 与训练归一化一致 |
| 找不到 librga.so | 按板端 RGA 驱动版本选择对应库并加入LD_LIBRARY_PATH |
| 类别数对不上 | 修改postprocess.h中OBJ_CLASS_NUM,并替换标签文件 |
结语
至此,你已经掌握了RKNPU2 部署 YOLOv5 目标检测的完整链路:onnx2rknn.py三步转换出 RKNN 模型,main.cc五步推理拿到检测结果,再用postprocess.cc中的反量化 + 双阈值过滤 + NMS 得到最终检测框。接下来可以试着替换成自训练模型、接入相机或 RTSP 视频流,把检测能力真正落地到你的边缘设备中。🚀
【免费下载链接】rknpu2项目地址: https://gitcode.com/gh_mirrors/rk/rknpu2
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考