Entender la detección de extremo a extremo en Ultralytics YOLO26

Introducción

Si vas a actualizar a YOLO26 desde un modelo anterior como YOLOv8 o YOLO11, uno de los mayores cambios que notarás es la eliminación de la Supresión no máxima (NMS). Los modelos YOLO tradicionales producen miles de predicciones superpuestas que necesitan un paso de postprocesamiento NMS independiente para filtrar y obtener las detecciones finales. Esto añade latencia, complica los gráficos de exportación y puede comportarse de forma incoherente en diferentes plataformas de hardware.

YOLO26 adopta un enfoque diferente. Genera las detecciones finales directamente desde el modelo, sin necesidad de filtrado externo. Esto se conoce como detección de objetos de extremo a extremo, y está habilitado por defecto en todos los modelos YOLO26. El resultado es un pipeline de despliegue más sencillo, menor latencia y hasta un 43% más de velocidad de inferencia en CPUs.

Esta guía te explica qué ha cambiado, si necesitas actualizar tu código, qué formatos de exportación son compatibles con la inferencia de extremo a extremo y cómo migrar sin problemas desde modelos YOLO antiguos.

Para profundizar en la motivación detrás de este cambio arquitectónico, consulta la entrada del blog de Ultralytics sobre por qué YOLO26 elimina NMS.

Resumen rápido
  • ¿Usas la API o la CLI de Ultralytics? No necesitas hacer cambios, simplemente cambia el nombre de tu modelo a yolo26n.pt.
  • ¿Usas código de inferencia personalizado (ONNX Runtime, TensorRT, etc.)? Actualiza tu postprocesamiento: la salida de detección ahora es (N, 300, 6) en formato xyxy, sin necesidad de NMS. Otras tareas añaden datos extra (coeficientes de máscara, puntos clave o ángulo).
  • ¿Exportando? La mayoría de los formatos admiten la salida de extremo a extremo de forma nativa. Sin embargo, algunos formatos (NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX y Edge TPU) vuelven automáticamente a la salida tradicional debido a limitaciones de operadores no compatibles (por ejemplo, torch.topk).

Cómo funciona la detección de extremo a extremo

YOLO26 utiliza una arquitectura de doble cabezal durante el entrenamiento. Ambos cabezales comparten la misma columna vertebral (backbone) y cuello (neck), pero producen resultados de formas distintas:

CabezalPropósitoSalida de detecciónPostprocesamiento
Uno a uno (por defecto)Inferencia de extremo a extremo(N, 300, 6)Solo umbral de confianza
Uno a muchosSalida YOLO tradicional(N, nc + 4, 8400)Requiere NMS

Las formas anteriores son para la detección. Otras tareas amplían la salida uno a uno con datos adicionales por detección:

TareaSalida de extremo a extremoDatos extra
Detección(N, 300, 6)
Segmentación(N, 300, 6 + nm) + proto (N, nm, H, W)nm coeficientes de máscara (32 por defecto)
Pose(N, 300, 57)17 puntos clave × 3 (x, y, visibilidad)
OBB(N, 300, 7)Ángulo de rotación

Durante el entrenamiento, ambos cabezales funcionan simultáneamente: el cabezal uno a muchos proporciona una señal de aprendizaje más rica, mientras que el cabezal uno a uno aprende a producir predicciones limpias y sin solapamientos. Durante la inferencia y la exportación, solo el cabezal uno a uno está activo por defecto, produciendo hasta 300 detecciones por imagen en el formato [x1, y1, x2, y2, confidence, class_id].

Cuando llamas a model.fuse(), se fusionan las capas Conv + BatchNorm para una inferencia más rápida y, en los modelos de extremo a extremo, también se elimina el cabezal uno a muchos, lo que reduce el tamaño del modelo y los FLOPs. Para obtener más detalles sobre la arquitectura de doble cabezal, consulta la página del modelo YOLO26.

¿Necesito cambiar mi código?

Usando la API de Python o la CLI de Ultralytics

No se necesitan cambios. Si utilizas la API de Python de Ultralytics estándar o la CLI, todo funciona automáticamente: la predicción, la validación y la exportación manejan los modelos de extremo a extremo de forma nativa.

No se requieren cambios de código con la API de Ultralytics
from ultralytics import YOLO

# Load a YOLO26 model
model = YOLO("yolo26n.pt")

# Predict — no NMS step, no code changes
results = model.predict("image.jpg")

Usando código de inferencia personalizado

Sí, el formato de salida es diferente. Si escribiste una lógica de postprocesamiento personalizada para YOLOv8 o YOLO11 (por ejemplo, al ejecutar la inferencia con ONNX Runtime o TensorRT), deberás actualizarla para manejar la nueva forma de salida:

YOLOv8 / YOLO11YOLO26 (extremo a extremo)
Salida de detección(N, nc + 4, 8400)(N, 300, 6)
Formato de cajaxywh (centro x, centro y, ancho, alto)xyxy (arriba a la izquierda x, arriba a la izquierda y, abajo a la derecha x, abajo a la derecha y)
DisposiciónCoordenadas de caja + puntuaciones de clase por ancla[x1, y1, x2, y2, conf, class_id]
NMS requeridoNo
PostprocesamientoNMS + filtro de confianzaSolo filtro de confianza

Para tareas de segmentación, pose y OBB, YOLO26 añade datos específicos de la tarea a cada detección; consulta la tabla de formas de salida anterior.

Donde N es el tamaño de lote y nc es el número de clases (por ejemplo, 80 para COCO).

Con los modelos de extremo a extremo, el postprocesamiento se vuelve mucho más sencillo; por ejemplo, al utilizar ONNX Runtime:

import onnxruntime as ort

# Load and run the exported end-to-end model
session = ort.InferenceSession("yolo26n.onnx")
output = session.run(None, {session.get_inputs()[0].name: input_tensor})

# End-to-end output: (batch, 300, 6) → [x1, y1, x2, y2, confidence, class_id]
detections = output[0][0]  # first image in batch
detections = detections[detections[:, 4] > conf_threshold]  # confidence filter — that's it!

Cambiar al cabezal uno a muchos

Si necesitas el formato de salida YOLO tradicional (por ejemplo, para reutilizar el código de postprocesamiento existente basado en NMS), puedes cambiar al cabezal uno a muchos en cualquier momento estableciendo end2end=False:

Usando el cabezal uno a muchos para una salida tradicional basada en NMS
from ultralytics import YOLO

model = YOLO("yolo26n.pt")

# Prediction with NMS (traditional behavior)
results = model.predict("image.jpg", end2end=False)

# Validation with NMS
metrics = model.val(data="coco.yaml", end2end=False)

# Export without end-to-end
model.export(format="onnx", end2end=False)

Compatibilidad de formatos de exportación

La mayoría de los formatos de exportación admiten la inferencia de extremo a extremo de forma nativa, incluidos ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js y MNN.

Los siguientes formatos no admiten el extremo a extremo y vuelven automáticamente al cabezal uno a muchos: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX y Edge TPU.

Qué ocurre cuando no se admite el extremo a extremo

Al exportar a uno de estos formatos, Ultralytics cambia automáticamente al cabezal uno a muchos y registra una advertencia; no se requiere intervención manual. Esto significa que necesitarás NMS en tu pipeline de inferencia para estos formatos, igual que con YOLOv8 o YOLO11.

TensorRT + INT8

TensorRT admite el extremo a extremo, pero se desactiva automáticamente al exportar con int8=True en TensorRT ≤10.3.0.

Compensaciones entre precisión y velocidad

La detección de extremo a extremo proporciona beneficios significativos en el despliegue con un impacto mínimo en la precisión:

MétricaExtremo a extremo (por defecto)Uno a muchos + NMS (end2end=False)
Velocidad de inferencia en CPUHasta un 43% más rápidaLínea base
Impacto en mAP~0.5 mAP menorIguala o supera a YOLO11
PostprocesamientoSolo filtro de confianzaPipeline NMS completo
Complejidad de despliegueMínimaRequiere implementación de NMS

Para la mayoría de las aplicaciones reales, la diferencia de ~0.5 en mAP es insignificante, especialmente si se consideran las ganancias en velocidad y simplicidad. Si la precisión máxima es tu prioridad, siempre puedes volver al cabezal uno a muchos usando end2end=False.

Consulta las métricas de rendimiento de YOLO26 para obtener evaluaciones detalladas en todos los tamaños de modelo (n, s, m, l, x).

Migrar desde YOLOv8 o YOLO11

Si vas a actualizar un proyecto existente a YOLO26, aquí tienes una lista de comprobación rápida para asegurar una transición fluida:

  • Usuarios de API/CLI de Ultralytics: No se necesitan cambios; simplemente actualiza el nombre del modelo a yolo26n.pt (o yolo26n-seg.pt, yolo26n-pose.pt, yolo26n-obb.pt)
  • Código de postprocesamiento personalizado: Actualízalo para manejar las nuevas formas de salida: (N, 300, 6) para detección, además de los datos específicos de cada tarea para segmentación, pose y OBB. Ten en cuenta también el cambio de formato de caja de xywh a xyxy
  • Pipelines de exportación: Consulta la sección de compatibilidad de formatos anterior para tu formato de destino
  • TensorRT + INT8: Verifica que tu versión de TensorRT sea >10.3.0 para soporte de extremo a extremo
  • Exportaciones FP16: Si necesitas todas las salidas en FP16, exporta con end2end=False; mira por qué output0 permanece en FP32
  • iOS / CoreML: El extremo a extremo es totalmente compatible. Si necesitas soporte para Xcode Preview, usa end2end=False con nms=True
  • Dispositivos Edge (NCNN, RKNN): Estos formatos vuelven automáticamente al modo uno a muchos, por lo que debes incluir NMS en tu pipeline en el dispositivo

Preguntas frecuentes

¿Puedo usar end2end=True y nms=True juntos?

No. Estas opciones son mutuamente excluyentes. Si estableces nms=True en un modelo de extremo a extremo durante la exportación, se forzará automáticamente a nms=False con una advertencia. El cabezal de extremo a extremo ya gestiona el filtrado de duplicados internamente, por lo que el NMS externo es innecesario.

Sin embargo, end2end=False combinado con nms=True es una configuración válida; esto integra el NMS tradicional en el gráfico de exportación. Esto puede ser útil para las exportaciones a CoreML porque te permite usar la función Vista previa en Xcode con el modelo de detección directamente.

¿Qué controla el parámetro max_det en los modelos de extremo a extremo?

El parámetro max_det (por defecto: 300) establece el número máximo de detecciones que el cabezal uno a uno puede emitir por imagen. Puedes ajustarlo durante la inferencia o en el momento de la exportación:

model.predict("image.jpg", max_det=100)  # fewer detections, slightly faster
model.export(format="onnx", max_det=500)  # more detections for dense scenes

Ten en cuenta que los checkpoints predeterminados de YOLO26 se entrenaron con max_det=300. Aunque puedes aumentar este valor, el cabezal uno a uno se optimizó durante el entrenamiento para producir hasta 300 detecciones limpias, por lo que las detecciones que superen ese límite podrían ser de menor calidad. Si necesitas más de 300 detecciones por imagen, considera volver a entrenar con un valor max_det más alto.

Mi modelo ONNX exportado genera (1, 300, 6) — ¿es correcto?

Sí, ese es el formato de salida esperado de extremo a extremo para detección: un tamaño de lote de 1, hasta 300 detecciones, cada una con 6 valores [x1, y1, x2, y2, confidence, class_id]. Simplemente filtra por el umbral de confianza y listo; no se necesita NMS.

Para otras tareas, la forma de salida es diferente:

TareaForma de salidaDescripción
Detección(1, 300, 6)[x1, y1, x2, y2, conf, class_id]
Segmentación(1, 300, 38) + (1, 32, 160, 160)6 valores de caja + 32 coeficientes de máscara, más un tensor de máscara prototipo
Pose(1, 300, 57)6 valores de caja + 17 puntos clave × 3 (x, y, visibilidad)
OBB(1, 300, 7)6 valores de caja + 1 ángulo de rotación

¿Cómo compruebo si mi modelo exportado es end-to-end?

Puedes comprobarlo usando la API de Python de Ultralytics o inspeccionando directamente los metadatos del modelo ONNX exportado:

Comprobar si un modelo es end-to-end
from ultralytics import YOLO

model = YOLO("yolo26n.onnx")
model.predict(verbose=False)  # run predict to setup predictor first
print(model.predictor.model.end2end)  # True if end-to-end is enabled

Alternativamente, comprueba la forma de salida (output shape): los modelos de detección end-to-end generan (1, 300, 6), mientras que los modelos tradicionales generan (1, nc + 4, 8400). Para otras formas de tareas, consulta las preguntas frecuentes sobre formas de salida.

¿Es compatible end-to-end con tareas de segmentación, pose y OBB?

Sí. Todas las variantes de tareas de YOLO26 — detección, segmentación, estimación de pose y detección de objetos orientados (OBB) — admiten inferencia end-to-end por defecto. La opción alternativa end2end=False también está disponible para todas las tareas.

Cada tarea extiende la salida de detección base con datos específicos de la tarea:

TareaModeloSalida de extremo a extremo
Detecciónyolo26n.pt(N, 300, 6)
Segmentaciónyolo26n-seg.pt(N, 300, 38) + proto (N, 32, 160, 160)
Poseyolo26n-pose.pt(N, 300, 57)
OBByolo26n-obb.pt(N, 300, 7)

Comentarios