Link to this sectionExportation Hailo pour les modèles YOLO d'Ultralytics#
Le format Hailo HEF n'est pas actuellement pris en charge en tant que cible directe model.export(format="hailo") dans Ultralytics. Le flux de travail ci-dessous est une solution de secours manuelle qui exporte d'abord en ONNX, puis utilise la chaîne d'outils Dataflow Compiler externe de Hailo pour produire un fichier .hef. Un flux de travail Ultralytics fluide devrait exposer Hailo via la même API d'exportation Python et CLI que les autres formats matériels.
La chaîne d'outils Hailo utilise des fichiers HEF pour les plateformes embarquées, y compris le Raspberry Pi AI Kit et le AI HAT+, les caméras industrielles, les passerelles de périphérie et les PC IA.
Ce guide explique comment exporter certains modèles Ultralytics YOLO vers le format HEF (Hailo Executable Format) de Hailo en utilisant le SDK Hailo Dataflow Compiler (DFC). Le flux de travail part d'un modèle YOLO .pt, l'exporte vers ONNX, le compile avec les outils Hailo et produit un fichier .hef prêt pour les accélérateurs Hailo pris en charge.
Link to this sectionQuand utiliser Hailo HEF#
HEF est l'artefact compilé consommé par HailoRT sur les périphériques cibles Hailo. Utilise ce guide manuel uniquement lorsque ton matériel de déploiement nécessite spécifiquement Hailo HEF avant que la prise en charge directe de l'exportation Hailo par Ultralytics ne soit disponible.
Le rôle du HEF dans le déploiement est similaire à celui de formats spécifiques au matériel tels que RKNN pour les NPU Rockchip, IMX500 pour les caméras IA Raspberry Pi, et Qualcomm QNN pour les NPU Snapdragon, mais il n'est actuellement pas généré directement par Ultralytics.
Ce flux de travail est pertinent quand tu as besoin de :
- Compatibilité avec Raspberry Pi AI Kit : Hailo-8L est utilisé dans le Raspberry Pi AI Kit et le AI HAT+ officiels.
- Post-traitement HailoRT : HailoRT peut inclure la non-maximum suppression YOLO dans le pipeline d'inférence compilé.
- Compilation INT8 : Le Hailo DFC quantifie le modèle avec des images de calibration représentatives pour produire un graphe INT8 pour le matériel Hailo. Apprends-en plus sur la quantification de modèle.
Link to this sectionFormat d'exportation Hailo HEF#
Le HEF est un exécutable spécifique au matériel généré par le Hailo Dataflow Compiler. Il contient le graphe du modèle quantifié, l'allocation mémoire, l'ordonnancement et un post-traitement optionnel configuré pour une architecture Hailo cible. Contrairement aux formats standard du mode Export de YOLO qui sont produits directement par model.export(format=...), la compilation HEF utilise actuellement un flux en deux étapes :
- Exporter YOLO vers ONNX avec Ultralytics.
- Utiliser les outils Hailo DFC pour analyser, optimiser, quantifier et compiler le modèle ONNX en HEF.
Le flux de travail complet se décompose dans le pipeline suivant :
YOLO (.pt) -> ONNX -> HAR (parse) -> HAR (optimize/quantize) -> HEF (compile)- Exporter vers ONNX en utilisant le mode Export d'Ultralytics
- Analyser le modèle ONNX dans le format intermédiaire HAR de Hailo
- Charger un script de modèle (
.alls) avec des directives de normalisation et de post-traitement - Calibrer et quantifier en utilisant des images représentatives
- Compiler vers un fichier HEF déployable
Link to this sectionTâches prises en charge#
L'exemple manuel actuel se concentre sur la détection d'objets YOLO11, car le script du modèle Hailo et la configuration de post-traitement sont spécifiques à la tête de détection. Une future implémentation directe model.export(format="hailo") devrait rendre l'exportation Hailo aussi simple que n'importe quel autre format d'exportation Ultralytics, avec une prise en charge des tâches limitée par la tête du modèle et la compatibilité du compilateur Hailo plutôt que par des étapes de flux de travail externes.
| Tâche | Cible d'exportation directe Hailo | Notes |
|---|---|---|
| Détection d'objets | ✅ Cible principale | La détection YOLOv8, YOLO11 et YOLO26 devrait être le premier chemin d'exportation directe. |
| Segmentation d'instance | ✅ Cible | La segmentation YOLOv8, YOLO11 et YOLO26 nécessite une gestion et une validation spécifiques de la sortie des masques par tâche. |
| Segmentation sémantique | ⚠️ À valider | La segmentation sémantique YOLO26 nécessite un compilateur dédié et un chemin de validation de sortie. |
| Estimation de pose | ⚠️ À valider | La pose nécessite une gestion de la sortie des points clés au-delà du chemin NMS de détection. |
| Détection OBB | ⚠️ À valider | L'OBB nécessite une gestion de la sortie des boîtes pivotées au-delà du chemin NMS de détection standard. |
| Classification | ⚠️ À valider | La classification a une tête de sortie plus simple, mais nécessite toujours une validation de compilation et d'exécution Hailo. |
Tant que l'exportation directe Hailo n'est pas implémentée dans Ultralytics, seul le flux de travail manuel ONNX-vers-HEF ci-dessous est documenté.
Link to this sectionVersions du SDK Hailo#
L'exportation directe Hailo doit tenir compte de la séparation entre le matériel et la génération du SDK de Hailo :
- Hailo-8 et Hailo-8L : utilise Hailo Dataflow Compiler v3.x. C'est le chemin pertinent pour les déploiements Raspberry Pi AI Kit et 13 TOPS AI HAT+.
- Hailo-10 et Hailo-15 : utilise Hailo Dataflow Compiler v5.x.
Cette séparation de version affecte les API du compilateur, les architectures prises en charge, la compatibilité HEF générée et les valeurs hw_arch qu'un exportateur direct doit exposer. La prise en charge d'une tâche sur une génération de matériel Hailo ne doit pas être considérée comme prise en charge sur une autre sans valider la version DFC cible et hw_arch.
Link to this sectionNotes de compatibilité#
La compatibilité de l'exportation Hailo dépend de la tête du modèle, de la taille de l'image d'entrée, du nombre de classes, de l'architecture Hailo, du script de modèle généré (.alls) et de la configuration de post-traitement. Les configurations statiques ne sont pas des modèles universels. Par exemple, un JSON NMS créé pour un modèle YOLO11n à 80 classes COCO n'est pas correct pour un modèle personnalisé à 3 classes ou pour une imgsz fixe différente.
| Portée | Support attendu | Notes |
|---|---|---|
| Détection YOLOv8 / YOLO11 | ✅ Bon | Tête de détection découplée partagée ; les directives .alls, les nœuds de fin et la configuration NMS doivent toujours correspondre au graphe exporté et à la imgsz fixe. |
| Détection personnalisée YOLOv8 / YOLO11 | ✅ Possible | Nécessite une configuration NMS par modèle générée à partir du nombre de classes, des strides et de la disposition de la tête de détection ; le JSON statique ne correspondra pas. |
| Détection YOLO26 | ✅ Cible | L'architecture sans NMS nécessite un chemin de compilateur/post-traitement séparé ; ne réutilise pas le flux de travail NMS YOLO11/YOLOv8 ci-dessous pour YOLO26. |
| Segmentation d'instance YOLO26 | ✅ Cible | Nécessite une gestion de la sortie des masques et une validation de la précision spécifiques à la segmentation YOLO26. |
| YOLO26 sémantique, pose, OBB, classification | ⚠️ Recherche | Ces tâches nécessitent une compilation dédiée et une validation de l'exécution avant de pouvoir être annoncées comme directement prises en charge. |
| Tailles d'image dynamiques ou arbitraires | ❌ Non supporté | La compilation Hailo utilise une forme d'entrée fixe ; les paramètres .alls et de post-traitement doivent correspondre à la imgsz exportée. |
Link to this sectionInstallation#
Link to this sectionÉtape 1 : Installer Ultralytics#
pip install ultralyticsLink to this sectionÉtape 2 : Installer le SDK Hailo DFC#
Le Hailo DFC est requis pour l'analyse, l'optimisation et la compilation. Télécharge le fichier Python wheel depuis la Hailo Developer Zone (inscription gratuite requise) et installe-le :
pip install /path/to/hailo_dataflow_compiler-*.whlLe SDK Hailo DFC nécessite une machine Linux x86_64. L'exportation et la compilation ne peuvent pas être effectuées sur des appareils ARM tels que Raspberry Pi. Copie le fichier .hef résultant sur ton appareil alimenté par Hailo pour le déploiement avec HailoRT.
Link to this sectionExemple d'exportation HEF pour YOLO11n#
Le script ci-dessous compile un modèle de détection YOLO11n de .pt à .hef avec une taille d'entrée fixe de 640 pixels. Il exporte vers ONNX en utilisant Ultralytics, puis compile avec Hailo DFC en utilisant COCO128 comme petit jeu de données de calibration.
Avant d'exécuter le script, fournis un JSON NMS Hailo qui correspond exactement au graphe d'exportation YOLO11n, au nombre de classes, aux strides et à la taille d'entrée fixe. Réutilise ce script comme point de départ connu pour YOLO11n ; les modèles personnalisés nécessitent des nœuds de fin, des directives .alls et des paramètres NMS correspondants.
Les modèles YOLO26 sont sans NMS. Un exportateur direct Ultralytics Hailo nécessite un chemin de compilation et de post-traitement dédié à YOLO26 pour la détection ou la segmentation d'instance au lieu de l'exemple NMS YOLO11 ci-dessous.
import ast
import random
from pathlib import Path
import numpy as np
import onnx
from hailo_sdk_client import ClientRunner
from PIL import Image
from ultralytics import YOLO
from ultralytics.data.utils import check_det_dataset
from ultralytics.utils import DATASETS_DIR, YAML
# Configuration
MODEL = "yolo11n"
HW_ARCH = "hailo8" # hailo8 | hailo8l | hailo15h
IMGSZ = 640
CALIB_IMAGES = 128
NMS_CONFIG = "yolo11n_nms_config.json" # Download or generate for your exact model.
OUT_DIR = Path(f"{MODEL}_hailo_model") # deploy folder (mirrors Ultralytics <model>_<format>_model exports)
OUT_DIR.mkdir(exist_ok=True)
# YOLO11 detection head end nodes. See "Supported Models and End Nodes" for YOLOv8 and other families.
END_NODES = [
"/model.23/cv2.0/cv2.0.2/Conv",
"/model.23/cv3.0/cv3.0.2/Conv",
"/model.23/cv2.1/cv2.1.2/Conv",
"/model.23/cv3.1/cv3.1.2/Conv",
"/model.23/cv2.2/cv2.2.2/Conv",
"/model.23/cv3.2/cv3.2.2/Conv",
]
# Step 1: Export to ONNX, then move it into the deploy folder to keep the working directory tidy
model = YOLO(f"{MODEL}.pt")
onnx_path = Path(model.export(format="onnx", imgsz=IMGSZ, opset=11))
onnx_path = onnx_path.rename(OUT_DIR / onnx_path.name)
# Copy the metadata Ultralytics embedded in the ONNX into the standard metadata.yaml sidecar.
# The HEF stores no class names, so inference reads them from this file.
meta = {p.key: p.value for p in onnx.load(onnx_path, load_external_data=False).metadata_props}
for k in ("stride", "batch", "channels"):
if k in meta:
meta[k] = int(meta[k])
for k in ("imgsz", "names", "args", "end2end"):
if k in meta:
meta[k] = ast.literal_eval(meta[k])
YAML.save(OUT_DIR / "metadata.yaml", meta)
# Step 2: Parse ONNX with Hailo DFC
# The DFC prints the detected end nodes after parsing; use them if unsure.
runner = ClientRunner(hw_arch=HW_ARCH)
runner.translate_onnx_model(str(onnx_path), end_node_names=END_NODES)
# Step 3: Load model script (normalization + HailoRT NMS)
# The conv layer names are generated by DFC and can change for other model sizes/families.
model_script = (
"normalization1 = normalization([0.0, 0.0, 0.0], [255.0, 255.0, 255.0])\n"
"change_output_activation(conv54, sigmoid)\n"
"change_output_activation(conv65, sigmoid)\n"
"change_output_activation(conv80, sigmoid)\n"
f'nms_postprocess("{NMS_CONFIG}", meta_arch=yolov8, engine=cpu)\n'
"allocator_param(width_splitter_defuse=disabled)"
)
runner.load_model_script(model_script)
# Step 4: Build calibration dataset (auto-downloads COCO128)
check_det_dataset("coco128.yaml")
calib_dir = DATASETS_DIR / "coco128" / "images" / "train2017"
image_files = list(calib_dir.glob("*.jpg")) + list(calib_dir.glob("*.png"))
if not image_files:
raise FileNotFoundError(f"No calibration images found in {calib_dir}")
calibset = np.zeros((CALIB_IMAGES, IMGSZ, IMGSZ, 3), dtype=np.float32)
for i in range(CALIB_IMAGES):
img = Image.open(random.choice(image_files)).convert("RGB").resize((IMGSZ, IMGSZ))
calibset[i] = np.array(img, dtype=np.float32)
# Step 5: Optimize and quantize
runner.optimize(calibset)
runner.save_har(str(OUT_DIR / f"{MODEL}.o.har")) # optional intermediate HAR
# Step 6: Compile to HEF
hef = runner.compile()
hef_path = OUT_DIR / f"{MODEL}.hef"
with open(hef_path, "wb") as f:
f.write(hef)
# Note: the Hailo SDK writes *.log files (acceleras.log, allocator.log, hailo_sdk.client.log,
# hailo_sdk.core.log) to the working directory. They are diagnostic scratch, safe to ignore or delete.
print(f"Compiled HEF saved to: {hef_path}")Le script d'exportation organise les artefacts et les journaux comme suit :
- Dossier de déploiement : Les artefacts sont enregistrés dans
yolo11n_hailo_model/, reproduisant la structure standard<model>_<format>_model/utilisée par d'autres exportations d'Ultralytics. - Fichiers requis : Les deux fichiers nécessaires au déploiement sont le fichier compilé
yolo11n.hefet son fichier auxiliairemetadata.yaml. - Métadonnées : Le fichier
metadata.yamlcontient des champs essentiels (names,imgsz,task,stride, etc.) extraits des métadonnées ONNX. Les scripts d'inférence chargent les noms des classes à partir de ce fichier, car le format HEF ne les stocke pas. - Fichiers intermédiaires : Le dossier d'exportation contient également les points de contrôle intermédiaires
yolo11n.onnxetyolo11n.o.har. - Fichiers journaux : Le SDK Hailo génère plusieurs journaux de diagnostic (par exemple,
acceleras.log,allocator.log,hailo_sdk.client.logethailo_sdk.core.log) dans le répertoire de travail ; ceux-ci peuvent être ignorés ou supprimés sans risque. - Raspberry Pi AI Kit : Pour ce matériel spécifique, assure-toi de définir
HW_ARCH = "hailo8l"avant d'exécuter l'étape de compilation.
Link to this sectionDécomposition étape par étape#
Le script complet ci-dessus s'exécute de bout en bout. Cette section explique ce que fait chaque étape et les détails spécifiques au modèle à surveiller lors de son adaptation à ton propre modèle.
Link to this sectionÉtape 1 : Exporter vers ONNX et enregistrer les métadonnées#
Ultralytics exporte ton modèle entraîné au format ONNX, que le DFC de Hailo ingère en entrée. opset=11 offre une large compatibilité avec le DFC, et le fichier ONNX est déplacé dans un dossier de déploiement yolo11n_hailo_model/ (reproduisant la structure <model>_<format>_model/ des autres exportations d'Ultralytics) pour garder le répertoire de travail propre.
Le HEF ne stocke aucun nom de classe, donc les métadonnées qu'Ultralytics intègre dans l'ONNX sont copiées dans un fichier auxiliaire standard metadata.yaml à côté de lui. Il s'agit du même metadata.yaml que celui produit par d'autres formats d'exportation (names, imgsz, task, stride, et plus), et l'inférence lit les noms de classes à partir de celui-ci, de sorte que le flux de travail fonctionne pour des modèles personnalisés sans avoir à coder les étiquettes en dur.
Link to this sectionÉtape 2 : Analyser le modèle ONNX#
runner.translate_onnx_model(...) convertit le graphe ONNX en représentation HAR intermédiaire de Hailo. La liste end_node_names indique au DFC où couper le graphe avant la NMS pour que Hailo puisse attacher son propre post-traitement matériel.
Le DFC imprime une suggestion après l'analyse :
[info] In order to use HailoRT post-processing capabilities, these end node names should be used: ...
Copie ces noms de nœuds si tu n'es pas sûr de ceux à utiliser, ou si tu travailles avec une architecture personnalisée ou moins courante.
Link to this sectionÉtape 3 : Charger le script de modèle#
Le script de modèle (.alls) configure la normalisation d'entrée, l'activation de sortie et le post-traitement NMS. Le paramètre meta_arch=yolov8 s'applique à la fois à YOLOv8 et à YOLO11 car ils partagent la même disposition de tête de détection.
MODEL = "yolo11n"
NMS_CONFIG = "yolo11n_nms_config.json"
model_script = (
"normalization1 = normalization([0.0, 0.0, 0.0], [255.0, 255.0, 255.0])\n"
"change_output_activation(conv54, sigmoid)\n"
"change_output_activation(conv65, sigmoid)\n"
"change_output_activation(conv80, sigmoid)\n"
f'nms_postprocess("{NMS_CONFIG}", meta_arch=yolov8, engine=cpu)\n'
"allocator_param(width_splitter_defuse=disabled)"
)
runner.load_model_script(model_script)Les noms de couche change_output_activation (conv54, conv65, conv80) sont attribués par le DFC lors de l'analyse et sont spécifiques au modèle. Si tu compiles une taille ou une architecture de modèle différente, vérifie les noms corrects dans la sortie du DFC ou génère les directives .alls à partir du graphe exporté.
Le fichier NMS_CONFIG est également spécifique au modèle. Utilise une configuration qui correspond exactement à ton modèle exporté.
engine=cpu exécute le NMS via HailoRT sur le CPU hôte. N'utilise engine=nn_core que pour les combinaisons modèle/script que Hailo documente comme étant prises en charge par le matériel cible et la version du SDK.
Supprime la ligne nms_postprocess si tu préfères exécuter le NMS entièrement dans ton code d'application. Si tu fais cela, mets à jour l'analyseur d'inférence car le HEF sortira des tenseurs de tête de détection bruts au lieu de détections NMS groupées.
Link to this sectionÉtape 4 : Construire le jeu de données de calibration#
La quantification INT8 nécessite un ensemble représentatif d'images empilées dans un tableau float32 de type (N, imgsz, imgsz, 3). Le script utilise COCO128, qu'Ultralytics télécharge automatiquement via check_det_dataset.
Utilise au moins 64 images pour la calibration. Plus d'images améliorent généralement la qualité de la quantification. Pour de meilleurs résultats, utilise des images de ton domaine de déploiement plutôt que COCO128.
Link to this sectionÉtape 5 : Optimiser et quantifier#
runner.optimize(calibset) applique un réglage fin tenant compte de la quantification et une analyse du bruit des couches, puis runner.save_har(...) écrit un point de contrôle intermédiaire facultatif. Un GPU est fortement recommandé ; sans cela, cette étape peut prendre plusieurs heures.
Link to this sectionÉtape 6 : Compiler en HEF#
runner.compile() produit le fichier HEF final, écrit dans yolo11n_hailo_model/yolo11n.hef. Il se trouve maintenant aux côtés de son metadata.yaml, prêt à être copié sur l'appareil pour l'inférence.
Link to this sectionModèles pris en charge et nœuds finaux#
Pour les modèles de détection, end_node_names identifie les sorties de la tête de détection ONNX que Hailo doit compiler avant d'attacher son post-traitement NMS. Ces noms varient selon l'architecture et peuvent changer lorsque le graphe exporté change.
Les exemples de nœuds de fin ci-dessous s'appliquent aux modèles de détection YOLOv8 et YOLO11 qui utilisent le post-traitement NMS de style YOLOv8 de Hailo. YOLO26 est sans NMS et n'utilise pas cette configuration NMS YOLO11.
Link to this sectionYOLO11 et YOLOv8#
YOLO11 et YOLOv8 partagent la même tête de détection découplée. L'index de couche diffère d'un entre les deux familles :
| Famille de modèles | Couche de tête de détection | Modèle de nœud final |
|---|---|---|
| YOLO11 (tous) | model.23 | /model.23/cv2.0/cv2.0.2/Conv (6 nœuds) |
| YOLOv8 (tous) | model.22 | /model.22/cv2.0/cv2.0.2/Conv (6 nœuds) |
Nœuds finaux YOLO11 (toutes tailles : n, s, m, l, x) :
END_NODES = [
"/model.23/cv2.0/cv2.0.2/Conv",
"/model.23/cv3.0/cv3.0.2/Conv",
"/model.23/cv2.1/cv2.1.2/Conv",
"/model.23/cv3.1/cv3.1.2/Conv",
"/model.23/cv2.2/cv2.2.2/Conv",
"/model.23/cv3.2/cv3.2.2/Conv",
]Nœuds finaux YOLOv8 (toutes tailles : n, s, m, l, x) :
END_NODES = [
"/model.22/cv2.0/cv2.0.2/Conv",
"/model.22/cv3.0/cv3.0.2/Conv",
"/model.22/cv2.1/cv2.1.2/Conv",
"/model.22/cv3.1/cv3.1.2/Conv",
"/model.22/cv2.2/cv2.2.2/Conv",
"/model.22/cv3.2/cv3.2.2/Conv",
]Link to this sectionAutres architectures#
Pour d'autres architectures de détection, exécute l'étape d'analyse sans end_node_names en premier, lis les nœuds suggérés depuis la sortie du journal DFC, puis relance avec ces nœuds :
# First pass: let the DFC suggest end nodes
runner = ClientRunner(hw_arch=HW_ARCH)
runner.translate_onnx_model(f"{MODEL}.onnx")
# Check the printed log for: "[info] In order to use HailoRT post-processing..."Pour une prise en charge directe d'Ultralytics, ces directives .alls et ces paramètres de post-traitement devraient être générés ou sélectionnés par l'exportateur plutôt que d'obliger les utilisateurs à les assembler manuellement.
Link to this sectionArchitectures matérielles prises en charge#
| Architecture | Appareil | Calcul de crête (Spécification fournisseur) | Cas d'utilisation courant |
|---|---|---|---|
hailo8 | Hailo-8 | 26 TOPS | Carte accélératrice Hailo |
hailo8l | Hailo-8L | 13 TOPS | Kit IA Raspberry Pi |
hailo15h | Hailo-15H | 20 TOPS | Appareils cibles Hailo-15 |
Définis HW_ARCH dans le script pour correspondre à ton appareil cible avant la compilation.
Link to this sectionExécution de l'inférence sur le matériel Hailo#
Une fois la compilation terminée, copie tout le dossier yolo11n_hailo_model/ (le .hef et son metadata.yaml) sur ton appareil équipé de Hailo et exécute l'inférence en utilisant soit l'API Python HailoRT (package hailo_platform), soit, sur Raspberry Pi, l'assistant picamera2 Hailo (un wrapper de HailoRT). Les deux sont présentés dans les onglets ci-dessous. Garder les deux fichiers ensemble permet aux scripts ci-dessous de lire les noms de classes à partir du metadata.yaml situé à côté du HEF. Contrairement aux étapes d'exportation du DFC, l'inférence s'exécute directement sur l'appareil en périphérie.
Le code d'inférence ci-dessous s'exécute sur l'appareil équipé de Hailo (par exemple, Raspberry Pi + Kit IA), et non sur la machine x86 utilisée pour la compilation.
Link to this sectionÉtape 1 : Installer HailoRT sur l'appareil#
Sur l'appareil cible, installe HailoRT et les liaisons Python. Pour les utilisateurs du Kit IA et de l'AI HAT+ de Raspberry Pi, le guide officiel du logiciel IA de Raspberry Pi installe HailoRT, le pilote de l'appareil et les liaisons Python avec :
sudo apt install dkms
sudo apt install hailo-all
sudo rebootPour les appareils Hailo autres que Raspberry Pi, installe le package HailoRT qui correspond à ton appareil, ton pilote et ta version de SDK depuis la zone des développeurs Hailo.
Les appareils AI HAT+ 2 utilisent un package Raspberry Pi différent (hailo-h10-all) et un flux de travail Hailo-10H. Suis le guide logiciel IA de Raspberry Pi pour cette génération de matériel.
Link to this sectionÉtape 2 : Vérification rapide#
Avant d'exécuter l'inférence Python, confirme que l'appareil Hailo est reconnu :
hailortcli fw-control identifyTu devrais voir le type d'appareil, la version du firmware et le numéro de série affichés.
Executing on device: 0001:01:00.0
Identifying board
Control Protocol Version: 2
Firmware Version: 4.23.0 (release,app,extended context switch buffer)
Logger Version: 0
Board Name: Hailo-8
Device Architecture: HAILO8Link to this sectionÉtape 3 : Exécuter l'inférence#
The scripts below run object detection with the compiled HEF file. Both tabs accept the same --source inputs (an image, a video, a USB webcam index, or csi for the Raspberry Pi Camera Module) and differ only in the inference API: the Hailo SDK tab uses the low-level hailo_platform API (portable, minimal dependencies), while the picamera2 tab uses the Raspberry Pi picamera2 Hailo helper. Images and videos are written to an annotated file; webcam and CSI streams display in a live window.
Le chemin HailoRT natif du fournisseur fonctionne sur n'importe quelle plateforme équipée d'un périphérique Hailo et ne nécessite aucune dépendance supplémentaire. Passe à --source un chemin d'image, un chemin de vidéo, un index de webcam (par ex. 0) pour une capture USB/V4L2 en direct, ou csi pour le module caméra Raspberry Pi. L'option CSI nécessite l'installation de picamera2, car l'OS moderne de Raspberry Pi achemine la caméra via libcamera plutôt que via un périphérique V4L2 standard.
import argparse
from pathlib import Path
import cv2
import numpy as np
import yaml
from hailo_platform import (
HEF,
ConfigureParams,
FormatType,
HailoStreamInterface,
InferVStreams,
InputVStreamParams,
OutputVStreamParams,
VDevice,
)
from tqdm import tqdm
IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".bmp", ".webp", ".tif", ".tiff"}
def parse_and_draw(per_class, frame, conf, names):
"""Draw HailoRT NMS detections (grouped by class, normalized [0, 1] coords) onto a BGR frame."""
h, w = frame.shape[:2]
for cls_idx, cls_dets in enumerate(per_class):
for det in cls_dets:
score = float(det[4])
if score < conf:
continue
# HailoRT NMS returns normalized [0, 1] coords as (y1, x1, y2, x2)
y1, x1, y2, x2 = det[:4]
x1, y1, x2, y2 = int(x1 * w), int(y1 * h), int(x2 * w), int(y2 * h)
label = f"{names[cls_idx]} {score:.2f}"
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.putText(frame, label, (x1 + 2, y1 + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, cv2.LINE_AA)
def preprocess(frame, imgsz):
"""BGR frame -> (1, imgsz, imgsz, 3) float32 in 0-255 (HEF normalizes internally)."""
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
resized = cv2.resize(rgb, (imgsz, imgsz))
return np.expand_dims(resized.astype(np.float32), axis=0)
def csi_frames(width=1280, height=720):
"""Yield BGR frames from the Pi CSI Camera Module via picamera2."""
from picamera2 import Picamera2
picam2 = Picamera2()
# picamera2 "RGB888" is BGR-ordered in memory, so it drops straight into OpenCV
picam2.configure(picam2.create_preview_configuration(main={"size": (width, height), "format": "RGB888"}))
picam2.start()
try:
while True:
yield picam2.capture_array("main") # BGR
finally:
picam2.stop()
picam2.close()
def cv2_frames(src):
"""Yield BGR frames from a video file or USB/V4L2 webcam via OpenCV."""
cap = cv2.VideoCapture(src)
if not cap.isOpened():
raise RuntimeError(f"Could not open source {src}")
total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 0 for live webcams
pbar = tqdm(total=total, desc="Processing video", unit="frame") if total > 0 else None
try:
while True:
ok, frame = cap.read() # BGR
if not ok:
break
yield frame
if pbar is not None:
pbar.update(1)
finally:
if pbar is not None:
pbar.close()
cap.release()
def open_source(source):
"""Yield (frame, kind) pairs where kind is 'image', 'video', or 'stream'."""
if source == "csi":
yield from ((f, "stream") for f in csi_frames())
elif source.isdigit():
yield from ((f, "stream") for f in cv2_frames(int(source)))
elif Path(source).suffix.lower() in IMAGE_EXTS:
frame = cv2.imread(source)
if frame is None:
raise FileNotFoundError(f"Could not read image {source}")
yield frame, "image"
else:
yield from ((f, "video") for f in cv2_frames(source))
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Hailo YOLO inference (image, video, webcam, or CSI camera)")
parser.add_argument("-m", "--model", default="yolo11n_hailo_model/yolo11n.hef", help="Path to the HEF model.")
parser.add_argument("--source", default="0", help="Image/video path, webcam index (e.g. 0), or 'csi'.")
parser.add_argument("--imgsz", type=int, default=640)
parser.add_argument("--conf", type=float, default=0.25)
args = parser.parse_args()
# Load class names from metadata.yaml saved next to the HEF during compilation (keyed by class index)
with open(Path(args.model).parent / "metadata.yaml") as f:
names = yaml.safe_load(f)["names"]
# Configure the device and network group ONCE
hef = HEF(args.model)
target = VDevice(VDevice.create_params())
configure_params = ConfigureParams.create_from_hef(hef, interface=HailoStreamInterface.PCIe)
network_group = target.configure(hef, configure_params)[0]
network_group_params = network_group.create_params()
input_vstreams_params = InputVStreamParams.make(network_group, quantized=False, format_type=FormatType.FLOAT32)
output_vstreams_params = OutputVStreamParams.make(network_group, quantized=False, format_type=FormatType.FLOAT32)
input_name = hef.get_input_vstream_infos()[0].name
writer = None # lazily created for video output
# Keep the pipeline and activation OPEN across frames (re-opening per frame is slow)
with InferVStreams(network_group, input_vstreams_params, output_vstreams_params) as pipeline:
with network_group.activate(network_group_params):
try:
for frame, kind in open_source(args.source):
raw = pipeline.infer({input_name: preprocess(frame, args.imgsz)})
parse_and_draw(raw[next(iter(raw.keys()))][0], frame, args.conf, names)
if kind == "image":
cv2.imwrite("output.jpg", frame)
print("Saved output.jpg")
elif kind == "video":
if writer is None:
h, w = frame.shape[:2]
writer = cv2.VideoWriter("output.mp4", cv2.VideoWriter_fourcc(*"mp4v"), 30, (w, h))
writer.write(frame)
else: # live stream
cv2.imshow("Hailo YOLO", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
finally:
if writer is not None:
writer.release()
print("Saved output.mp4")
cv2.destroyAllWindows()Exécute-le avec n'importe quelle source (les images enregistrent output.jpg, les vidéos enregistrent output.mp4, les flux en direct s'affichent dans une fenêtre, appuie sur q pour quitter) :
python hailo_infer.py --source bus.jpg # single image
python hailo_infer.py --source clip.mp4 # video file
python hailo_infer.py --source 0 # USB webcam, live
python hailo_infer.py --source csi # Raspberry Pi Camera ModuleLe format de sortie de détection suppose que le HEF a été compilé avec nms_postprocess dans le script .alls. Si tu as compilé sans NMS, les sorties brutes sont les 6 tenseurs de tête de détection et tu dois exécuter le NMS séparément dans ton application.
Link to this sectionInférence vidéo avec TAPPAS#
Pour les pipelines vidéo à haut débit, TAPPAS fournit des éléments GStreamer qui diffusent la vidéo à travers la puce Hailo en temps réel :
MODEL=yolo11n
gst-launch-1.0 filesrc location=video.mp4 ! decodebin ! \
hailonet hef-path=${MODEL}.hef ! \
hailofilter function-name=yolov8 ! \
hailooverlay ! autovideosinkConsulte la documentation TAPPAS pour les options complètes de configuration de pipeline.
Link to this sectionRésumé#
Ce guide a couvert le flux de travail complet pour exporter des modèles de détection Ultralytics YOLO vers le format Hailo HEF :
- Exporter vers ONNX avec Ultralytics (
model.export(format="onnx")). - Analyser le modèle ONNX avec le DFC Hailo et spécifier les nœuds de fin de tête de détection.
- Configurer la normalisation et le NMS via un script de modèle.
- Quantifier avec un ensemble de données de calibration (COCO128 via Ultralytics).
- Compiler vers un fichier
.hefprêt pour Hailo-8, Hailo-8L ou Hailo-15.
Pour plus de détails, consulte la Hailo Developer Zone et la documentation Hailo. Pour les autres cibles d'exportation Ultralytics, consulte les guides connexes ONNX, OpenVINO, TensorRT, NCNN, TFLite Edge TPU, RKNN, Sony IMX500 et Qualcomm QNN. Pour comparer la vitesse et la précision des modèles exportés entre les formats, utilise le mode Benchmark. Pour la liste complète des formats et des options, visite la documentation du mode Export et la page du guide d'intégration.
Link to this sectionFAQ#
Link to this sectionQuels appareils Hailo sont pris en charge ?#
Le DFC Hailo prend en charge Hailo-8 (hailo8), Hailo-8L (hailo8l) et Hailo-15H (hailo15h). Consulte le tableau Architectures matérielles prises en charge pour la valeur HW_ARCH correspondante.
Link to this sectionQuels modèles Ultralytics peuvent être exportés ?#
Ce guide se concentre sur les modèles de détection. Consulte Tâches prises en charge pour la portée au niveau des tâches, Notes de compatibilité pour les limites de compatibilité des modèles, et Modèles pris en charge et nœuds de fin pour des exemples de nœuds de fin YOLO11 et YOLOv8.
Link to this sectionPourquoi le script de modèle utilise-t-il meta_arch=yolov8 pour YOLO11 ?#
YOLO11 utilise la même architecture de tête de détection découplée que YOLOv8. Le DFC Hailo utilise meta_arch=yolov8 pour la configuration NMS pour les deux familles de modèles.
Link to this sectionAi-je besoin d'un GPU pour l'étape d'optimisation ?#
Un GPU est fortement recommandé pour le réglage fin conscient de la quantification dans runner.optimize(). Sans lui, le processus fonctionne toujours mais est nettement plus lent (plusieurs heures contre environ 10 à 20 minutes avec un GPU).
Link to this sectionComment trouver les bons nœuds de fin pour mon modèle ?#
Exécute runner.translate_onnx_model(...) sans spécifier end_node_names, puis utilise les nœuds de tête de détection suggérés imprimés par le DFC. Consulte Autres architectures pour l'exemple de commande.
Link to this sectionOù puis-je obtenir le SDK Hailo DFC ?#
Le fichier wheel Python du SDK Hailo DFC est disponible sur la Hailo Developer Zone. Pour un exportateur direct Ultralytics Hailo, le script du modèle et la configuration de post-traitement devraient être générés ou sélectionnés dans le flux de travail d'exportation.