ARTICLE DETAIL

资讯详情

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

rknn模型转换问题记录:yolov5s从onnx到rk3588的TaoToken配置与排错

rknn模型转换问题记录:yolov5s从onnx到rk3588的TaoToken配置与排错 1. yolov5s 转 rknn 为什么总在 rk3588 上翻车把 yolov5s 的 onnx 丢给 rknn-toolkit2 转成 rknn再部署到 rk3588 上跑推理这条链路看起来只有三步导出 onnx、转换 rknn、板端加载。但真正动手的人都知道报错往往不在转换那一步而是转换成功之后板端输出一堆乱七八糟的框或者干脆加载失败。我这次记录的就是这类问题转换过程无报错rk3588 上却输出目标过多识别框满天飞。先说清楚这套东西是什么、能做什么、适合谁。rknn 是瑞芯微给自家 NPU 用的模型格式rk3588 内置 6TOPS 算力的 NPU只有把 onnx 转成 rknn 才能吃到这个算力。yolov5s 是最常见的轻量检测模型参数量小、速度快适合边缘盒子做实时检测。适合谁做边缘 AI 部署、想在 rk3588 上跑目标检测、又不想从零啃 RKNN SDK 的开发者。如果你正好卡在转换成功但推理结果不对这个坎上这篇就是给你写的。核心检索词先摆出来rknn 模型转换、yolov5s onnx 转 rk3588、rknn.config mean_values std_values、rk3588 NPU 推理输出异常。这几个词基本覆盖了你会搜到的所有入口。问题的本质其实不复杂。yolov5s 导出 onnx 时输出层结构、anchor 数量、类别数都会影响 rknn 的解析。rk3588 的 NPU 对输入输出的维度、量化参数非常敏感尤其是 mean_values 和 std_values 这两个归一化参数一旦和训练时不一致或者被误删模型输出的数值范围就全乱了后处理解出来的框自然离谱。我踩过的坑就是早期测试时把 mean_values 和 std_values 删掉图省事结果转换没报错板端输出爆炸查了两天才发现是这两个参数没了。还有一个高频坑是输出维度。yolov5 不同版本输出层数不一样yolov5-6.0 默认输出四个分支但 rknn 转换时通常只需要三个特征层输出多出来的那个会干扰解析。正确做法是导出 onnx 时就把输出固定成三个对应 80×80、40×40、20×20 三个尺度。每个输出的通道数是 255这个 255 3 × 853 是每个网格三个 anchor85 5 805 是 box 四坐标加一个置信度80 是类别数。理解这个拆解后面排查输出异常就有方向了。工具侧接入这块我用 TaoToken 统一管理 Key 和 API 通道把模型转换脚本、板端推理服务、以及调用大模型做日志分析的环节都走同一个入口省得每个工具单独配一遍。下面从环境准备开始一步步给可复制的配置和命令。2. TaoToken 前置准备统一 Key 与 API 通道在动手转模型之前先把工具侧的接入通道理顺。为什么要先做这一步因为整个流程里你会用到多个工具本地跑 rknn-toolkit2 的转换脚本、板端跑推理的服务、可能还有用大模型帮忙分析报错日志的脚本。如果每个都单独配 Key管理起来很乱而且换环境时容易漏配。TaoToken 的作用就是提供一个统一的 Key 和 API 通道把这些工具侧的调用收敛到一个入口。先拿到 Key。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台创建 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 进去之后左侧找 API Keys新建一个复制出来保存好。这个 Key 后面会写进配置文件。API 的基础地址是 https://taotoken.net/api 注意这个地址不带 UTM 参数配置里直接写这个就行。模型对话的入口在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 如果你想让大模型帮你分析转换日志可以走这个通道。长期做编码和 Agent 任务的可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到配置问题先翻这个。这里要强调一点TaoToken 是合规的 API 通道服务不是那种灰色中转配置时按官方文档来别自己乱改地址。我见过有人把 Base URL 写成别的结果 401排查半天。配置文件的骨架我放在下一节这里先把 Key 和地址准备好。你需要记下三样东西API Keysk- 开头那串、Base URLhttps://taotoken.net/api 、以及你要用的 Model ID。Model ID 在模型列表页能看到选一个适合做代码分析和日志解读的就行。如果你用的是 Claude Code 这类工具配置方式略有不同需要设置 ANTHROPIC_BASE_URL 和 ANTHROPIC_API_KEY具体在接入文档里有说明。Cline 或 MCP 类的工具则是在 settings.json 里配 Base URL、Key、Model ID 三件套。Codex 的话看 auth.json。不管哪种核心都是这三样Base URL、Key、Model ID缺一不可。准备好这些就可以进入实际的模型转换环节了。工具侧通道理顺之后后面转换脚本里如果需要调用大模型做辅助分析直接读同一份配置就行不用再单独折腾。3. 可复制配置config.toml 与 settings.json 骨架这一节给可直接复制的配置片段。先说清楚路径TaoToken 相关的配置我放在项目根目录的 config.toml工具侧的 settings.json 放在对应工具的配置目录。路径和原文保持一致你照着建就行。先看 config.toml这是给转换脚本和辅助分析脚本读的# config.toml [taotoken] base_url https://taotoken.net/api api_key sk-你的Key替换这里 model_id 你的ModelID timeout 60 [rknn] onnx_path ./yolov5s.onnx rknn_path ./yolov5s.rknn target_platform rk3588 mean_values [[0, 0, 0]] std_values [[255, 255, 255]] quantized_dtype asymmetric_quantized-8注意 mean_values 和 std_values 这两行就是我前面说的血泪教训。yolov5 训练时输入是 0-255 的像素值归一化到 0-1 是靠除以 255所以 std_values 写 255mean_values 写 0。如果你训练时用了别的归一化方式这里要对应改。删掉这两行转换不报错但板端输出全乱。再看 settings.json这是给 Cline 或 MCP 类工具用的{ mcpServers: { taotoken: { command: npx, args: [-y, taotoken/mcp-server], env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: sk-你的Key替换这里, TAOTOKEN_MODEL_ID: 你的ModelID } } } }如果你用的是 Claude Code配置写在环境变量或对应的 settings 里{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的Key替换这里, ANTHROPIC_MODEL: 你的ModelID } }Codex 的 auth.json 类似{ base_url: https://taotoken.net/api, api_key: sk-你的Key替换这里, model: 你的ModelID }三件套记住Base URL、Key、Model ID。任何工具接入都是这三样位置不同而已。接下来是转换命令。rknn-toolkit2 的转换脚本我写成 onnx2rknn.py核心部分from rknn.api import RKNN rknn RKNN(verboseTrue) rknn.config( mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3588, quantized_dtypeasymmetric_quantized-8 ) ret rknn.load_onnx(model./yolov5s.onnx) if ret ! 0: print(load_onnx failed) exit(ret) ret rknn.build(do_quantizationTrue, dataset./dataset.txt) if ret ! 0: print(build failed) exit(ret) ret rknn.export_rknn(./yolov5s.rknn) if ret ! 0: print(export failed) exit(ret) rknn.release()dataset.txt 里放量化校准图片的路径每行一张准备 100 到 200 张和训练集同分布的图。量化校准做不好精度掉得厉害。导出 onnx 这一步也要注意输出层。yolov5 导出时用python export.py --weights yolov5s.pt --include onnx --opset 12如果你用的是 airockchip 的 yolov5 分支导出脚本已经改好了输出结构直接用。标准版 yolov5-6.0 导出会有四个输出需要在导出前改模型结构把输出固定成三个。改法参考模型里的 Detect 层把训练时的辅助输出去掉。配置和命令都给全了下一节验证请求和成功结果。4. 验证请求与成功结果从转换到板端推理配置写完先别急着上板子在 PC 上验证转换结果。rknn-toolkit2 提供了模拟推理功能可以在没有 NPU 的机器上跑一遍看输出维度对不对。验证脚本 verify.pyfrom rknn.api import RKNN import numpy as np rknn RKNN() ret rknn.load_rknn(./yolov5s.rknn) if ret ! 0: print(load rknn failed) exit(ret) ret rknn.init_runtime() if ret ! 0: print(init runtime failed) exit(ret) img np.random.rand(1, 3, 640, 640).astype(np.float32) * 255 outputs rknn.inference(inputs[img]) for i, out in enumerate(outputs): print(foutput[{i}] shape: {out.shape}) rknn.release()跑通的话你会看到三个输出形状分别是 (1, 255, 80, 80)、(1, 255, 40, 40)、(1, 255, 20, 20)。如果输出是四个说明 onnx 导出时没改结构。如果形状不对比如通道数不是 255检查类别数和 anchor 配置。如果输出数值范围异常比如全是 0 或者特别大回头查 mean_values 和 std_values。PC 验证通过后把 rknn 文件拷到 rk3588 板子上。板端推理用 rknn-toolkit-lite2 或者 C 接口的 rknn_api。Python 版验证from rknnlite.api import RKNNLite import numpy as np rknn_lite RKNNLite() ret rknn_lite.load_rknn(./yolov5s.rknn) if ret ! 0: print(load rknn failed) exit(ret) ret rknn_lite.init_runtime(core_maskRKNNLite.NPU_CORE_0) if ret ! 0: print(init runtime failed) exit(ret) img np.random.rand(1, 3, 640, 640).astype(np.float32) * 255 outputs rknn_lite.inference(inputs[img]) for i, out in enumerate(outputs): print(foutput[{i}] shape: {out.shape}, dtype: {out.dtype}) rknn_lite.release()板端跑通输出形状和 PC 一致就说明转换和部署链路没问题。接下来接后处理把三个输出解码成框。yolov5 的后处理逻辑是每个网格预测三个 anchor 的偏移加上类别分数做 NMS。如果前面 mean/std 配错这一步解出来的框会满天飞置信度也乱。成功的结果应该是输入一张真实图片板端推理后能正确框出目标置信度合理框的位置和 PC 上 PyTorch 推理结果接近。如果框的数量明显偏多先查 mean/std再查输出层数最后查后处理的 anchor 配置是否和训练时一致。我实测下来只要 mean_values 和 std_values 配对输出层数正确板端结果和 PC 基本一致。量化带来的精度损失在可接受范围内mAP 掉 1 到 2 个点正常。5. 常见报错排查401、local proxy failed、reading choices、OAuth这一节对照真实报错一个个排。这些报错有的是工具侧接入问题有的是模型转换问题分开看。401 Unauthorized。这个基本是 Key 配错了。检查 config.toml 或 settings.json 里的 api_key 是不是复制完整有没有多余空格。Base URL 确认是 https://taotoken.net/api 别写成别的。如果用的是 Claude Code检查 ANTHROPIC_API_KEY 和 ANTHROPIC_BASE_URL 是否都设了。401 还可能是 Key 过期或被删去控制台重新生成一个。local proxy failed。这个报错通常出现在工具尝试走本地代理但代理没起来。检查你的环境变量里有没有 HTTP_PROXY 或 HTTPS_PROXY 指向一个不存在的本地端口。有的话清掉或者确认代理服务在跑。TaoToken 的接入不需要额外代理直连 Base URL 就行。如果公司网络有要求按网络管理员的配置来别自己乱设。reading choices 相关报错。这个多出现在调用模型接口返回格式解析时。检查 Model ID 是否写对模型列表页确认一下。如果返回体里没有 choices 字段可能是请求体格式不对或者模型不支持当前调用方式。对照接入文档里的请求示例检查 messages 结构、role 字段、content 格式。还有一种情况是超时把 timeout 调大config.toml 里我写了 60 秒网络慢的话加到 120。OAuth 相关报错。如果你用的是需要 OAuth 的工具检查 token 是否过期。有些工具会缓存 OAuth token过期后需要重新授权。清掉缓存重新走一遍授权流程。如果是 Claude Code 的 OAuth确认登录状态必要时重新登录。模型转换侧的报错。load_onnx failed 通常是 onnx 文件路径不对或文件损坏用 onnxruntime 先验证一下 onnx 能不能加载。build failed 多半是量化校准数据集有问题检查 dataset.txt 里的图片路径是否存在图片格式是否支持。export_rknn failed 检查输出路径权限。板端加载失败。load_rknn failed 检查 rknn 文件是否完整拷贝板端 rknn 驱动版本和转换时 toolkit 版本是否匹配。版本不匹配是高频坑rknn-toolkit2 的版本要和板端 runtime 版本对应差一个大版本就可能加载失败。输出框过多。回到 mean_values 和 std_values确认没删、没写错。再确认输出层数是三个不是四个。最后检查后处理的 anchor 和类别数是否和训练时一致。这三个都对了框就正常了。排查顺序建议先看工具侧 401 和 proxy再看模型转换的 load/build/export最后看板端加载和输出。每步都有明确的检查点别跳步。6. 把 TaoToken 接入你的 rknn 工作流模型转换和板端推理跑通之后工具侧的接入可以进一步固化。我的做法是把 TaoToken 的配置放在项目根目录转换脚本、日志分析脚本、板端服务都读同一份 config.toml。这样换机器、换环境时只改一处 Key 就行。具体来说转换脚本里如果需要大模型帮忙解读 rknn 的 verbose 日志直接读 config.toml 里的 base_url 和 api_key调模型对话接口。板端服务如果需要上报推理统计或异常也走同一个通道。Coding Plan 适合长期做这类边缘部署项目的Agent 任务可以挂上去省得每次手动跑。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 配置遇到问题先翻这个。API Keys 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite Key 轮换或新建都在这。模型对话入口 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 需要让模型分析日志时走这里。最后给一个实用技巧把 mean_values 和 std_values 写进转换脚本的注释里标清楚为什么是这两个值。下次再有人包括未来的你改这个脚本看到注释就不会手贱删掉。这个坑我踩过一次不想再踩第二次。转换命令和验证脚本都存进项目仓库配一份 README 说明版本对应关系rknn-toolkit2 版本、板端 runtime 版本、onnx opset 版本都记下来。边缘部署最怕版本漂移记清楚能省很多排查时间。
返回列表