如果你正在准备地瓜智能车比赛,或者手头有一块拥有 10 TOPS 算力的地平线 RDK X5,并打算用它来跑 YOLOv5 做目标检测(比如识别二维码、障碍物),那你一定会面临一个必经的门槛:模型转换。
RDK X5 的核心优势在于其内置的 BPU(大脑处理器)。直接在 CPU 上跑 PyTorch 的 .pt 文件不仅帧率极低(不到 5 FPS),还会严重占用系统资源。为了发挥 BPU 的全部实力实现几十上百帧的丝滑检测,我们必须使用官方的“天工开物 (OpenExplorer)”工具链,将 .pt 模型转换为 BPU 专属的 .bin 格式。
这篇博客记录了我在 Windows 环境下,使用 Docker 配合 RDK X5 最新 v1.2.8 工具链完成转换的全过程,并总结了几个极其容易踩坑的致命报错及解决方案。
准备工作
- 宿主机系统:Windows 10/11
- 必备软件:Docker Desktop(已开启并在运行)、Python 环境(已安装
ultralytics和onnx) - 目标硬件:地平线 RDK X5 (系统 Ubuntu 22.04)
- 待转换模型:训练好的 YOLOv5 模型
best.pt
第一步:导出 ONNX 模型(避坑 Opset 限制)
天工开物编译器并不直接认识 .pt 文件,我们需要先将其转为 .onnx 中间格式。为了完美控制导出参数和路径,我们不使用终端命令,而是编写一个 Python 导出脚本。
新建一个 Python 文件(例如 export_onnx.py),填入以下代码,并根据你的实际情况修改 PT_MODEL_PATH 和 ONNX_SAVE_PATH:
import torch
from ultralytics import YOLO
import os
import shutil # 新增:用于文件移动/复制
try:
import onnx
if not hasattr(onnx, '__version__'):
onnx.__version__ = "1.15.0"
except ImportError as e:
print("❌ 未安装onnx库,请运行:pip install onnx==1.15.0")
exit(1)
def convert_yolo_pt_to_onnx():
"""
YOLO PT模型转ONNX格式(最终修复版:解决路径不一致问题)
"""
# ======================== 配置参数(仅需修改这里)========================
PT_MODEL_PATH = r"E:\wsy\dg\yolov5\yolov5-7.0\yolov5-7.0\runs\train\exp\weights\best.pt" # 你的PT路径
ONNX_SAVE_PATH = r"E:\wsy\dg\yolov5\yolov5-7.0\onnx\best.onnx" # 期望的ONNX保存路径
INPUT_SIZE = 640
USE_DYNAMIC_BATCH = False
SIMPLIFY_MODEL = True
DEVICE = "cpu"
# =====================================================================
# 1. 前置检查:PT文件是否存在
if not os.path.exists(PT_MODEL_PATH):
print(f"❌ 找不到PT模型文件:{PT_MODEL_PATH}")
return
# 2. 设备适配
if DEVICE == "cuda" and not torch.cuda.is_available():
print("⚠️ CUDA不可用,自动切换到CPU")
DEVICE = "cpu"
try:
# 3. 加载YOLO模型
torch.set_grad_enabled(False)
print(f"📌 正在加载模型:{PT_MODEL_PATH}")
model = YOLO(PT_MODEL_PATH)
print("✅ 模型加载成功")
# 4. 定义ultralytics默认导出路径(PT文件同目录)
pt_dir = os.path.dirname(PT_MODEL_PATH)
default_onnx_path = os.path.join(pt_dir, "best.onnx") # 默认导出路径
# 删除旧的默认ONNX文件(避免缓存干扰)
if os.path.exists(default_onnx_path):
os.remove(default_onnx_path)
# 5. 创建目标保存目录
onnx_dir = os.path.dirname(ONNX_SAVE_PATH)
if not os.path.exists(onnx_dir):
os.makedirs(onnx_dir)
print(f"📌 创建ONNX保存目录:{onnx_dir}")
# 6. 导出ONNX
print(f"📌 正在导出ONNX模型(默认路径:{default_onnx_path})")
export_args = {
"format": "onnx",
"imgsz": INPUT_SIZE,
"dynamic": USE_DYNAMIC_BATCH,
"simplify": SIMPLIFY_MODEL,
"device": DEVICE,
"opset": 11, # ⚠️ 关键避坑点
"verbose": False
}
model.export(**export_args)
# 7. 核心修复:将默认路径的ONNX移动到目标路径
if os.path.exists(default_onnx_path):
# 移动文件(覆盖目标路径已存在的文件)
shutil.move(default_onnx_path, ONNX_SAVE_PATH)
print(f"📌 将ONNX模型从默认路径移动到目标路径:{ONNX_SAVE_PATH}")
else:
print(f"❌ 未找到Ultralytics默认导出的ONNX文件:{default_onnx_path}")
return
# 8. 验证目标路径的ONNX文件
if os.path.exists(ONNX_SAVE_PATH):
print("✅ ONNX模型导出+移动成功!")
try:
onnx_model = onnx.load(ONNX_SAVE_PATH)
onnx.checker.check_model(onnx_model)
print("✅ ONNX模型验证通过!")
except Exception as e:
print(f"⚠️ ONNX验证警告(不影响基本使用):{e}")
else:
print("❌ 移动后目标路径仍无ONNX文件")
except Exception as e:
print(f"❌ 转换出错:{e}")
if "No module named 'onnx'" in str(e):
print("💡 运行:pip install onnx==1.15.0")
elif "file not found" in str(e):
print("💡 检查PT文件路径是否正确,避免中文/空格")
elif "CUDA out of memory" in str(e):
print("💡 改为DEVICE='cpu'")
if __name__ == "__main__":
convert_yolo_pt_to_onnx()
⚠️ 避坑指南 1:Opset 版本过高
注意代码中的 "opset": 11!如果不显式指定,YOLO 默认可能会使用 Opset 12 甚至更高版本导出,而地平线工具链目前最高只稳定支持到 Opset 11。如果版本过高,在后续检查模型时会报出 The opset version of the model is 12, the maximum supported version is 11 的致命错误。此外,代码中的 "simplify": True 也极大提高了模型后续编译的成功率。
第二步:配置 Docker 编译环境
为了不弄脏 Windows 环境,我们使用 Docker 来运行地平线的 Ubuntu 20.04 编译环境。虽然 RDK X5 跑的是 Ubuntu 22.04,但在 Docker 中使用 20.04 进行交叉编译是完全兼容的。
1. 建立工作目录
在 Windows 上(例如 D 盘)创建一个名为 D:\rdk_workspace 的文件夹。
将刚才导出的 best.onnx 放进去,并新建一个名为 calibration_data 的文件夹,里面放入 50~100 张比赛场地的实拍图片(.jpg 或 .png),用于量化校准。
2. 拉取并启动官方工具链镜像
打开 Windows 的管理员命令行(CMD 或 PowerShell),拉取适用于 X5 的 v1.2.8 镜像并挂载我们的工作目录:
# 拉取镜像
docker pull openexplorer/ai_toolchain_ubuntu_20_x5_gpu:v1.2.8
# 启动容器并挂载文件夹到 /data
docker run -it --rm -v D:\rdk_workspace:/data openexplorer/ai_toolchain_ubuntu_20_x5_gpu:v1.2.8
成功执行后,你的命令行提示符会变成类似 root@xxxx:/#,说明你已经进入了地平线的编译环境!
输入 cd /data 即可进入我们挂载的工作目录。
第三步:处理校准图片(避坑二进制格式)
这是新手最容易崩溃的一步。很多人直接把 .jpg 喂给编译器,结果遇到报错:cannot reshape array of size xxx into shape (1,3,640,640)。
⚠️ 避坑指南 2:图片必须转为二进制纯净格式
编译器需要的是解压后、经过通道转换(BGR变RGB)、调整好尺寸(640x640)且排列格式为 NCHW 的纯二进制 .bin 文件。
我们在 Docker 命令行中,新建并运行一个 Python 预处理脚本。
首先创建脚本 convert_img.py(在 Windows 的 D:\rdk_workspace 里直接新建即可):
import cv2
import numpy as np
import os
import glob
src_dir = '/data/calibration_data'
dst_dir = '/data/calib_bin'
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
print("开始转换图片...")
image_files = glob.glob(os.path.join(src_dir, '*.[jp][pn]*'))
for f in image_files:
img = cv2.imread(f)
if img is None: continue
img = cv2.resize(img, (640, 640))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = np.transpose(img, (2, 0, 1)) # HWC 转 NCHW
name = os.path.basename(f).split('.')[0]
bin_path = os.path.join(dst_dir, name + '.bin')
img.astype(np.uint8).tofile(bin_path)
print("转换完成!已存入 /data/calib_bin 文件夹。")
回到 Docker 终端运行它:
python3 /data/convert_img.py
这会在工作目录下生成包含 .bin 图片的 calib_bin 文件夹。
第四步:编写 YAML 配置文件(避坑编码与 Layout)
在地平线工具链中,编译参数全靠一个 YAML 文件控制。在 Windows 工作目录下新建 yolov5.yaml,填入以下内容:
model_parameters:
onnx_model: '/data/best.onnx'
output_model_file_prefix: 'yolov5'
march: 'bayes-e'
input_parameters:
input_name: 'images'
input_type_train: 'rgb'
input_layout_train: 'NCHW'
input_type_rt: 'nv12'
input_layout_rt: 'NHWC'
input_shape: '1x3x640x640'
norm_type: 'data_scale'
scale_value: 0.003921568627451
calibration_parameters:
cal_data_dir: '/data/calib_bin'
calibration_type: 'max'
⚠️ 避坑指南 3:严格的 Layout 与字符编码
- 纯英文无注释:Windows 记事本默认保存中文为 GBK 编码,会导致 Docker 内解析 YAML 报
utf-8 codec can't decode错误。最稳妥的方法是文件内不要有任何中文注释。 - Layout 匹配:为了追求 RDK X5 上的最高帧率,我们将
input_type_rt(运行时输入格式)设为nv12。一旦设为 nv12,底层的input_layout_rt必须严格声明为NHWC,并且补充训练时的格式input_layout_train: 'NCHW',否则会报缺失 Layout 的错误。
第五步:一键编译出炉
万事俱备,在 Docker 终端输入最终的魔法口令(注意,v1.2.8 工具链中编译命令已由 makemodels 升级为 makertbin):
hb_mapper makertbin --model-type onnx --config yolov5.yaml
编译器会经历解析、校准 (Calibration) 和编译三个阶段。当屏幕底部出现绿色的 SUCCESS 时,恭喜你!
在你的 Windows D:\rdk_workspace\model_output 文件夹里,已经静静地躺着生成好的 yolov5.bin 文件了。这就是即将赋予地瓜小车视觉灵魂的大脑!
附录:以后的极简复用流程
这个 Docker 镜像会永久留在你的电脑里。下次更新了模型,只需要三步:
- 把新的
.pt模型通过 Python 脚本导出为best.onnx并放进D:\rdk_workspace。 - 运行
docker run -it --rm -v D:\rdk_workspace:/data openexplorer/ai_toolchain_ubuntu_20_x5_gpu:v1.2.8进入环境。 - 执行
hb_mapper makertbin --model-type onnx --config yolov5.yaml,然后去文件夹里拿新的.bin即可,整个转换过程不到两分钟!

3289

被折叠的 条评论
为什么被折叠?



