征程6|YOLOv5x 在 Horizon J6 平台的完整部署实战(上)

YOLOv5x 在 Horizon J6 上的端到端部署实践(上):工具链部署

本文记录 YOLOv5x 从 PyTorch 权重到 J6 可执行 HBM 模型的部署流程。上篇聚焦工具链侧:环境准备、ONNX 导出、校准数据生成和 HBM 编译;下篇再展开板端 C++ 推理部署与精度评估。

平台 :Horizon J6 (nash-e)

SDK :horizon_j6_open_explorer_v3.8.1-py310

模型 :YOLOv5x,输入分辨率 640x640

板端输入:NV12;PC 端校准输入:RGB float32


1. 环境准备

首先安装 SDK 中的 host 端工具链和 board 端运行时:

bash 复制代码
cd horizon_j6_open_explorer_v3.8.1-py310_20260326/package/host
bash install.sh

cd ../board
bash install.sh

Python 侧需要准备模型导出、ONNX 处理、校准与评估相关依赖:

bash 复制代码
pip install torch onnx onnxsim onnxruntime opencv-python-headless pycocotools

Horizon 工具链建议使用 SDK 自带 whl 安装,重点包括:

  • horizon_tc_ui
  • hmct
  • hbdk4_compiler

后续操作均在示例工程目录中进行:

bash 复制代码
cd horizon_j6_open_explorer_v3.8.1-py310_20260326/nano_toolchain/yolov5x_End-to-End_Pipeline/

2. Stage 1:PyTorch 导出 ONNX

YOLOv5 的 .pt 权重是包含 Python 对象引用的序列化文件,因此导出前需要确保 YOLOv5 源码在 Python 路径中。SDK 中已经包含对应源码,可直接复用:

bash 复制代码
nano_toolchain/model_convert/detection/yolov5x_scratch/yolov5_repo/

导出流程可以概括为:

  1. 加载 yolov5x.pt
  2. 设置模型为 evalexport 状态
  3. 构造 (1, 3, 640, 640) 的 dummy input
  4. 使用 torch.onnx.export 导出 ONNX
  5. 使用 onnxsim 简化模型

执行命令:

bash 复制代码
python3 stage1_model_export.py \
  --weights ./model/yolov5x.pt \
  --img-size 640 \
  --batch-size 1 \
  --include onnx \
  --opset 12 \
  --simplify

导出后得到:

文件 说明
model/yolov5x.pt 原始 PyTorch 权重
model/yolov5x.onnx 简化后的 ONNX 模型

模型输出包含三个检测头:

scss 复制代码
P3/8   (1, 3, 80, 80, 85)
P4/16  (1, 3, 40, 40, 85)
P5/32  (1, 3, 20, 20, 85)

其中 85 = 4(bbox) + 1(obj) + 80(classes)


3. Stage 2:生成校准数据

PTQ 量化需要少量代表性样本来统计激活分布。一般选择 50 到 500 张图片即可,关键是预处理必须和后续推理保持一致。

本流程中的校准预处理为:

rust 复制代码
原始图片
  -> Letterbox Resize 到 640x640,padding=114
  -> BGR 转 RGB
  -> HWC 转 CHW
  -> /255 归一化
  -> 保存为 .npy

执行:

bash 复制代码
mkdir -p calib_images
# 从 COCO 验证集拷贝若干图片到 calib_images/

python3 stage2_calibration_set.py

输出目录:

erlang 复制代码
calibration_data_yolov5/
├── xxx.npy
├── yyy.npy
└── ...

每个 .npy 文件的格式为:

makefile 复制代码
shape: (1, 3, 640, 640)
dtype: float32
range: [0, 1]

4. Stage 3:ONNX 编译为 HBM

Horizon 工具链的大致链路为:

rust 复制代码
ONNX -> hmct 量化校准 -> .bc 量化模型 -> hbdk4 编译 -> .hbm

核心编译配置如下:

yaml 复制代码
model_parameters:
  onnx_model: model/yolov5x.onnx
  march: nash-e
  working_dir: ./model_output
  output_model_file_prefix: yolov5x_640x640_nv12
  remove_node_type: 'Dequantize'

input_parameters:
  input_name: images
  input_type_rt: nv12
  input_type_train: rgb
  input_layout_train: NCHW
  input_shape: 1x3x640x640
  norm_type: 'data_scale'
  scale_value: 0.003921568627451

calibration_parameters:
  cal_data_dir: ./calibration_data_yolov5
  calibration_type: 'default'

compiler_parameters:
  compile_mode: latency
  core_num: 1
  optimize_level: O2
  jobs: 16

这里最需要注意的是:

  • march: nash-e 对应 J6 BPU 架构。
  • input_type_rt: nv12 表示板端运行时输入为 NV12。
  • input_type_train: rgb 与校准数据保持一致。
  • scale_value: 1/255 表示板端运行时由模型完成归一化。

编译命令:

bash 复制代码
hb_compile -c full_compile_config.yaml

主要产物:

复制代码
model_output/
├── yolov5x_640x640_nv12.hbm
├── yolov5x_640x640_nv12_quantized_model.bc
├── yolov5x_640x640_nv12_original_float_model.onnx
├── yolov5x_640x640_nv12_quant_info.json
└── yolov5x_640x640_nv12.html

其中 .hbm 是后续板端部署使用的模型文件。


5. 查看模型输入输出

将 HBM 放到板端后,可以用 hrt_model_exec 查看模型信息:

bash 复制代码
hrt_model_exec model_info --model_file yolov5x_640x640_nv12.hbm

输入一般会被拆成两个 NV12 tensor:

Tensor Shape 说明
images_y (1, 640, 640, 1) Y 平面
images_uv (1, 320, 320, 2) UV 交错平面

输出仍然是 YOLOv5 的三个检测头,但要特别关注 stride:

ini 复制代码
output: shape=(1,3,80,80,85), stride=(7372800,2457600,30720,384,4)
729:    shape=(1,3,40,40,85), stride=(1843200,614400,15360,384,4)
741:    shape=(1,3,20,20,85), stride=(460800,153600,7680,384,4)

最后一维虽然只有 85 个 float,理论大小是 340 bytes,但实际 col stride 是 384 bytes,说明中间存在 padding。这个细节会直接影响下篇的 C++ 后处理实现。


小结

上篇完成了从 yolov5x.ptyolov5x_640x640_nv12.hbm 的工具链流程。关键点主要有三个:

  1. 导出 ONNX 时要正确加载 YOLOv5 源码和模型结构。
  2. 校准数据预处理要与部署推理保持一致。
  3. 编译配置中要明确 J6 架构、NV12 输入和运行时归一化方式。

下篇将继续介绍如何在 J6 板端用 C++ 加载 HBM、构造 NV12 输入、调用 UCP/DNN API、解析带 padding 的输出,并完成 YOLOv5 后处理和 mAP 评估。

相关推荐
青 春 记 忆1 小时前
LeetCode 104. 二叉树的最大深度|Python 解法详解
python·算法·leetcode
watersink1 小时前
机器学习关联分析
人工智能·算法·机器学习
牛油果子哥q1 小时前
C++STL算法超全精讲:排序/查找/去重/遍历/最值/合并全套API、仿函数、Lambda适配、实战避坑
开发语言·c++·算法
AI服务老曹1 小时前
摄像机安装AI视频分析完整流程:从现场物理安装、硬解配置到算法POC效果验证
人工智能·算法·音视频
孤存5221 小时前
c语言动态内存管理
c语言·开发语言·算法
牛阿大1 小时前
MPC算法
算法
祖力552 小时前
快速学会数据结构中的链式队列与循环队列
linux·c语言·数据结构·算法
原凉是这样的丶2 小时前
Qwen3.8-27B 开源后,我用双 RTX 4090 跑通了:vLLM 0.27.1、128K 上下文与 MTP 实测
linux·算法
码农大叔的博客2 小时前
golang示例:for九九乘法表
开发语言·算法·golang