Meet YOLO26: next-gen vision AI.

Link to this sectionExportação HEF para Modelos YOLO da Ultralytics#

Não é um formato de exportação direto da Ultralytics

O formato Hailo HEF não é suportado atualmente como um destino direto da função model.export(format="hailo") do Ultralytics. O fluxo de trabalho abaixo é um método alternativo manual que exporta primeiro para ONNX e, em seguida, utiliza a cadeia de ferramentas Dataflow Compiler externa da Hailo para produzir um arquivo .hef. Um fluxo de trabalho Ultralytics fluido deve expor a Hailo através da mesma API de exportação Python e CLI utilizada por outros formatos de hardware.

O conjunto de ferramentas Hailo utiliza arquivos HEF para plataformas embarcadas, incluindo o Raspberry Pi AI Kit e AI HAT+, câmeras industriais, gateways de borda e PCs com IA.

Este guia orienta sobre como exportar modelos selecionados do Ultralytics YOLO para o HEF (Hailo Executable Format) da Hailo usando o SDK Hailo Dataflow Compiler (DFC). O fluxo de trabalho começa com um modelo YOLO .pt, exporta para ONNX, compila com as ferramentas da Hailo e produz um arquivo .hef pronto para aceleradores Hailo suportados.

Link to this sectionQuando utilizar o HEF da Hailo#

HEF é o artefato compilado consumido pelo HailoRT em dispositivos alvo Hailo. Utilize este guia manual apenas quando o seu hardware de implantação exigir especificamente o Hailo HEF antes que o suporte de exportação direta do Ultralytics para Hailo esteja disponível.

O HEF tem uma função de implantação semelhante a formatos específicos de hardware, como RKNN para NPUs Rockchip, IMX500 para câmeras com IA Raspberry Pi e Qualcomm QNN para NPUs Snapdragon, mas não é atualmente gerado diretamente pela Ultralytics.

Este fluxo de trabalho é relevante quando você precisa de:

  • Compatibilidade com o Raspberry Pi AI Kit: O Hailo-8L é utilizado no kit oficial Raspberry Pi AI Kit e AI HAT+.
  • Pós-processamento com HailoRT: O HailoRT pode incluir a supressão de não-máximos (NMS) do YOLO no pipeline de inferência compilado.
  • Compilação INT8: O DFC da Hailo quantiza o modelo com imagens de calibração representativas para produzir um grafo INT8 para o hardware da Hailo. Saiba mais sobre quantização de modelos.

Link to this sectionFormato de Exportação HEF da Hailo#

HEF é um executável específico de hardware gerado pelo Hailo Dataflow Compiler. Ele contém o grafo do modelo quantizado, alocação de memória, agendamento e pós-processamento opcional configurado para uma arquitetura Hailo de destino. Ao contrário dos formatos padrão do Modo de Exportação do YOLO produzidos diretamente por model.export(format=...), a compilação HEF utiliza atualmente um fluxo de duas etapas:

  1. Exportar YOLO para ONNX com a Ultralytics.
  2. Utilizar as ferramentas DFC da Hailo para analisar, otimizar, quantizar e compilar o modelo ONNX em HEF.

O fluxo de trabalho completo expande-se para o seguinte pipeline:

YOLO (.pt) -> ONNX -> HAR (parse) -> HAR (optimize/quantize) -> HEF (compile)
  1. Exportar para ONNX usando o Modo de Exportação da Ultralytics
  2. Analisar o modelo ONNX para o formato intermediário HAR da Hailo
  3. Carregar um script de modelo (.alls) com diretrizes de normalização e pós-processamento
  4. Calibrar e quantizar usando imagens representativas
  5. Compilar para um arquivo HEF implantável

Link to this sectionTarefas Suportadas#

O exemplo manual atual foca na detecção de objetos YOLO11 porque o script do modelo Hailo e a configuração de pós-processamento são específicos do head de detecção. Uma futura implementação direta model.export(format="hailo") deverá tornar a exportação para Hailo tão simples quanto qualquer outro formato de exportação do Ultralytics, com suporte a tarefas controlado pelo head do modelo e pela compatibilidade do compilador Hailo, em vez de etapas externas de fluxo de trabalho.

TarefaDestino de Exportação Direta HailoNotas
Detecção de Objetos✅ Destino principalA detecção YOLOv8, YOLO11 e YOLO26 deve ser o primeiro caminho de exportação direta.
Segmentação de instâncias✅ DestinoA segmentação YOLOv8, YOLO11 e YOLO26 requer manuseio e validação específicos de saída de máscara para a tarefa.
Segmentação semântica⚠️ ValidarA segmentação semântica YOLO26 precisa de um compilador dedicado e um caminho de validação de saída.
Estimativa de Pose⚠️ ValidarA pose requer manuseio de saída de keypoints além do caminho de NMS de detecção.
Detecção OBB⚠️ ValidarOBB requer manuseio de saída de caixas rotacionadas além do caminho de NMS de detecção padrão.
Classificação⚠️ ValidarA classificação possui um head de saída mais simples, mas ainda precisa da compilação Hailo e validação de tempo de execução.

Até que a exportação direta para Hailo seja implementada no Ultralytics, apenas o fluxo de trabalho manual de ONNX para HEF abaixo está documentado.

Link to this sectionVersões do SDK Hailo#

A exportação direta para Hailo deve levar em conta a divisão entre as gerações de hardware e SDK da Hailo:

  • Hailo-8 e Hailo-8L: utilize o Hailo Dataflow Compiler v3.x. Este é o caminho relevante para implantações em Raspberry Pi AI Kit e 13 TOPS AI HAT+.
  • Hailo-10 e Hailo-15: utilize o Hailo Dataflow Compiler v5.x.

Esta divisão de versões afeta as APIs do compilador, arquiteturas suportadas, compatibilidade do HEF gerado e quais valores de hw_arch um exportador direto deve expor. O suporte a tarefas em uma geração de hardware Hailo não deve ser tratado como suporte em outra sem validar a versão do DFC de destino e o hw_arch.

Link to this sectionNotas de Compatibilidade#

A compatibilidade da exportação Hailo depende do head do modelo, tamanho da imagem de entrada, contagem de classes, arquitetura Hailo, script do modelo gerado (.alls) e configuração de pós-processamento. Configurações estáticas não são modelos universais. Por exemplo, um JSON de NMS criado para um modelo YOLO11n de 80 classes COCO não é correto para um modelo personalizado de 3 classes ou para um imgsz fixo diferente.

EscopoSuporte EsperadoNotas
Detecção YOLOv8 / YOLO11✅ BomHead de detecção desacoplado compartilhado; as diretivas .alls, nós finais e configuração de NMS ainda precisam corresponder ao grafo exportado e ao imgsz fixo.
Detecção personalizada YOLOv8 / YOLO11✅ PossívelRequer configuração de NMS por modelo, gerada a partir da contagem de classes, strides e layout do head de detecção; um JSON estático não será compatível.
Detecção YOLO26✅ DestinoA arquitetura sem NMS precisa de um caminho separado de compilador/pós-processamento; não reutilize o fluxo de trabalho de NMS do YOLO11/YOLOv8 abaixo para o YOLO26.
Segmentação de instância YOLO26✅ DestinoPrecisa de manuseio de saída de máscara específico para segmentação YOLO26 e validação de precisão.
Semântica, pose, OBB e classificação YOLO26⚠️ PesquisaEssas tarefas precisam de validação dedicada de compilador e tempo de execução antes de poderem ser anunciadas como diretamente suportadas.
Tamanhos de imagem dinâmicos ou arbitrários❌ Não suportadoA compilação Hailo usa um formato de entrada fixo; as configurações de .alls e de pós-processamento devem corresponder ao imgsz exportado.

Link to this sectionInstalação#

Link to this sectionPasso 1: Instalar a Ultralytics#

pip install ultralytics

Link to this sectionPasso 2: Instalar o SDK DFC da Hailo#

O DFC da Hailo é necessário para análise, otimização e compilação. Baixe o wheel do Python do Hailo Developer Zone (registro gratuito necessário) e instale-o:

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

O SDK DFC da Hailo requer uma máquina Linux x86_64. A exportação e a compilação não podem ser realizadas em dispositivos ARM, como o Raspberry Pi. Copie o arquivo .hef resultante para o seu dispositivo alimentado pela Hailo para implantação com o HailoRT.

Link to this sectionExemplo de Exportação HEF do YOLO11n#

O script abaixo compila um modelo de detecção YOLO11n de .pt para .hef em um tamanho de entrada fixo de 640 pixels. Ele exporta para ONNX usando a Ultralytics e, em seguida, compila com o DFC da Hailo usando o COCO128 como um pequeno conjunto de dados de calibração.

Antes de executar o script, forneça um JSON de NMS da Hailo que corresponda exatamente ao grafo de exportação do YOLO11n, contagem de classes, strides e tamanho de entrada fixo. Reutilize este script como um ponto de partida conhecido para YOLO11n; modelos personalizados precisam de nós finais, diretivas .alls e configurações de NMS correspondentes.

O YOLO26 usa um caminho Hailo diferente

Modelos YOLO26 são livres de NMS. Um exportador Ultralytics Hailo direto precisa de um caminho dedicado de compilação e pós-processamento para detecção ou segmentação de instância, em vez do exemplo de NMS do YOLO11 abaixo.

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

O script de exportação organiza os artefatos e logs da seguinte forma:

  • Pasta de implantação: Os artefatos são salvos em yolo11n_hailo_model/, espelhando o layout padrão <model>_<format>_model/ usado por outras exportações do Ultralytics.
  • Arquivos necessários: Os dois arquivos necessários para a implantação são o yolo11n.hef compilado e o sidecar metadata.yaml.
  • Metadados: O metadata.yaml contém campos essenciais (names, imgsz, task, stride, etc.) extraídos dos metadados ONNX. Os scripts de inferência carregam os nomes das classes a partir deste arquivo, já que o formato HEF não os armazena.
  • Arquivos intermediários: A pasta de exportação também contém os checkpoints intermediários yolo11n.onnx e yolo11n.o.har.
  • Arquivos de log: O Hailo SDK gera vários logs de diagnóstico (por exemplo, acceleras.log, allocator.log, hailo_sdk.client.log e hailo_sdk.core.log) no diretório de trabalho; eles podem ser ignorados ou excluídos com segurança.
  • Raspberry Pi AI Kit: Para este hardware específico, certifique-se de definir HW_ARCH = "hailo8l" antes de executar a etapa de compilação.

Link to this sectionDetalhamento Passo a Passo#

O script completo acima é executado de ponta a ponta. Esta seção explica o que cada etapa faz e os detalhes específicos do modelo a serem observados ao adaptá-lo para o seu próprio modelo.

Link to this sectionEtapa 1: Exportar para ONNX e salvar metadados#

O Ultralytics exporta seu modelo treinado para o formato ONNX, que o Hailo DFC ingere como entrada. opset=11 proporciona ampla compatibilidade com o DFC, e o ONNX é movido para uma pasta de implantação yolo11n_hailo_model/ (espelhando o layout <model>_<format>_model/ de outras exportações do Ultralytics) para manter o diretório de trabalho organizado.

O HEF não armazena nomes de classes, portanto, os metadados que o Ultralytics incorpora no ONNX são copiados para um sidecar metadata.yaml padrão ao lado dele. Este é o mesmo metadata.yaml que outros formatos de exportação produzem (names, imgsz, task, stride e mais), e a inferência lê os nomes das classes a partir dele, para que o fluxo de trabalho funcione para modelos personalizados sem codificar nenhum rótulo.

Link to this sectionPasso 2: Analisar o Modelo ONNX#

runner.translate_onnx_model(...) converte o grafo ONNX na representação intermediária HAR do Hailo. A lista end_node_names informa ao DFC onde cortar o grafo antes do NMS para que o Hailo possa anexar seu próprio pós-processamento de hardware.

Encontrando nós finais

O DFC imprime uma sugestão após a análise:

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

Copie esses nomes de nós se não tiver certeza de quais usar, ou se estiver trabalhando com uma arquitetura personalizada ou menos comum.

Link to this sectionPasso 3: Carregar o Script do Modelo#

O script do modelo (.alls) configura a normalização de entrada, ativação de saída e pós-processamento de NMS. A configuração meta_arch=yolov8 aplica-se tanto ao YOLOv8 quanto ao YOLO11, uma vez que compartilham o mesmo layout de cabeça de detecção.

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

Os nomes das camadas change_output_activation (conv54, conv65, conv80) são atribuídos pelo DFC durante a análise e são específicos do modelo. Se você estiver compilando um modelo de tamanho ou arquitetura diferente, verifique os nomes corretos na saída do DFC ou gere as diretivas .alls a partir do grafo exportado.

O arquivo NMS_CONFIG também é específico do modelo. Use uma configuração que corresponda exatamente ao seu modelo exportado.

engine=cpu executa o NMS através do HailoRT na CPU host. Use engine=nn_core apenas para combinações de modelo/script que a Hailo documenta como suportadas pela versão do hardware e do SDK de destino.

Remova a linha nms_postprocess se preferir executar o NMS totalmente no código da sua aplicação. Se fizer isso, atualize o analisador de inferência, pois o HEF emitirá tensores de cabeça de detecção brutos em vez de detecções de NMS agrupadas.

Link to this sectionPasso 4: Criar o Conjunto de Dados de Calibração#

A quantização INT8 requer um conjunto representativo de imagens empilhadas em um array float32 (N, imgsz, imgsz, 3). O script usa o COCO128, que o Ultralytics baixa automaticamente via check_det_dataset.

Dica

Use pelo menos 64 imagens para calibração. Mais imagens geralmente melhoram a qualidade da quantização. Para obter melhores resultados, use imagens do seu domínio de implantação em vez do COCO128.

Link to this sectionPasso 5: Otimizar e Quantizar#

runner.optimize(calibset) aplica ajuste fino consciente da quantização e análise de ruído de camada, então runner.save_har(...) grava um checkpoint intermediário opcional. Uma GPU é fortemente recomendada; sem ela, esta etapa pode levar várias horas.

Link to this sectionPasso 6: Compilar para HEF#

runner.compile() produz o HEF final, gravado em yolo11n_hailo_model/yolo11n.hef. Ele agora fica ao lado de seu metadata.yaml, pronto para ser copiado para o dispositivo para inferência.

Link to this sectionModelos Suportados e Nós Finais#

Para modelos de detecção, end_node_names identifica as saídas da cabeça de detecção ONNX que a Hailo deve compilar antes de anexar seu pós-processamento de NMS. Esses nomes variam de acordo com a arquitetura e podem mudar quando o grafo exportado muda.

Os exemplos de nós finais abaixo aplicam-se a modelos de detecção YOLOv8 e YOLO11 que usam o pós-processamento de NMS estilo YOLOv8 da Hailo. O YOLO26 não utiliza NMS e não usa esta configuração de NMS do YOLO11.

Link to this sectionYOLO11 e YOLOv8#

O YOLO11 e o YOLOv8 compartilham a mesma cabeça de detecção desacoplada. O índice da camada difere em um entre as duas famílias:

Família de ModelosCamada da Cabeça de DetecçãoPadrão de Nó Final
YOLO11 (todos)model.23/model.23/cv2.0/cv2.0.2/Conv (6 nós)
YOLOv8 (todos)model.22/model.22/cv2.0/cv2.0.2/Conv (6 nós)

Nós finais do YOLO11 (todos os tamanhos: 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ós finais do YOLOv8 (todos os tamanhos: 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 sectionOutras Arquiteturas#

Para outras arquiteturas de detecção, execute a etapa de análise sem end_node_names primeiro, leia os nós sugeridos da saída do log do DFC e, em seguida, execute novamente com esses nós:

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

Para suporte direto do Ultralytics, estas diretivas .alls e configurações de pós-processamento devem ser geradas ou selecionadas pelo exportador, em vez de exigir que os usuários as montem manualmente.

Link to this sectionArquiteturas de Hardware Suportadas#

ArquiteturaDispositivoPico de Computação (Especificação do Fornecedor)Caso de Uso Comum
hailo8Hailo-826 TOPSPlaca aceleradora Hailo
hailo8lHailo-8L13 TOPSRaspberry Pi AI Kit
hailo15hHailo-15H20 TOPSDispositivos alvo Hailo-15

Define HW_ARCH no script para corresponder ao teu dispositivo alvo antes de compilar.

Link to this sectionExecutando inferência em hardware Hailo#

Assim que a compilação terminar, copie toda a pasta yolo11n_hailo_model/ (o .hef mais seu metadata.yaml) para o seu dispositivo com tecnologia Hailo e execute a inferência usando a API Python do HailoRT (pacote hailo_platform) ou, no Raspberry Pi, o auxiliar picamera2 Hailo (um wrapper do HailoRT). Ambos são mostrados nas abas abaixo. Manter os dois arquivos juntos permite que os scripts abaixo leiam os nomes das classes a partir do metadata.yaml ao lado do HEF. Ao contrário das etapas de exportação do DFC, a inferência é executada diretamente no dispositivo de borda.

Nota

O código de inferência abaixo corre no dispositivo com tecnologia Hailo (por exemplo, Raspberry Pi + AI Kit), não na máquina x86 usada para compilação.

Link to this sectionPasso 1: Instalar o HailoRT no dispositivo#

No dispositivo alvo, instala o HailoRT e as bindings Python. Para utilizadores do Raspberry Pi AI Kit e AI HAT+, o guia oficial de software Raspberry Pi AI instala o HailoRT, o controlador do dispositivo e as bindings Python com:

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

Para dispositivos Hailo que não sejam Raspberry Pi, instala o pacote HailoRT que corresponda ao teu dispositivo, controlador e versão do SDK a partir da Hailo Developer Zone.

Os dispositivos AI HAT+ 2 usam um pacote diferente do Raspberry Pi (hailo-h10-all) e um fluxo de trabalho Hailo-10H. Segue o guia de software Raspberry Pi AI para essa geração de hardware.

Link to this sectionPasso 2: Verificação rápida de sanidade#

Antes de executar a inferência Python, confirma se o dispositivo Hailo é reconhecido:

hailortcli fw-control identify

Deverás ver o tipo de dispositivo, a versão do firmware e o número de série impressos.

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 sectionPasso 3: Executar inferência#

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.

O caminho HailoRT nativo do fornecedor é executado em qualquer plataforma com um dispositivo Hailo e não precisa de dependências extras. Passe para --source um caminho de imagem, um caminho de vídeo, um índice de webcam (por exemplo, 0) para captura USB/V4L2 ao vivo, ou csi para o Módulo de Câmera do Raspberry Pi. A opção CSI requer que o picamera2 esteja instalado, uma vez que o Raspberry Pi OS moderno roteia a câmera através do libcamera em vez de um dispositivo V4L2 simples.

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

Execute-o contra qualquer fonte (imagens salvam output.jpg, vídeos salvam output.mp4, fluxos ao vivo são exibidos em uma janela, pressione q para sair):

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
Dica

O formato de saída da deteção assume que o HEF foi compilado com nms_postprocess no script .alls. Se compilaste sem NMS, as saídas brutas são os 6 tensores de cabeçalho de deteção e deves executar o NMS na tua aplicação separadamente.

Link to this sectionInferência de vídeo com TAPPAS#

Para pipelines de vídeo de alto débito, o TAPPAS fornece elementos GStreamer que transmitem vídeo através do chip Hailo em tempo real:

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

Consulta a documentação do TAPPAS para opções completas de configuração de pipeline.

Link to this sectionResumo#

Este guia cobriu o fluxo de trabalho completo para exportar modelos de deteção Ultralytics YOLO para o formato Hailo HEF:

  1. Exportar para ONNX com Ultralytics (model.export(format="onnx")).
  2. Analisar o modelo ONNX com o Hailo DFC e especificar os nós finais do cabeçalho de deteção.
  3. Configurar a normalização e o NMS através de um script de modelo.
  4. Quantizar com um conjunto de dados de calibração (COCO128 via Ultralytics).
  5. Compilar para um ficheiro .hef pronto para Hailo-8, Hailo-8L ou Hailo-15.

Para mais detalhes, veja a Hailo Developer Zone e a documentação da Hailo. Para outros destinos de exportação do Ultralytics, veja os guias relacionados de ONNX, OpenVINO, TensorRT, NCNN, TFLite Edge TPU, RKNN, Sony IMX500 e Qualcomm QNN. Para comparar a velocidade e a precisão do modelo exportado entre formatos, use o modo Benchmark. Para a lista completa de formatos e opções, visite a documentação do modo Export e a página do guia de integrações.

Link to this sectionFAQ#

Link to this sectionQue dispositivos Hailo são suportados?#

O Hailo DFC suporta Hailo-8 (hailo8), Hailo-8L (hailo8l) e Hailo-15H (hailo15h). Consulta a tabela Arquiteturas de Hardware Suportadas para o valor de HW_ARCH correspondente.

Link to this sectionQuais modelos Ultralytics podem ser exportados?#

Este guia foca-se em modelos de deteção. Consulta Tarefas Suportadas para o âmbito ao nível da tarefa, Notas de Compatibilidade para limites de compatibilidade de modelos e Modelos Suportados e Nós Finais para exemplos de nós finais YOLO11 e YOLOv8.

Link to this sectionPorque é que o script do modelo usa meta_arch=yolov8 para o YOLO11?#

O YOLO11 usa a mesma arquitetura de cabeçalho de deteção desacoplada que o YOLOv8. O Hailo DFC usa meta_arch=yolov8 para a configuração NMS para ambas as famílias de modelos.

Link to this sectionPreciso de um GPU para o passo de otimização?#

Um GPU é fortemente recomendado para o ajuste fino consciente da quantização em runner.optimize(). Sem um, o processo ainda funciona, mas é significativamente mais lento (várias horas contra cerca de 10-20 minutos com um GPU).

Link to this sectionComo encontro os nós finais corretos para o meu modelo?#

Executa runner.translate_onnx_model(...) sem especificar end_node_names e, em seguida, usa os nós de cabeçalho de deteção sugeridos impressos pelo DFC. Consulta Outras Arquiteturas para o exemplo de comando.

Link to this sectionOnde posso obter o SDK Hailo DFC?#

O Python wheel do SDK Hailo DFC está disponível na Hailo Developer Zone. Para um exportador Ultralytics Hailo direto, o script do modelo e a configuração de pós-processamento devem ser gerados ou selecionados dentro do fluxo de trabalho de exportação.

Comentários