HEF Model Compilation
本教程演示如何在 NVIDIA CUDA 环境下,从公开数据集训练 YOLOv8n 检测模型,导出静态 shape 的 ONNX,再经 Hailo Dataflow Compiler (DFC) 量化编译为可部署到 NE503 的 .hef 文件。本教程以安全帽检测(Helmet / No Helmet)为示例,所述方法具有通用性,可适用于任何 Hailo 自训检测模型(车辆、行人、PPE 等)的训练与编译流程。
目标读者:希望在 NE503(Hailo-15H)上部署自训检测模型的 ML 工程师,尤其是具备 YOLO 训练经验、但尚未接触过边缘 NPU 部署的开发者。
1. 概览
本教程覆盖从数据集准备到 HEF 部署的完整流程:
全链路流水线
载体选择:安全帽检测
本教程以安全帽检测(Helmet / No Helmet)为示例,使用 Roboflow Safety Helmet v4 数据集(12000 图)。该任务的类别定义清晰,业务指标直观:一个 2 类模型可同时输出「总人数」与「佩戴安全帽人数」——总人数 = Helmet + No Helmet、合规率 = Helmet / 总人数,无需额外的 person 检测器级联。
本教程的最终产物 safety_helmet_yolov8n_384_640.hef 已在 NE503 真机验证,val mAP50 ≈ 0.93。
2. 环境准备(NVIDIA CUDA)
2.1 硬件需求
| 组件 | 要求 |
|---|---|
| GPU | NVIDIA GPU,独占机 ≥8 GB 显存;共享机 ≥16 GB 显存(参考机型:Tesla T4 16G) |
| CPU | ≥4 核(推荐 8 核) |
| RAM | ≥16 GB(推荐 30 GB) |
| 存储 | ≥50 GB(数据集 + 训练产物 + Hailo SW Suite ~13 GB) |
| 网络 | 稳定的互联网连接(下载数据集与工具链) |
2.2 软件栈
| 项 | 实测版本 |
|---|---|
| 操作系统 | Ubuntu 22.04 |
| CUDA | 12.x |
| Python | 3.10+ |
| PyTorch | 2.x(CUDA 12.x 对应版本) |
| ultralytics | 8.4.75+(旧版的 imgsz 不支持 tuple,见 §4) |
| ONNX 工具 | onnx + onnxslim |
2.3 训练环境一键安装
mkdir -p ~/yolo-train/{weights,datasets,scripts,logs,runs}
python3 -m venv ~/yolo-train/venv
source ~/yolo-train/venv/bin/activate
pip install ultralytics torch torchvision onnx onnxslim
# 验证 CUDA 可用
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"
# 期望输出: CUDA available: True
2.4 Hailo DFC 工具链
Hailo DFC(Dataflow Compiler)只发布 linux/amd64(wheel 限定 linux_x86_64 + 原生 .so),通过 Docker 容器运行,原生 x86 无翻译开销。
- 到 Hailo Developer Zone 注册免费账号
- 下载
hailo_ai_sw_suite压缩包(约 13 GB,版本需与设备 NPU 固件对齐,本教程实测 v5.3.0) - 导入镜像后,后续编译步骤在容器内执行(见 §6)
注意:DFC 工具链仅在 Linux x86_64 上运行。本教程全程基于 NVIDIA CUDA 服务器(如 Tesla T4),不涉及 Mac 编译环境。
3. 数据集准备
3.1 下载 Roboflow Safety Helmet v4
数据集来源:Roboflow Universe 的 Safety Helmet.v4-data160.yolov8,YOLOv8 pyTorch 格式。到 Roboflow Universe 搜索 "Safety Helmet" 下载,或用 API key 拉取:
pip install roboflow
from roboflow import Roboflow
rf = Roboflow(api_key="<你的 API key>") # 在 Roboflow 账号设置里生成
rf.workspace("<workspace>").project("safety-helmet").version(4).download("yolov8")
手动下载 zip 后解压:
cd ~/yolo-train/datasets
unzip "Safety Helmet.v4-data160.yolov8.zip" -d safety-helmet
cd safety-helmet
ls -d train valid test # 三个 split 都在
确保数据集目录对 DFC 容器可读(Roboflow 下载默认为 700 权限):
chmod -R a+rX ~/yolo-train/datasets/safety-helmet
3.2 数据集分割
| Split | 图片数 | 含 background 图 | 备注 |
|---|---|---|---|
| train | 10500 | 15 | 含少量无标注背景图 |
| valid | 1000 | 1 | 用于训练期验证 |
| test | 500 | 2 | 最终评估 |
| 合计 | 12000 | 18 |
3.3 data.yaml 配置
path: ~/yolo-train/datasets/safety-helmet
train: train/images
val: valid/images
test: test/images
nc: 2
names: ["Helmet", "No Helmet"]
类别定义:
Helmet(class 0):佩戴安全帽的人头框No Helmet(class 1):未佩戴安全帽的人头框
业务映射:Helmet 框数 = 佩戴安全帽的人数、No Helmet 框数 = 未佩戴安全帽的人数、总人数 = Helmet + No Helmet、合规率 = Helmet / 总人数。
4. 模型训练
4.1 关键超参:为何固定为 640×384
NE503 的 sub 流(用于 AI 推理的低分辨率流)固定尺寸为 640W×384H,像素格式 NV12。模型输入需与此尺寸匹配,NCHW [1, 3, 384, 640](H 在前,W 在后)。
ultralytics 8.4.75 存在一个限制:train 的 imgsz 仅接受 int(8.4.96+ 版本才支持 tuple)。解决方法为使用 imgsz=640 + rect=True(矩形训练),实际生成 384×640 的训练输入:
TRAIN_IMGSZ = 640 # int(8.4.75 不支持 tuple)
RECT = True # 矩形训练,保持 384 高度
EXPORT_IMGSZ = (384, 640) # 导出时固定为静态 shape
rect=True让 dataloader 按 batch 内图像的长宽比,生成最接近 imgsz 的矩形(不强行 resize 到正方形)。安全帽图多为横向(宽>高),实际生成 384(H)×640(W)。日志里 "Image sizes 640 train" 只是回显参数值,不代表 tensor shape 是 640×640。若 ultralytics ≥8.4.96,可直接imgsz=(384,640)省掉 rect;本教程为兼容旧版用 rect 方案。
4.2 训练脚本(关键片段)
import torch
from ultralytics import YOLO
WEIGHTS_DIR = "~/yolo-train/weights"
DATA_YAML = "~/yolo-train/datasets/safety-helmet/data.yaml"
PROJECT = "~/yolo-train/runs/helmet"
NAME = "yolov8n_640_rect"
TRAIN_IMGSZ = 640
RECT = True
EXPORT_IMGSZ = (384, 640)
EPOCHS = 100
BATCH = 8 # 可根据 GPU 显存调整(独占机可开 16/32)
PATIENCE = 20
WORKERS = 4
# 1) 训练
model = YOLO(f"{WEIGHTS_DIR}/yolov8n.pt") # 预训练 backbone
model.train(
data=DATA_YAML,
imgsz=TRAIN_IMGSZ,
rect=RECT,
epochs=EPOCHS,
batch=BATCH,
patience=PATIENCE,
workers=WORKERS,
project=PROJECT,
name=NAME,
exist_ok=True,
)
# 2) 导出静态 ONNX(见 §5)
best_pt = f"{PROJECT}/{NAME}/weights/best.pt"
em = YOLO(best_pt)
em.export(
format="onnx",
imgsz=list(EXPORT_IMGSZ),
opset=11,
simplify=True,
dynamic=False,
)
类数由
data.yaml的nc决定,脚本本身不固定类数——2 类或 4 类均可使用同一脚本。
4.3 启动训练(tmux 后台)
ssh <gpu-server> 'tmux new-session -d -s helmet-train \
"source ~/yolo-train/venv/bin/activate && \
cd ~/yolo-train && python scripts/train_helmet.py 2>&1 | tee logs/helmet-train.log"'
# 实时跟随日志
ssh <gpu-server> 'tail -f ~/yolo-train/logs/helmet-train.log'
# 监控显存(确认没影响其他进程)
ssh <gpu-server> 'nvidia-smi --query-gpu=memory.used,memory.total,utilization.gpu --format=csv'