Meet YOLO26: next-gen vision AI.

Link to this sectionEsportazione Hailo per modelli Ultralytics YOLO#

Non è un formato di esportazione Ultralytics diretto

Il formato Hailo HEF non è attualmente supportato come destinazione diretta model.export(format="hailo") di Ultralytics. Il flusso di lavoro di seguito è un fallback manuale che esporta prima in ONNX, quindi utilizza la toolchain esterna Dataflow Compiler di Hailo per produrre un file .hef. Un flusso di lavoro Ultralytics integrato dovrebbe esporre Hailo tramite la stessa API di esportazione Python e CLI degli altri formati hardware.

La toolchain Hailo utilizza file HEF per piattaforme embedded tra cui Raspberry Pi AI Kit e AI HAT+, telecamere industriali, gateway edge e PC AI.

Questa guida illustra l'esportazione di modelli Ultralytics YOLO selezionati nel formato HEF (Hailo Executable Format) di Hailo utilizzando l'SDK Hailo Dataflow Compiler (DFC). Il flusso di lavoro parte da un modello YOLO .pt, lo esporta in ONNX, lo compila con gli strumenti Hailo e produce un file .hef pronto per gli acceleratori Hailo supportati.

Link to this sectionQuando utilizzare Hailo HEF#

HEF è l'artefatto compilato utilizzato da HailoRT sui dispositivi di destinazione Hailo. Usa questa guida manuale solo quando il tuo hardware di distribuzione richiede specificamente Hailo HEF prima che sia disponibile il supporto diretto all'esportazione di Ultralytics verso Hailo.

HEF ha un ruolo nel deployment simile a formati specifici per l'hardware come RKNN per NPU Rockchip, IMX500 per Raspberry Pi AI Cameras e Qualcomm QNN per NPU Snapdragon, ma non è attualmente generato direttamente da Ultralytics.

Questo flusso di lavoro è rilevante quando hai bisogno di:

  • Compatibilità Raspberry Pi AI Kit: Hailo-8L è utilizzato nel Raspberry Pi AI Kit ufficiale e in AI HAT+.
  • Post-elaborazione HailoRT: HailoRT può includere la non-maximum suppression di YOLO nella pipeline di inferenza compilata.
  • Compilazione INT8: L'Hailo DFC quantizza il modello con immagini di calibrazione rappresentative per produrre un grafo INT8 per l'hardware Hailo. Scopri di più sulla quantizzazione del modello.

Link to this sectionFormato di esportazione Hailo HEF#

HEF è un eseguibile specifico per l'hardware generato dal compilatore Hailo Dataflow. Contiene il grafo del modello quantizzato, l'allocazione della memoria, la pianificazione e la post-elaborazione opzionale configurata per un'architettura Hailo di destinazione. A differenza dei formati standard di modalità di esportazione YOLO prodotti direttamente da model.export(format=...), la compilazione HEF utilizza attualmente un flusso a due fasi:

  1. Esporta YOLO in ONNX con Ultralytics.
  2. Usa gli strumenti Hailo DFC per analizzare, ottimizzare, quantizzare e compilare il modello ONNX in HEF.

L'intero flusso di lavoro si espande nella seguente pipeline:

YOLO (.pt) -> ONNX -> HAR (parse) -> HAR (optimize/quantize) -> HEF (compile)
  1. Esporta in ONNX utilizzando la modalità di esportazione di Ultralytics
  2. Analizza il modello ONNX nel formato HAR intermedio di Hailo
  3. Carica uno script modello (.alls) con direttive di normalizzazione e post-elaborazione
  4. Calibra e quantizza utilizzando immagini rappresentative
  5. Compila in un file HEF distribuibile

Link to this sectionAttività supportate#

L'esempio manuale attuale si concentra sul rilevamento oggetti con YOLO11 perché lo script del modello Hailo e la configurazione di post-elaborazione sono specifici per la head di rilevamento. Una futura implementazione diretta di model.export(format="hailo") dovrebbe rendere l'esportazione verso Hailo simile a ogni altro formato di esportazione Ultralytics, con il supporto alle attività regolato dalla head del modello e dalla compatibilità del compilatore Hailo anziché da passaggi di flusso di lavoro esterni.

CompitoDestinazione di esportazione diretta HailoNote
Object Detection✅ Destinazione principaleIl rilevamento con YOLOv8, YOLO11 e YOLO26 dovrebbe essere il primo percorso di esportazione diretta.
Segmentazione di istanze✅ DestinazioneLa segmentazione con YOLOv8, YOLO11 e YOLO26 richiede la gestione e la convalida dell'output delle maschere specifiche per l'attività.
Segmentazione semantica⚠️ ValidaLa segmentazione semantica con YOLO26 necessita di un compilatore dedicato e di un percorso di convalida dell'output.
Pose Estimation⚠️ ValidaLa posa (pose) richiede la gestione dell'output dei punti chiave (keypoint) oltre al percorso NMS di rilevamento.
Rilevamento OBB⚠️ ValidaL'OBB richiede la gestione dell'output delle caselle ruotate oltre al percorso standard NMS di rilevamento.
Classificazione⚠️ ValidaLa classificazione ha una head di output più semplice, ma necessita comunque della compilazione Hailo e della convalida runtime.

Finché l'esportazione diretta Hailo non sarà implementata in Ultralytics, è documentato solo il flusso di lavoro manuale da ONNX a HEF qui sotto.

Link to this sectionVersioni dell'SDK Hailo#

L'esportazione diretta verso Hailo deve tener conto della suddivisione tra hardware e generazione SDK di Hailo:

  • Hailo-8 e Hailo-8L: usa Hailo Dataflow Compiler v3.x. Questo è il percorso rilevante per le distribuzioni Raspberry Pi AI Kit e 13 TOPS AI HAT+.
  • Hailo-10 e Hailo-15: usa Hailo Dataflow Compiler v5.x.

Questa suddivisione di versioni influenza le API del compilatore, le architetture supportate, la compatibilità degli HEF generati e quali valori hw_arch un esportatore diretto dovrebbe esporre. Il supporto alle attività su una generazione di hardware Hailo non dovrebbe essere considerato come supporto su un'altra senza convalidare la versione DFC di destinazione e hw_arch.

Link to this sectionNote sulla compatibilità#

La compatibilità dell'esportazione Hailo dipende dalla head del modello, dalla dimensione dell'immagine di input, dal conteggio delle classi, dall'architettura Hailo, dallo script del modello generato (.alls) e dalla configurazione di post-elaborazione. Le configurazioni statiche non sono modelli universali. Ad esempio, un JSON NMS creato per un modello YOLO11n COCO a 80 classi non è corretto per un modello personalizzato a 3 classi o per una diversa imgsz fissa.

AmbitoSupporto previstoNote
Rilevamento YOLOv8 / YOLO11✅ BuonoHead di rilevamento disaccoppiata condivisa; le direttive .alls, i nodi finali e la configurazione NMS devono comunque corrispondere al grafo esportato e alla imgsz fissa.
Rilevamento YOLOv8 / YOLO11 personalizzato✅ PossibileRichiede una configurazione NMS per modello generata dal conteggio delle classi, dagli stride e dal layout della head di rilevamento; un JSON statico non coinciderà.
Rilevamento YOLO26✅ DestinazioneL'architettura senza NMS necessita di un percorso separato per il compilatore e la post-elaborazione; non riutilizzare il flusso di lavoro NMS per YOLO11/YOLOv8 riportato sotto per YOLO26.
Segmentazione di istanze YOLO26✅ DestinazioneNecessita di gestione dell'output della maschera specifica per la segmentazione YOLO26 e della convalida dell'accuratezza.
YOLO26 semantica, posa, OBB, classificazione⚠️ RicercaQueste attività necessitano di un compilatore dedicato e di una convalida runtime prima di poter essere dichiarate come direttamente supportate.
Dimensioni dell'immagine dinamiche o arbitrarie❌ Non supportatoLa compilazione Hailo utilizza una forma di input fissa; le impostazioni .alls e di post-elaborazione devono corrispondere alla imgsz esportata.

Link to this sectionInstallazione#

Link to this sectionPassaggio 1: Installa Ultralytics#

pip install ultralytics

Link to this sectionPassaggio 2: Installa l'SDK Hailo DFC#

L'Hailo DFC è richiesto per l'analisi, l'ottimizzazione e la compilazione. Scarica la wheel Python dalla Hailo Developer Zone (è richiesta la registrazione gratuita) e installala:

pip install /path/to/hailo_dataflow_compiler-*.whl
Nota

L'SDK Hailo DFC richiede una macchina Linux x86_64. L'esportazione e la compilazione non possono essere eseguite su dispositivi ARM come Raspberry Pi. Copia il file .hef risultante sul tuo dispositivo basato su Hailo per il deployment con HailoRT.

Link to this sectionEsempio di esportazione YOLO11n HEF#

Lo script qui sotto compila un modello di rilevamento YOLO11n da .pt a .hef con una dimensione di input fissa di 640 pixel. Esporta in ONNX utilizzando Ultralytics, quindi compila con Hailo DFC utilizzando COCO128 come piccolo set di dati di calibrazione.

Prima di eseguire lo script, fornisci un JSON NMS per Hailo che corrisponda esattamente al grafo di esportazione YOLO11n, al conteggio delle classi, agli stride e alla dimensione di input fissa. Riutilizza questo script come punto di partenza noto per YOLO11n; i modelli personalizzati necessitano di nodi finali, direttive .alls e impostazioni NMS corrispondenti.

YOLO26 utilizza un percorso Hailo differente

I modelli YOLO26 non utilizzano NMS. Un esportatore diretto Ultralytics Hailo necessita di un percorso dedicato per la compilazione e la post-elaborazione di YOLO26 per il rilevamento o la segmentazione di istanze, anziché l'esempio NMS per YOLO11 riportato qui sotto.

Pipeline completa
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}")

Lo script di esportazione organizza artefatti e log come segue:

  • Cartella di Distribuzione: Gli artefatti vengono salvati in yolo11n_hailo_model/, rispecchiando il layout standard <model>_<format>_model/ utilizzato da altre esportazioni di Ultralytics.
  • File Richiesti: I due file necessari per la distribuzione sono il yolo11n.hef compilato e il sidecar metadata.yaml.
  • Metadati: Il file metadata.yaml contiene campi essenziali (names, imgsz, task, stride, ecc.) estratti dai metadati ONNX. Gli script di inferenza caricano i nomi delle classi da questo file poiché il formato HEF non li memorizza.
  • File Intermedi: La cartella di esportazione contiene anche i checkpoint intermedi yolo11n.onnx e yolo11n.o.har.
  • File di Log: L'SDK Hailo genera diversi log diagnostici (ad esempio acceleras.log, allocator.log, hailo_sdk.client.log e hailo_sdk.core.log) nella directory di lavoro; questi possono essere tranquillamente ignorati o eliminati.
  • Raspberry Pi AI Kit: Per questo hardware specifico, assicurati di impostare HW_ARCH = "hailo8l" prima di eseguire il passaggio di compilazione.

Link to this sectionAnalisi passo dopo passo#

Lo script completo qui sopra viene eseguito dall'inizio alla fine. Questa sezione spiega cosa fa ogni fase e i dettagli specifici del modello da osservare quando lo adatti al tuo modello.

Link to this sectionPassaggio 1: Esportazione in ONNX e Salvataggio dei Metadati#

Ultralytics esporta il tuo modello addestrato in formato ONNX, che il DFC di Hailo acquisisce come input. opset=11 offre un'ampia compatibilità DFC e l'ONNX viene spostato in una cartella di distribuzione yolo11n_hailo_model/ (che rispecchia il layout <model>_<format>_model/ di altre esportazioni Ultralytics) per mantenere ordinata la directory di lavoro.

L'HEF non memorizza alcun nome di classe, quindi i metadati che Ultralytics incorpora nell'ONNX vengono copiati in un sidecar standard metadata.yaml accanto ad esso. Questo è lo stesso metadata.yaml prodotto da altri formati di esportazione (names, imgsz, task, stride e altro), e l'inferenza legge i nomi delle classi da esso, quindi il flusso di lavoro funziona per modelli personalizzati senza dover codificare alcuna etichetta.

Link to this sectionPassaggio 2: Analizza il modello ONNX#

runner.translate_onnx_model(...) converte il grafo ONNX nella rappresentazione HAR intermedia di Hailo. La lista end_node_names indica al DFC dove tagliare il grafo prima della NMS in modo che Hailo possa collegare la sua elaborazione hardware.

Ricerca dei nodi finali

Il DFC stampa un suggerimento dopo l'analisi:

[info] In order to use HailoRT post-processing capabilities, these end node names should be used: ...

Copia quei nomi di nodo se non sei sicuro di quali usare o se stai lavorando con un'architettura personalizzata o meno comune.

Link to this sectionPassaggio 3: Carica lo script del modello#

Lo script del modello (.alls) configura la normalizzazione dell'input, l'attivazione dell'output e la post-elaborazione NMS. L'impostazione meta_arch=yolov8 si applica sia a YOLOv8 che a YOLO11 poiché condividono lo stesso layout dell'head di rilevamento.

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)
Nota

I nomi dei layer change_output_activation (conv54, conv65, conv80) sono assegnati dal DFC durante l'analisi e sono specifici del modello. Se stai compilando una dimensione o un'architettura di modello diversa, controlla l'output del DFC per i nomi corretti o genera le direttive .alls dal grafo esportato.

Anche il file NMS_CONFIG è specifico del modello. Usa una configurazione che corrisponda esattamente al tuo modello esportato.

engine=cpu esegue l'NMS tramite HailoRT sulla CPU host. Usa engine=nn_core solo per combinazioni di modello/script che Hailo documenta come supportate dall'hardware target e dalla versione dell'SDK.

Rimuovi la riga nms_postprocess se preferisci eseguire l'NMS interamente nel codice della tua applicazione. Se lo fai, aggiorna il parser di inferenza poiché l'HEF restituirà tensori raw dell'head di rilevamento invece di rilevamenti NMS raggruppati.

Link to this sectionPassaggio 4: Crea il set di dati di calibrazione#

La quantizzazione INT8 richiede un set rappresentativo di immagini impilate in un array float32 (N, imgsz, imgsz, 3). Lo script utilizza COCO128, che Ultralytics scarica automaticamente tramite check_det_dataset.

Suggerimento

Usa almeno 64 immagini per la calibrazione. Più immagini generalmente migliorano la qualità della quantizzazione. Per risultati ottimali, usa immagini dal tuo dominio di deployment piuttosto che COCO128.

Link to this sectionPassaggio 5: Ottimizza e quantizza#

runner.optimize(calibset) applica il fine-tuning consapevole della quantizzazione e l'analisi del rumore dei layer, quindi runner.save_har(...) scrive un checkpoint intermedio facoltativo. Una GPU è fortemente consigliata; senza di essa, questo passaggio può richiedere diverse ore.

Link to this sectionPassaggio 6: Compila in HEF#

runner.compile() produce l'HEF finale, scritto in yolo11n_hailo_model/yolo11n.hef. Ora si trova accanto al suo metadata.yaml, pronto per essere copiato sul dispositivo per l'inferenza.

Link to this sectionModelli supportati e nodi finali#

Per i modelli di rilevamento, end_node_names identifica gli output dell'head di rilevamento ONNX che Hailo deve compilare prima di allegare la sua post-elaborazione NMS. Questi nomi variano in base all'architettura e possono cambiare quando cambia il grafo esportato.

Gli esempi di nodi finali qui sotto si applicano ai modelli di rilevamento YOLOv8 e YOLO11 che utilizzano la post-elaborazione NMS in stile YOLOv8 di Hailo. YOLO26 non utilizza NMS e non impiega questa configurazione NMS di YOLO11.

Link to this sectionYOLO11 e YOLOv8#

YOLO11 e YOLOv8 condividono lo stesso head di rilevamento disaccoppiato. L'indice del layer differisce di uno tra le due famiglie:

Famiglia di modelliLayer dell'head di rilevamentoModello di nodo finale
YOLO11 (tutti)model.23/model.23/cv2.0/cv2.0.2/Conv (6 nodi)
YOLOv8 (tutti)model.22/model.22/cv2.0/cv2.0.2/Conv (6 nodi)

Nodi finali YOLO11 (tutte le dimensioni: 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",
]

Nodi finali YOLOv8 (tutte le dimensioni: 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 sectionAltre architetture#

Per altre architetture di rilevamento, esegui prima il passaggio di analisi senza end_node_names, leggi i nodi suggeriti dall'output del registro DFC, quindi riesegui con quei nodi:

# 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..."

Per il supporto diretto di Ultralytics, queste direttive .alls e impostazioni di post-elaborazione dovrebbero essere generate o selezionate dall'esportatore invece di richiedere agli utenti di assemblarle manualmente.

Link to this sectionArchitetture hardware supportate#

ArchitetturaDispositivoCalcolo di picco (Specifiche fornitore)Caso d'uso comune
hailo8Hailo-826 TOPSScheda acceleratrice Hailo
hailo8lHailo-8L13 TOPSRaspberry Pi AI Kit
hailo15hHailo-15H20 TOPSDispositivi target Hailo-15

Imposta HW_ARCH nello script in modo che corrisponda al tuo dispositivo target prima di compilare.

Link to this sectionEsecuzione dell'inferenza su hardware Hailo#

Una volta terminata la compilazione, copia l'intera cartella yolo11n_hailo_model/ (il file .hef più il suo metadata.yaml) sul tuo dispositivo basato su Hailo ed esegui l'inferenza utilizzando l'API Python HailoRT (pacchetto hailo_platform) o, su Raspberry Pi, l'helper picamera2 Hailo (un wrapper di HailoRT). Entrambi sono mostrati nelle schede sottostanti. Tenere i due file insieme consente agli script sottostanti di leggere i nomi delle classi dal metadata.yaml accanto all'HEF. A differenza dei passaggi di esportazione DFC, l'inferenza viene eseguita direttamente sul dispositivo edge.

Nota

Il codice di inferenza qui sotto viene eseguito sul dispositivo basato su Hailo (ad esempio, Raspberry Pi + AI Kit), non sulla macchina x86 utilizzata per la compilazione.

Link to this sectionPassaggio 1: Installa HailoRT sul dispositivo#

Sul dispositivo target, installa HailoRT e i binding Python. Per gli utenti di Raspberry Pi AI Kit e AI HAT+, la guida ufficiale al software AI di Raspberry Pi installa HailoRT, il driver del dispositivo e i binding Python con:

sudo apt install dkms
sudo apt install hailo-all
sudo reboot

Per i dispositivi Hailo non Raspberry Pi, installa il pacchetto HailoRT che corrisponde al tuo dispositivo, al driver e alla versione dell'SDK dalla Hailo Developer Zone.

I dispositivi AI HAT+ 2 utilizzano un pacchetto Raspberry Pi diverso (hailo-h10-all) e il flusso di lavoro Hailo-10H. Segui la guida al software AI di Raspberry Pi per quella generazione di hardware.

Link to this sectionPassaggio 2: Controllo rapido#

Prima di eseguire l'inferenza Python, conferma che il dispositivo Hailo sia riconosciuto:

hailortcli fw-control identify

Dovresti vedere stampati il tipo di dispositivo, la versione del firmware e il numero di serie.

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: HAILO8

Link to this sectionPassaggio 3: Esegui l'inferenza#

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.

Il percorso nativo del fornitore HailoRT viene eseguito su qualsiasi piattaforma con un dispositivo Hailo e non necessita di dipendenze aggiuntive. Passa a --source un percorso immagine, un percorso video, un indice webcam (ad esempio 0) per l'acquisizione USB/V4L2 live, o csi per il Modulo Fotocamera Raspberry Pi. L'opzione CSI richiede che picamera2 sia installato, poiché il moderno Raspberry Pi OS instrada la fotocamera tramite libcamera anziché un semplice dispositivo V4L2.

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()

Eseguilo contro qualsiasi sorgente (le immagini salvano output.jpg, i video salvano output.mp4, i flussi live vengono visualizzati in una finestra, premi q per uscire):

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 Module
Suggerimento

Il formato dell'output di rilevamento presuppone che l'HEF sia stato compilato con nms_postprocess nello script .alls. Se hai compilato senza NMS, gli output grezzi sono i 6 tensori della head di rilevamento e devi eseguire NMS separatamente nella tua applicazione.

Link to this sectionInferenza video con TAPPAS#

Per pipeline video ad alto throughput, TAPPAS fornisce elementi GStreamer che trasmettono video attraverso il chip Hailo in tempo reale:

MODEL=yolo11n
gst-launch-1.0 filesrc location=video.mp4 ! decodebin ! \
  hailonet hef-path=${MODEL}.hef ! \
  hailofilter function-name=yolov8 ! \
  hailooverlay ! autovideosink

Consulta la documentazione TAPPAS per le opzioni di configurazione complete della pipeline.

Questa guida ha trattato il flusso di lavoro completo per esportare i modelli di rilevamento Ultralytics YOLO nel formato Hailo HEF:

  1. Esporta in ONNX con Ultralytics (model.export(format="onnx")).
  2. Analizza il modello ONNX con il Hailo DFC e specifica i nodi finali della head di rilevamento.
  3. Configura la normalizzazione e l'NMS tramite uno script di modello.
  4. Quantizza con un set di dati di calibrazione (COCO128 tramite Ultralytics).
  5. Compila in un file .hef pronto per Hailo-8, Hailo-8L o Hailo-15.

Per ulteriori dettagli, consulta la Hailo Developer Zone e la documentazione di Hailo. Per altre destinazioni di esportazione Ultralytics, consulta le guide correlate su ONNX, OpenVINO, TensorRT, NCNN, TFLite Edge TPU, RKNN, Sony IMX500 e Qualcomm QNN. Per confrontare velocità e precisione del modello esportato tra diversi formati, usa la modalità Benchmark. Per l'elenco completo dei formati e delle opzioni, visita la documentazione della modalità Esportazione e la pagina della guida alle integrazioni.

Link to this sectionFAQ#

Link to this sectionQuali dispositivi Hailo sono supportati?#

Il Hailo DFC supporta Hailo-8 (hailo8), Hailo-8L (hailo8l) e Hailo-15H (hailo15h). Vedi la tabella Architetture hardware supportate per il valore HW_ARCH corrispondente.

Link to this sectionQuali modelli Ultralytics possono essere esportati?#

Questa guida si concentra sui modelli di rilevamento. Vedi Attività supportate per l'ambito a livello di attività, Note sulla compatibilità per i limiti di compatibilità del modello e Modelli supportati e nodi finali per esempi di nodi finali YOLO11 e YOLOv8.

Link to this sectionPerché lo script del modello utilizza meta_arch=yolov8 per YOLO11?#

YOLO11 utilizza la stessa architettura della head di rilevamento disaccoppiata di YOLOv8. Il Hailo DFC utilizza meta_arch=yolov8 per la configurazione NMS per entrambe le famiglie di modelli.

Link to this sectionHo bisogno di una GPU per il passaggio di ottimizzazione?#

Una GPU è vivamente consigliata per il fine-tuning consapevole della quantizzazione in runner.optimize(). Senza di essa, il processo funziona comunque ma è significativamente più lento (diverse ore rispetto a circa 10-20 minuti con una GPU).

Link to this sectionCome trovo i nodi finali corretti per il mio modello?#

Esegui runner.translate_onnx_model(...) senza specificare end_node_names, quindi utilizza i nodi della detection-head suggeriti stampati dal DFC. Vedi Altre architetture per il comando di esempio.

Link to this sectionDove posso trovare l'SDK Hailo DFC?#

Il file Python wheel dell'SDK Hailo DFC è disponibile nella Hailo Developer Zone. Per un esportatore diretto Ultralytics Hailo, lo script del modello e la configurazione di post-elaborazione dovrebbero essere generati o selezionati all'interno del flusso di lavoro di esportazione.

Commenti