拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

在RK3576部署YOLO模型:从权重转换到NPU推理的完整链路与TaoToken调试实践

在RK3576部署YOLO模型:从权重转换到NPU推理的完整链路与TaoToken调试实践

1. 为什么 RK3576 上跑 YOLO 总在量化这步翻车

RK3576 这颗芯片在边缘盒子、工业相机、机器人主控里出现得越来越多,6 TOPS 的 NPU 算力拿来跑 YOLOv8n 这种轻量检测模型,理论上单帧推理能压到十几毫秒。但真正上手你会发现,从训练完的.pt到板子上跑出框,中间隔着一整条工具链:ONNX 导出、RKNN 量化转换、板端编译、精度对齐。任何一环参数写错,最后要么模型加载失败,要么框全歪了。

我见过最多的翻车点集中在量化阶段。RKNN-Toolkit2 默认走i8量化,如果你的校准集(dataset.txt 里那批图)和实际场景差太远,或者 ONNX 导出时没关掉某些算子,量化后的模型 mAP 能掉二三十个点。更麻烦的是板端只给你一个「检测结果不对」的现象,不告诉你哪一层出的问题。

这篇就按真实链路走一遍:PC 侧把yolov8n.pt转成yolov8n.rknn,板端编译rknn_model_zoo的 demo 跑通实时检测,中间穿插逐层精度比对的动作。同时说清楚怎么用 TaoToken 的统一 Key/API 通道来管调试日志和模型版本——边缘部署最烦的就是「这块板子跑的到底是哪个版本的模型」,把版本信息通过 API 通道回传,比在板子上贴标签靠谱得多。

适合谁看:手上已经有 RK3576 开发板、装好了 Ubuntu 环境、想把训练好的 YOLO 落到板子上的人。如果你还没配好交叉编译环境,先把aarch64工具链和adb装好再往下看。

核心检索词先摆出来:RK3576 部署 YOLO 模型,本质是把 PyTorch 权重经过 ONNX 中转,用 RKNN-Toolkit2 量化成 NPU 能吃的.rknn格式,再在板端用rknn_model_zoo的 C++ demo 加载推理。整条链路 PC 侧负责转换,板端负责编译运行,两边通过文件拷贝衔接。

2. TaoToken 在边缘调试链路里的定位与前置准备

先说清楚 TaoToken 在这套流程里干什么,免得你以为是拿来跑推理的。NPU 推理是板子本地完成的,TaoToken 不参与。它解决的是另外两个问题:调试日志的集中查看,以及模型版本的统一管理。

边缘部署的痛点很具体。你在 PC 上转了三版.rknn,拷到板子上测,发现第二版精度最好,但过两天忘了第二版对应的是哪个 ONNX、哪批校准图。板子本身存储有限,不可能把每版模型和日志都留着。这时候如果有个统一的 API 通道,把「模型哈希 + 转换参数 + 板端实测 mAP」作为一条记录发出去,后面回溯就轻松了。

TaoToken 提供的就是这种统一 Key/API 通道。官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。注意 API 地址不带 UTM 参数,直接填https://taotoken.net/api就行。

前置准备分两块。PC 侧需要:Ubuntu 20.04(我用的是服务器版)、Conda、Python 3.8、git。板端需要:能 ssh 或 adb 进去的 RK3576、aarch64交叉编译工具链、基本的cmake和make。

先把五个文件拉齐,这是后面所有步骤的基础:

# 1. 官方权重 wget https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8n.pt # 2. ultralytics 主库 git clone https://github.com/ultralytics/ultralytics.git # 3. 瑞芯微优化版 ultralytics(关键,普通版导出的 ONNX 算子不兼容) git clone -b rk_opt_v1 https://github.com/airockchip/ultralytics_yolov8.git # 4. 板端 demo 与转换脚本 git clone https://github.com/airockchip/rknn_model_zoo # 5. 转换工具链 git clone https://github.com/airockchip/rknn-toolkit2

这里有个坑要提前说:ultralytics_yolov8必须用rk_opt_v1分支,不能用主线的 ultralytics。瑞芯微在这个分支里改了检测头的导出逻辑,把后处理拆成了 NPU 友好的形式。如果你直接用官方 ultralytics 导出 ONNX,转 RKNN 时会报算子不支持,或者转出来框的位置全错。

Conda 环境建 Python 3.8,因为 RKNN-Toolkit2 2.3.2 的 wheel 是按cp38编的:

conda create -n yolov8 python=3.8 conda activate yolov8 cd ultralytics pip install -e .

装完ultralytics后敲yolo能出帮助信息就说明环境通了。接着装 RKNN-Toolkit2,注意 requirements 和 wheel 的路径要对上:

pip install -r ./rknn-toolkit2/packages/x86_64/requirements_cp38-2.3.2.txt -i https://mirrors.aliyun.com/pypi/simple/ pip install ./rknn-toolkit2/packages/x86_64/rknn_toolkit2-2.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

装完在 Python 里from rknn.api import RKNN不报错,前置就算齐了。TaoToken 的 Key 这时候可以先申请好,后面板端跑通后用来回传版本记录。申请入口在控制台 https://taotoken.net/console ,Key 管理在 https://taotoken.net/api-keys 。如果你后面要长期做编码和 Agent 调试,可以看下 Coding Plan https://taotoken.net/coding-plan ,不过这篇主线还是部署,Key 够用就行。

3. 可复制的 RKNN 转换配置与 ONNX 导出参数

这一节是整条链路最容易出错的地方,我把每一步的配置都写全,你直接改路径就能用。

先改ultralytics_yolov8的默认配置,指定模型路径。注意 YAML 里冒号后面必须有空格:

# path_to_your/ultralytics_yolov8/ultralytics/cfg/default.yaml model: ./yolov8n.pt # 换成你 yolov8n.pt 的实际路径 data: coco128.yaml epochs: 100

然后导出 ONNX。关键是要在ultralytics_yolov8目录下执行,并且把当前目录加进PYTHONPATH,否则它会去 import 主线的 ultralytics:

cd path_to_your/ultralytics_yolov8 export PYTHONPATH=./ yolo export model=yolov8n.pt format=onnx opset=12

opset=12是我实测下来最稳的版本。opset 太高(比如 17)会引入一些 RKNN 还没支持的算子,转的时候直接报Unsupported op。导出成功后目录下会有yolov8n.onnx,用netron打开确认输出节点是三个检测头,而不是带 NMS 的完整图。

接下来是 RKNN 转换。rknn_model_zoo里带了convert.py,但它的默认参数不一定适合你的场景,我建议直接写一个转换脚本,把量化参数显式写出来:

# convert_rknn.py from rknn.api import RKNN rknn = RKNN(verbose=True) # 预处理配置,mean/std 要和训练时一致 rknn.config( mean_values=[[0, 0, 0]], std_values=[[255, 255, 255]], target_platform='rk3576', quantized_dtype='asymmetric_quantized-8', # i8 非对称量化 quantized_algorithm='normal', optimization_level=3, ) # 加载 ONNX ret = rknn.load_onnx(model='./yolov8n.onnx') assert ret == 0, 'load_onnx failed' # 构建,dataset.txt 里是校准图路径,一行一张 ret = rknn.build(do_quantization=True, dataset='./dataset.txt') assert ret == 0, 'build failed' # 导出 ret = rknn.export_rknn('./yolov8n.rknn') assert ret == 0, 'export failed' rknn.release()

dataset.txt的内容就是校准图路径列表,建议放 100 到 300 张和实际场景接近的图:

./calib/0001.jpg ./calib/0002.jpg ./calib/0003.jpg

如果你用rknn_model_zoo自带的convert.py,命令是这样:

cd path_to_your/ultralytics_yolov8 python convert.py ./yolov8n.onnx rk3576 i8 ../model/yolov8n.rknn

参数顺序是onnx路径 平台 量化类型 输出路径。i8就是 8 位整数量化,fp16是半精度不量化。精度掉点严重时,先用fp16转一版做对照,如果fp16精度正常而i8掉点,那问题就锁定在量化校准上。

这里插一句模型版本管理。每次转换完,把 ONNX 的 md5、校准集名称、量化类型记下来,通过 TaoToken 的 API 通道发一条记录。这样板端跑出问题时,你能立刻知道当前加载的是哪版。API 调用示例:

curl -X POST https://taotoken.net/api/v1/records \ -H "Authorization: Bearer $TAOTOKEN_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"yolov8n","onnx_md5":"abc123","quant":"i8","calib":"scene_v2"}'

具体字段以接入文档为准,文档在 https://taotoken.net/doc 。这一步不是必须的,但边缘设备一多,没有版本记录会非常痛苦。

4. 板端编译与推理验证:从 build-linux.sh 到检测框输出

PC 侧转出yolov8n.rknn后,把它拷到板子上编译运行。板端操作建议直接 ssh 进去做,adb也行。

先编译rknn_model_zoo里的 YOLOv8 demo。注意-t指定平台rk3576,-a指定架构aarch64,-d指定 demo 名yolov8:

cd path_to_your/rknn_model_zoo bash build-linux.sh -t rk3576 -a aarch64 -d yolov8

编译过程会拉 cmake 配置,如果报找不到交叉编译器,检查build-linux.sh里的GCC_COMPILER路径是不是指向你本机的aarch64-linux-gnu-gcc。编译成功后产物在install/rk3576_linux_aarch64/rknn_yolov8_demo/。

把模型拷进 demo 的 model 目录:

cp path_to_your/yolov8n.rknn \ path_to_your/rknn_model_zoo/install/rk3576_linux_aarch64/rknn_yolov8_demo/model/

然后跑测试图:

cd path_to_your/rknn_model_zoo/install/rk3576_linux_aarch64/rknn_yolov8_demo ./rknn_yolov8_demo model/yolov8n.rknn model/bus.jpg

跑通的话会在当前目录生成out.jpg,用scp拉回 PC 看,框应该正常画在公交车和人上。如果框位置全错或者数量不对,先别怀疑模型,检查model/bus.jpg的尺寸和 demo 里预处理是否匹配。

实时检测的话,demo 支持接摄像头。RK3576 一般走 MIPI CSI,设备节点是/dev/video0之类。改一下运行参数:

./rknn_yolov8_demo model/yolov8n.rknn /dev/video0

实测下来 YOLOv8n 在 RK3576 上单帧推理大概 15 到 25 毫秒,加上前后处理,整体能到 25 到 30 FPS,做实时检测够用。如果帧率明显偏低,用rknn_query查一下是不是跑在了 CPU 上而不是 NPU。

验证成功的标志有三个:out.jpg里框位置正确、终端打印的推理耗时在几十毫秒量级、连续跑十分钟不崩。到这一步,模型部署链路就算通了。

5. 常见报错排查:401、local proxy failed 与量化掉点

部署过程里报错集中在几类,我按实际遇到的频率排一下。

第一类:RKNN 转换时报Unsupported op。九成是 ONNX 导出时用了官方 ultralytics 而不是rk_opt_v1分支。回去检查PYTHONPATH是不是指向了ultralytics_yolov8,yolo export命令是不是在那个目录下执行的。另一个可能是 opset 太高,降到 12 重导。

第二类:板端加载模型报rknn_init failed。先确认.rknn的 target_platform 是rk3576而不是rk3588。平台不匹配的模型加载会直接失败。用rknn.config时平台参数写错,转出来的模型在板子上就是废的。

第三类:量化后精度掉点严重。这是最隐蔽的。排查顺序:先用fp16转一版,如果fp16正常,说明是量化问题。然后检查dataset.txt里的校准图,是不是和实际场景差太远。我试过用 COCO 的图去校准一个工业缺陷检测模型,mAP 直接掉到个位数,换成产线实拍图后恢复到正常水平。校准图数量建议 200 张左右,太少统计不准,太多转换慢。

第四类:TaoToken API 调用报 401。这是 Key 没带对或者过期了。检查Authorization头是不是Bearer加 Key,中间有空格。Key 在 https://taotoken.net/api-keys 管理,重新生成一个再试。如果报local proxy failed,那是本地网络出口的问题,不是 Key 的问题,检查板子或 PC 的网络配置能不能正常访问外网。

第五类:板端 demo 报reading choices或输出解析异常。这通常是模型输出节点数量和 demo 里硬编码的不一致。rk_opt_v1分支导出的 ONNX 是三个输出头,如果你自己改了模型结构,demo 的后处理就对不上。用netron确认输出节点数,和rknn_model_zoo里yolov8demo 的postprocess.cc对照。

第六类:OAuth 或鉴权相关报错。如果你用 TaoToken 的某些需要 OAuth 的接口,token 过期会报这个。重新走一遍授权流程,或者直接用 API Key 方式调用,简单直接。

排查时记住一个原则:先隔离变量。PC 侧转换和板端运行分开验证,fp16和i8分开对比,校准集换一批再测。每次只改一个变量,才能定位到具体哪一步出的问题。

6. 把调试链路固定下来:模型对话与接入文档的配合用法

链路跑通一次不难,难的是每次换模型、换场景都能稳定复现。我的做法是把整个流程脚本化,PC 侧一个convert.sh管转换,板端一个run.sh管编译运行,中间用 TaoToken 的 API 通道串版本记录。

转换脚本里把 ONNX md5、量化类型、校准集名称作为参数传进去,转换完自动发一条记录。板端启动时先拉一次最新记录,确认加载的模型和 PC 侧记录一致。这样多块板子并行调试时不会搞混。

调试日志这块,板端 demo 默认打印到 stdout,你可以重定向到文件再通过 API 通道上传关键字段。不需要传全部日志,只传推理耗时、检测框数量、模型哈希这几个值就够定位问题。

如果你在调试过程中需要对比不同模型的行为,可以用模型对话入口 https://taotoken.net/model-chat 快速验证 API 通道是否正常,确认 Key 和网络都没问题。接入细节以文档为准,https://taotoken.net/doc 里有完整的参数说明和示例。

长期做边缘编码和 Agent 调试的话,Coding Plan https://taotoken.net/coding-plan 能省掉每次配 Key 的麻烦,不过部署这条链路本身用普通 Key 就够。

最后给个实用技巧:板端存储紧张时,别把每版.rknn都留着。转完一版,测完精度,把模型哈希和实测指标记到 TaoToken,然后删掉板上的旧模型。需要回溯时按哈希重新转一版就行,转换脚本参数都固定了,复现成本很低。这样板子永远只存当前最优的那一版,省空间也省得搞混。

返回列表