本文记录一次把 YOLO11n 的 ONNX 模型转换成 MaixCAM2 可用文件的完整过程。
MaixCAM2 不能直接运行电脑上训练出来的 onnx 文件,一般需要先做 INT8 量化,再转换成 MaixCAM2 支持的 .axmodel,最后用一个 .mud 文件描述模型信息。最终我们需要得到这三个文件:
1 | |
其中:
yolo11n_npu.axmodel:使用完整 NPU 算力,对应NPU2。yolo11n_vnpu.axmodel:使用虚拟 NPU,对应NPU1,适合需要给 AI-ISP 留算力的情况。yolo11n.mud:MaixPy 读取的模型描述文件,里面记录模型类型、类别标签、预处理参数和两个 axmodel 文件名。
本文参考了 Sipeed 的 MaixPy 文档:
准备文件
我的转换目录如下:
1 | |
目录中先放好模型和校准图片:
1 | |
images 文件夹是量化校准图片。图片最好来自模型真实使用场景,数量可以几十张到几百张。本文示例中用了 30 张图片,所以配置文件里 calibration_size 写 30。
查看模型
可以用 Netron 打开 yolo11n.onnx 查看模型结构。
对 MaixCAM2 的 YOLO11 目标检测模型,官方文档推荐使用方案一,也就是这三个输出节点:
1 | |
我这个模型的原始 ONNX 信息是:
1 | |
原始最终输出 output0 [1,84,8400] 是 YOLO 后处理前的合并输出。为了让 MaixPy 的 nn.YOLO11 更容易识别,我没有直接拿 output0 做输出,而是把模型整理成三尺度检测头输出:
1 | |
这里的 144 = 64 + 80,其中 64 是 YOLO11 的 bbox 分布回归通道,80 是 COCO 类别数。如果你是自定义类别,类别数不一定是 80,这里要按自己的模型输出为准。
Docker 环境
本文使用 Docker 中的 Pulsar2 工具链转换模型。我本机镜像是:
1 | |
可以看到:
1 | |
进入转换目录后,后面所有命令都在 PowerShell 中执行:
1 | |
这里把当前 Windows 目录挂载到 Docker 容器的 /data:
1 | |
我这个镜像里的 pulsar2 命令实际路径是:
1 | |
所以脚本里直接使用这个完整路径。
准备转换目录
在 D:\code\onnx_to_mud\2\teach 下创建这些文件夹:
1 | |
作用如下:
1 | |
整理 ONNX 输出节点
新建 prepare_yolo11_maixcam2_onnx.py,用于从原始模型中取出三个尺度的 bbox 和 cls 输出,并重新拼成 MaixPy 更好解析的三尺度输出。
1 | |
如果你的模型不是标准 COCO 80 类 YOLO11n,或者 Netron 里节点名称不同,就要按自己的模型结构改 pairs 里的节点名和输出通道数。
编写 Pulsar2 配置
config/yolo11n.vnpu.json:
1 | |
config/yolo11n.npu.json 和上面基本一样,只把 npu_mode 改成 NPU2:
1 | |
几个关键参数说明:
target_hardware:命令行里指定为AX620E,对应 MaixCAM2。npu_mode = NPU1:虚拟 NPU,只用一部分 NPU 算力,生成model_vnpu。npu_mode = NPU2:完整 NPU,生成model_npu。calibration_dataset:校准图片打包后的tar文件。calibration_size:校准图片数量,不能比实际图片数量大。calibration_mean和calibration_std:对应 YOLO 常见预处理x / 255。dst_perm [0,2,3,1]:把输出从NCHW转成NHWC,方便 MaixPy 后处理解析。
一键转换脚本
新建 convert_yolo11n_maixcam2.sh:
1 | |
执行转换:
1 | |
转换过程会比较久,中间会看到量化校准、精度分析和 NPU 编译日志。成功时会出现类似下面的信息:
1 | |
我这次转换后,三个输出被检查为:
1 | |
这说明输出已经从 NCHW 转成了 NHWC。
编写 MUD 文件
在 out 目录新建 yolo11n.mud:
1 | |
如果是自己训练的模型,一定要把 labels 改成自己的类别,而且顺序要和训练数据集的类别顺序一致。
最终文件
转换完成后,out 目录里应该有:
1 | |
我这次生成的文件大小大致如下:
1 | |
使用时把这三个文件放到 MaixCAM2 的同一个目录即可,例如:
1 | |
MaixPy 加载测试
在 MaixCAM2 上可以用 maix.nn.YOLO11 加载:
1 | |
如果加载时报 model output not valid 一类错误,优先检查:
.mud中的model_type是否是yolo11。.mud中的type是否是detector。labels数量是否和模型类别数一致。- 输出节点形状是否是三尺度检测头,而不是直接拿了最终
output0 [1,84,8400]。 model_npu、model_vnpu文件名是否和实际文件名一致。
小结
整个流程可以概括为:
1 | |
MaixCAM2 的目标硬件是 AX620E,转换时建议同时生成 NPU1 和 NPU2 两个版本,这样后面是否启用 AI-ISP 都能选择合适的模型。