地平线 RDK X5 部署 YOLOv5 保姆级教程:从 .pt 到 .bin 的完整避坑指南

CLIP-GmP-ViT-L-14编码模型

CLIP-GmP-ViT-L-14编码模型

图像识别
CLIP

CLIP-GmP-ViT-L-14编码模型` 是一个图文双塔编码模型,适合做图文匹配、零样本分类和跨模态检索演示。本镜像已经完成 Web 部署,打开页面即可上传图片并测试图文表征能力

如果你正在准备地瓜智能车比赛,或者手头有一块拥有 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 环境(已安装 ultralyticsonnx
  • 目标硬件:地平线 RDK X5 (系统 Ubuntu 22.04)
  • 待转换模型:训练好的 YOLOv5 模型 best.pt

第一步:导出 ONNX 模型(避坑 Opset 限制)

天工开物编译器并不直接认识 .pt 文件,我们需要先将其转为 .onnx 中间格式。为了完美控制导出参数和路径,我们不使用终端命令,而是编写一个 Python 导出脚本

新建一个 Python 文件(例如 export_onnx.py),填入以下代码,并根据你的实际情况修改 PT_MODEL_PATHONNX_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 镜像会永久留在你的电脑里。下次更新了模型,只需要三步:

  1. 把新的 .pt 模型通过 Python 脚本导出为 best.onnx 并放进 D:\rdk_workspace
  2. 运行 docker run -it --rm -v D:\rdk_workspace:/data openexplorer/ai_toolchain_ubuntu_20_x5_gpu:v1.2.8 进入环境。
  3. 执行 hb_mapper makertbin --model-type onnx --config yolov5.yaml,然后去文件夹里拿新的 .bin 即可,整个转换过程不到两分钟!

您可能感兴趣的与本文相关的镜像

CLIP-GmP-ViT-L-14编码模型

CLIP-GmP-ViT-L-14编码模型

图像识别
CLIP

CLIP-GmP-ViT-L-14编码模型` 是一个图文双塔编码模型,适合做图文匹配、零样本分类和跨模态检索演示。本镜像已经完成 Web 部署,打开页面即可上传图片并测试图文表征能力

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值