RDK-X5部署YOLOv8n Detect:从 .pt 导出 ONNX 并转换为 BPU .bin(Bayes-E / NV12)

本文整理一套可复用的流程:将 Ultralytics YOLOv8 的 PyTorch 权重(.pt)导出为 ONNX(.onnx),再通过地平线工具链编译为 BPU 可执行的 .bin,并补充一个常见坑:部分 bbox 输出头的反量化(Dequantize)节点需要移除,否则后处理结果可能异常。

资源下载RDK X5 主板资料(百度网盘) 提取码: f1w1

前置准备

安装 bpu_infer_lib(示例)

1
pip install bpu_infer_lib_x5 -i http://sdk.d-robotics.cc:8080/simple/ --trusted-host sdk.d-robotics.cc

Python 镜像源(示例)

1
pip3 install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

Git 配置(SSH 方式,示例)

  1. 生成 SSH 密钥对
1
ssh-keygen -t rsa
  1. 添加公钥到 Gitee → 设置 → SSH 公钥
1
cat ~/.ssh/id_rsa.pub
  1. 修改远程仓库地址
1
git remote set-url origin git@gitee.com:你的用户名/仓库.git
  1. 提交代码
1
2
3
git add .
git commit -m "提交信息"
git push origin master

1. 环境与项目准备

  1. 拉取 Ultralytics 仓库并按官方文档配置环境
1
git clone https://github.com/ultralytics/ultralytics.git
  1. 下载预训练权重(以 YOLOv8n Detect 为例)
1
2
cd ultralytics
wget https://github.com/ultralytics/assets/releases/download/v8.2.0/yolov8n.pt

2. 导出前:修改 Detect 输出头(关键)

目标:把三个特征层的 Bounding Box 信息和 Classify 信息拆分输出,一共 6 个输出头,并确保输出顺序固定(否则后续编译/解析可能报错)。

文件:./ultralytics/ultralytics/nn/modules/head.py
位置:Detect 类的 forward 方法(建议先备份原始实现,例如重命名为 forward_,训练时再切回)。

1
2
3
4
5
6
def forward(self, x):
result = []
for i in range(self.nl):
result.append(self.cv3[i](x[i]).permute(0, 2, 3, 1).contiguous())
result.append(self.cv2[i](x[i]).permute(0, 2, 3, 1).contiguous())
return result

如果导出的 ONNX 输出头顺序与预期不一致,可以通过调整 append 的顺序来对齐。

3. 导出为 ONNX

如果出现命令行 yolo/ultralytics 版本混乱,建议先确认当前 Python 环境中 ultralytics 的实际加载路径。

1
2
conda list | grep ultralytics
pip list | grep ultralytics

如存在已安装的包,可先卸载,避免与本地仓库源码冲突:

1
2
conda uninstall ultralytics
pip uninstall ultralytics

定位实际加载目录(示例):

1
python -c "import ultralytics; print(ultralytics.__path__)"

执行导出(按需修改 imgsz):

1
2
from ultralytics import YOLO
YOLO('yolov8n.pt').export(imgsz=640, format='onnx', simplify=True, opset=11)

4. PTQ 量化与编译(hb_mapper)

参考工具链手册与 OE 包(OpenExplore)进行模型检查,确保算子均可在 BPU 上执行,然后进行编译。

示例命令:

1
2
hb_mapper checker --model-type onnx --march bayes-e --model yolov8n.onnx
hb_mapper makertbin --model-type onnx --config config_yolov8_detect_nv12.yaml

5. 移除 bbox 输出头的反量化节点(常见坑)

在某些配置下,bbox 相关输出头会带反量化节点,若直接使用可能导致后处理结果不正确。一个经验口诀:尺寸里带 64 的输出往往对应 4 * REG (REG=16) 的 bbox 分支,常见需要处理。

  1. hb_mapper makertbin 日志确认输出名称(示例):
1
2
3
4
5
6
7
Graph output:
output0: shape=[1, 80, 80, 1], dtype=FLOAT32
326: shape=[1, 40, 40, 64], dtype=FLOAT32
334: shape=[1, 20, 20, 1], dtype=FLOAT32
342: shape=[1, 80, 80, 64], dtype=FLOAT32
350: shape=[1, 40, 40, 1], dtype=FLOAT32
358: shape=[1, 20, 20, 64], dtype=FLOAT32
  1. 进入编译产物目录(示例):
1
cd yolov8n_bayese_640x640_nv12
  1. 生成 hb_model_modifier.log 并查找 Dequantize 节点(示例):
1
hb_model_modifier yolov8n_bayese_640x640_nv12.bin

日志里常能看到类似名称(示例):

1
2
3
/model.22/cv2.0/cv2.0.2/Conv_output_0_HzDequantize
/model.22/cv2.1/cv2.1.2/Conv_output_0_HzDequantize
/model.22/cv2.2/cv2.2.2/Conv_output_0_HzDequantize
  1. 移除上述节点(名称以你实际导出的为准):
1
2
3
4
hb_model_modifier yolov8n_detect_bayese_224x224_nv12.bin \
-r /model.22/cv2.0/cv2.0.2/Conv_output_0_HzDequantize \
-r /model.22/cv2.1/cv2.1.2/Conv_output_0_HzDequantize \
-r /model.22/cv2.2/cv2.2.2/Conv_output_0_HzDequantize

最终产物通常形如 *_modified.bin,即可用于板端推理或对接 TROS 功能包。

6. 简要部署建议

  • NCHW 输入模型:可用 OpenCV + numpy 准备输入数据。
  • NV12 输入模型:可用 codec/jpu/vpu/gpu 等硬件模块准备输入数据,或直接对接对应中间件/功能包。

分享
RDK-X5部署YOLOv8n Detect:从 .pt 导出 ONNX 并转换为 BPU .bin(Bayes-E / NV12)
https://asteriayx.github.io/ai/yolov8-pt-to-bpu-bin/
作者
yuxin
发布于
2026年6月12日
许可协议