ONNX

ONNX es un formato de grafo portable. LibreYOLO traza el modelo con torch.onnx.export, opcionalmente simplifica el grafo y escribe la familia, la tarea, los nombres de clase y el tamaño de entrada en los metadatos del propio archivo, de modo que cualquier backend de LibreYOLO pueda reconstruir el postprocesado.

Flag
export(format="onnx")
Escribe
Un archivo .onnx, con los metadatos embebidos en el grafo
Extra
pip install "libreyolo[onnx]"
Se recarga con
LibreYOLO("weights/LibreYOLO9t.onnx")
Formas
Batch dinámico por defecto en Python; excepciones por tarea más abajo
Precisión
FP32, FP16 (half=True), INT8 (int8=True, detección YOLO9)

Instalación

Instalación
pip install "libreyolo[onnx]"

El extra instala onnx, onnxsim y onnxruntime. Con onnx solo basta para escribir el archivo; onnxsim ejecuta la pasada de simplificación y onnxruntime ejecuta el artefacto y realiza la calibración INT8.

Exportación

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Escribe weights/LibreYOLO9t.onnxpath = model.export(format="onnx")print(path)
CLI
libreyolo export --model LibreYOLO9t.pt --format onnx
Argumentos
model.export(    format="onnx",    imgsz=640,        # int, o (alto, ancho)    batch=1,    dynamic=True,     # valor por defecto en Python; en la CLI es False    simplify=True,    # pasa onnxsim sobre el grafo    opset=None,       # None elige 13, o 17 para las familias estilo DETR    half=False,       # pesos y activaciones en FP16    int8=False,       # INT8 QDQ, solo detección YOLO9    data=None,        # data.yaml de calibración, solo INT8    device=None,      # dispositivo de trazado; None usa el del modelo    output_path=None, # None escribe weights/<stem>.onnx)

Sin output_path, el archivo se guarda en weights/ con el stem del checkpoint, añadiendo _fp16 o _int8 cuando se pidió esa precisión.

dynamic es True por defecto en Python y False en la CLI. Cuando está activo, el eje de batch se vuelve simbólico y algunas tareas se abren más: la segmentación semántica abre también el alto y el ancho de la máscara, la restauración con Real-ESRGAN abre los ejes espaciales, y los detectores de dos etapas mantienen dinámicos el alto y el ancho de origen porque su redimensionado ocurre dentro del grafo.

opset se elige por familia cuando se omite. Las familias estilo DETR (detr, deformable_detr, dinodetr, dfine, deim, deimv2, ec, lwdetr, rfdetr, rtdetr, rtdetrv2, rtdetrv4) más deit, midas y moge2 reciben el opset 17, que es donde baja aten::scaled_dot_product. Todo lo demás recibe 13. El matting se eleva a 19 en cualquier caso, porque el decodificador de BiRefNet necesita el operador DeformConv, que ONNX define a partir del opset 19.

simplify=True ejecuta onnxsim y conserva el grafo original si la pasada falla, así que un error de simplificación es un aviso y no un fallo de exportación. En macOS arm64 con onnx 1.22 o más reciente y onnxsim 0.6.5 o más antiguo, la pasada se omite por completo, porque esa combinación puede abortar el proceso de Python.

NMS embebido

Incrustar NMS en el grafo
from libreyolo import LibreYOLO # Solo detección YOLO9, batch 1. dynamic se fuerza a False.LibreYOLO("LibreYOLO9t.pt").export(    format="onnx",    nms=True,    conf=0.25,    iou=0.45,    max_det=300,)
CLI
libreyolo export --model LibreYOLO9t.pt --format onnx --nms \  --conf 0.25 --iou 0.45 --max-det 300

nms=True es solo para detección YOLO9 y requiere batch 1; pedirlo con dynamic=True registra un aviso y desactiva dynamic. El grafo pasa entonces a tener dos salidas: output, con forma (batch, max_det, 6), y raw, el tensor del detector sin decodificar que el propio backend de LibreYOLO usa para que el postprocesado sea idéntico al de la vía PyTorch.

DeepStream

deepstream=True es una opción exclusiva de ONNX. Exporta el grafo en la disposición que espera el parser de NVIDIA DeepStream y escribe dos archivos adjuntos a su lado, config_infer_primary_<stem>.txt y <stem>_labels.txt, para que el artefacto encaje en un pipeline sin configuración escrita a mano.

Es mutuamente excluyente con nms=True, y pedir ambos lanza un ValueError: DeepStream ejecuta la supresión en su propia etapa de clustering. Pasarlo a cualquier formato distinto de ONNX también lanza un error. Consulta DeepStream para la tabla de familias y tareas soportadas y la compilación del parser.

INT8

INT8 con datos de calibración
from libreyolo import LibreYOLO LibreYOLO("LibreYOLO9t.pt").export(    format="onnx",    int8=True,    data="coco128.yaml",   # unos cientos de imágenes representativas    fraction=1.0,)

int8=True ejecuta la cuantización estática de ONNX Runtime y escribe un grafo QDQ con entradas y salidas en float32. Solo se cuantizan los nodos Conv y Gemm. Dejar en float32 la decodificación de la cabeza de detección es deliberado: esa concatenación mezcla coordenadas de box a escala de píxel con puntuaciones de clase en el rango de 0 a 1, y una única escala de activación por tensor dominada por la magnitud de los boxes llevaría todas las puntuaciones a cero.

Este flag actualmente aplica solo a detección YOLO9, y cualquier otra cosa lanza NotImplementedError en la comprobación previa. Omitir data recurre a coco8.yaml con un aviso; ocho imágenes no son un conjunto de calibración representativo. Un modelo que ya fue cuantizado en PyTorch sigue una ruta distinta, descrita en Cuantización.

Ejecutar el artefacto

A través de LibreYOLO
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("weights/LibreYOLO9t.onnx")result = model.predict(SAMPLE_IMAGE)print(result.boxes.xyxy[:3])
ONNX Runtime puro
import numpy as npimport onnximport onnxruntime as ort session = ort.InferenceSession(    "weights/LibreYOLO9t.onnx",    providers=["CPUExecutionProvider"],) # En esta vía, el preprocesado y el postprocesado corren de tu cuenta.batch = np.zeros((1, 3, 640, 640), dtype=np.float32)outputs = session.run(None, {session.get_inputs()[0].name: batch})print([out.shape for out in outputs]) # El grafo lleva la familia, la tarea, los nombres de clase y el tamaño de entrada.meta = {p.key: p.value for p in onnx.load("weights/LibreYOLO9t.onnx").metadata_props}print(meta["model_family"], meta["task"], meta["imgsz"])

LibreYOLO() despacha por el sufijo .onnx y devuelve el mismo objeto Results que un checkpoint .pt, porque los nombres de clase, la tarea, el tamaño de entrada y el esquema de pose se escribieron en los metadata_props del grafo en el momento de la exportación. Con device="auto" la sesión toma CUDAExecutionProvider cuando ONNX Runtime lo reporta y recurre a la CPU en caso contrario.

El segundo snippet es para lectores sin LibreYOLO instalado. El preprocesado, la decodificación, el NMS y el reescalado de coordenadas corren de tu cuenta en esa vía; el bloque de metadatos sigue ahí para leerlo.

Restricciones

Los nombres de los tensores de salida son fijos por tarea, y son lo que el consumidor sin metadatos tiene que igualar:

TareaNombres de salida
Detección, cabezas de rejilla y de anchorsoutput
Detección, estilo DETRpred_logits, pred_boxes
Detección, RF-DETRdets, labels
Clasificaciónoutput
Segmentación semánticasemantic_logits
Profundidaddepth
Normales de superficienormal
Bordesedges
Restauraciónrestored
Mattingmatte
Miradayaw_logits, pitch_logits

RF-DETR es también la única familia cuyo tensor de entrada se llama input en lugar de images.

Varias tareas llevan en esta versión un contrato de resolución fija en tiempo de ejecución. Profundidad, normales de superficie y bordes rechazan batch != 1 y fuerzan dynamic=False. El matting fuerza el cuadrado nativo de 1024, porque las tablas de posición relativa del Swin de BiRefNet están ligadas a su resolución. La restauración fuerza un lienzo fijo para todas las familias salvo Real-ESRGAN, cuyo generador es totalmente convolucional.

Un imgsz rectangular funciona para las familias YOLO9, HRNet, NAFNet y Real-ESRGAN. Las familias con contrato de cuadrado fijo (clip, deformable_detr, detr, dinodetr, dfine, deim, deimv2, ec, lwdetr, moge2, rtdetr, rtdetrv2, rtdetrv4, rfdetr, siglip2, ssd) lo rechazan de plano.

Dos combinaciones se rechazan antes del trazado: la segmentación YOLO9, porque YOLO9 es solo detección en LibreYOLO, y la segmentación RTMDet-Ins, cuya decodificación de máscaras con kernels dinámicos no tiene contrato de runtime exportado.

Para la tabla completa de familias y tareas, consulta la matriz de exportación. Para una combinación concreta, pregunta directamente a la librería:

Comprobar una familia y tarea antes de exportar
libreyolo formats --family yolo9 --task detect

Leído de libreyolo/export/onnx.py, libreyolo/export/exporter.py, libreyolo/export/support.py, libreyolo/backends/onnx.py y libreyolo/cli/commands/export.py en la rama dev.