Link to this sectionEntender la detección de extremo a extremo en Ultralytics YOLO26#
Link to this sectionIntroducción#
Si vas a actualizar a YOLO26 desde un modelo anterior como YOLOv8 o YOLO11, uno de los cambios más importantes que notarás es la eliminación de la supresión de no máximos (NMS). Los modelos YOLO tradicionales producen miles de predicciones solapadas que requieren un paso de postprocesamiento de NMS independiente para filtrarlas y llegar a las detecciones finales. Esto añade latencia, complica los grafos de exportación y puede comportarse de forma inconsistente en distintas 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á activado por defecto en todos los modelos YOLO26. El resultado es un pipeline de despliegue más sencillo, menor latencia y una inferencia hasta un 43% más rápida en CPUs.
Esta guía te explica qué ha cambiado, si necesitas actualizar tu código, qué formatos de exportación admiten la inferencia de extremo a extremo y cómo migrar sin problemas desde modelos YOLO más antiguos.
Para ver más a fondo la motivación detrás de este cambio arquitectónico, consulta la entrada del blog de Ultralytics sobre por qué YOLO26 elimina la NMS.
- ¿Usas la API o CLI de Ultralytics? No necesitas realizar 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 formatoxyxy, sin necesidad de NMS. Otras tareas añaden datos extra (coeficientes de máscara, puntos clave o ángulo). - ¿Vas a exportar? 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, Edge TPU y QNN) recurren automáticamente a la salida tradicional debido a las restricciones de los operadores no soportados (por ejemplo,
torch.topk). Los flujos de trabajo de Hailo HEF se compilan desde ONNX con scripts específicos de Hailo, así que verifica la cabecera de detección y la configuración de NMS para tu modelo.
Link to this sectionCómo funciona la detección de extremo a extremo#
YOLO26 utiliza una arquitectura de doble cabecera durante el entrenamiento. Ambas cabeceras comparten el mismo backbone y cuello, pero producen salidas de formas diferentes:
| Cabecera | Propósito | Salida de detección | Postprocesamiento |
|---|---|---|---|
| Uno a uno (predeterminado) | Inferencia de extremo a extremo | (N, 300, 6) | Solo umbral de confianza |
| Uno a muchos | Salida 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:
| Tarea | Salida de extremo a extremo | Datos extra |
|---|---|---|
| Detección | (N, 300, 6) | — |
| Segmentación de instancias | (N, 300, 6 + nm) + proto (N, nm, H, W) | nm coeficientes de máscara (predeterminado 32) |
| Pose | (N, 300, 57) | 17 puntos clave × 3 (x, y, visibilidad) |
| OBB | (N, 300, 7) | Ángulo de rotación |
During training, both heads run simultaneously — the one-to-many head provides a richer learning signal, while the one-to-one head learns to produce clean, non-overlapping predictions. During inference and export, only the one-to-one head is active by default, producing up to 300 detections per image in the format [x1, y1, x2, y2, confidence, class_id].
Cuando llamas a model.fuse(), se pliegan las capas Conv + BatchNorm para una inferencia más rápida y, en los modelos de extremo a extremo, también se elimina la cabecera uno a muchos, lo que reduce el tamaño del modelo y los FLOPs. Para más detalles sobre la arquitectura de doble cabecera, consulta la página del modelo YOLO26.
Link to this section¿Necesito cambiar mi código?#
Link to this sectionUso de la API de Python o CLI de Ultralytics#
No se necesitan cambios. Si utilizas la API de Python de Ultralytics o la CLI estándar, todo funciona automáticamente: la predicción, la validación y la exportación gestionan los modelos de extremo a extremo desde el primer momento.
from ultralytics import YOLO
# Load a YOLO26 model
model = YOLO("yolo26n.pt")
# Predict — no NMS step, no code changes
results = model.predict("image.jpg")Link to this sectionUso de 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), necesitarás actualizarla para manejar la nueva forma de salida:
| YOLOv8 / YOLO11 | YOLO26 (extremo a extremo) | |
|---|---|---|
| Salida de detección | (N, nc + 4, 8400) | (N, 300, 6) |
| Formato de caja | xywh (x central, y central, ancho, alto) | xyxy (x superior izquierda, y superior izquierda, x inferior derecha, y inferior derecha) |
| Disposición | Coordenadas de caja + puntuaciones de clase por ancla | [x1, y1, x2, y2, conf, class_id] |
| NMS necesaria | Sí | No |
| Postprocesamiento | NMS + filtro de confianza | Solo filtro de confianza |
Para las 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 del 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!Link to this sectionCambiar a la cabecera uno a muchos#
Si necesitas el formato de salida YOLO tradicional (por ejemplo, para reutilizar código de postprocesamiento basado en NMS existente), puedes cambiar a la cabecera uno a muchos en cualquier momento estableciendo end2end=False:
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)Link to this sectionCompatibilidad de formatos de exportación#
La mayoría de los formatos de exportación admiten la inferencia de extremo a extremo desde el primer momento, incluidos ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js y MNN.
Los siguientes formatos no admiten el extremo a extremo y recurren automáticamente a la cabecera uno a muchos: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU y Qualcomm QNN.
Para Hailo HEF, el paso de compilación ocurre fuera de model.export(format=...) tras una exportación ONNX. Utiliza los registros de Hailo DFC, el script de modelo .alls y el JSON de NMS que coincidan exactamente con tu modelo de detección; si tu cadena de herramientas de Hailo no admite un grafo YOLO26 de extremo a extremo, exporta el modelo ONNX con end2end=False y compila la cabecera de detección tradicional.
TensorRT admite el extremo a extremo, pero se desactiva automáticamente al exportar con int8=True en TensorRT ≤10.3.0.
Link to this sectionCompensaciones entre precisión y velocidad#
La detección de extremo a extremo proporciona importantes ventajas de despliegue con un impacto mínimo en la precisión:
| Métrica | Extremo a extremo (predeterminado) | Uno a muchos + NMS (end2end=False) |
|---|---|---|
| Velocidad de inferencia en CPU | Hasta un 43% más rápida | Línea base |
| Impacto en mAP | ~0.5 mAP menor | Iguala o supera a YOLO11 |
| Postprocesamiento | Solo filtro de confianza | Pipeline NMS completo |
| Complejidad de despliegue | Mínima | Requiere implementación de NMS |
Para la mayoría de las aplicaciones del mundo real, la diferencia de ~0.5 mAP es insignificante, especialmente si se consideran las ganancias en velocidad y simplicidad. Si la precisión máxima es tu máxima prioridad, siempre puedes volver a la cabecera uno a muchos usando end2end=False.
Consulta las métricas de rendimiento de YOLO26 para ver benchmarks detallados en todos los tamaños de modelo (n, s, m, l, x).
Link to this sectionMigración desde YOLOv8 o YOLO11#
Si vas a actualizar un proyecto existente a YOLO26, aquí tienes una lista de comprobación rápida para garantizar una transición fluida:
- Usuarios de la API / CLI de Ultralytics: No se necesitan cambios; simplemente actualiza el nombre del modelo a
yolo26n.pt(oyolo26n-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 datos específicos de la tarea para segmentación, pose y OBB. Ten en cuenta también el cambio de formato de caja dexywhaxyxy - Pipelines de exportación: Revisa 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 contar con soporte end-to-end
- Exportaciones FP16: Si necesitas todas las salidas en FP16, realiza la exportación con
end2end=False— consulta por qué output0 permanece en FP32 - iOS / CoreML: El modo end-to-end es totalmente compatible. Si necesitas soporte para Xcode Preview, utiliza
end2end=Falseconnms=True - Dispositivos Edge (NCNN, RKNN): Estos formatos recurren automáticamente a one-to-many, así que incluye NMS en tu pipeline en el dispositivo
Link to this sectionPreguntas frecuentes#
Link to this section¿Puedo usar end2end=True y nms=True a la vez?#
No. Estas opciones son mutuamente excluyentes. Si estableces nms=True en un modelo end-to-end durante la exportación, se cambiará automáticamente a nms=False mostrando una advertencia. La cabecera end-to-end 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: integra el NMS tradicional en el grafo de exportación. Esto puede ser útil para exportaciones a CoreML porque permite usar la función Preview en Xcode directamente con el modelo de detección.
Link to this section¿Qué controla el parámetro max_det en los modelos end-to-end?#
El parámetro max_det (por defecto: 300) establece el número máximo de detecciones que la cabecera one-to-one puede devolver 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 scenesTen en cuenta que los checkpoints predeterminados de YOLO26 se entrenaron con max_det=300. Aunque puedes aumentar este valor, la cabecera one-to-one se optimizó durante el entrenamiento para producir hasta 300 detecciones limpias, por lo que las detecciones que superen ese límite podrían tener una menor calidad. Si necesitas más de 300 detecciones por imagen, considera volver a entrenar con un valor de max_det superior.
Link to this sectionMi modelo ONNX exportado arroja (1, 300, 6) — ¿es correcto?#
Sí, ese es el formato de salida esperado end-to-end para detección: batch size de 1, hasta 300 detecciones, cada una con 6 valores [x1, y1, x2, y2, confidence, class_id]. Simplemente filtra según el umbral de confianza y listo; no necesitas NMS.
Para otras tareas, la forma de la salida es diferente:
| Tarea | Forma de la salida | Descripció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 |
Link to this section¿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:
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 enabledAlternativamente, verifica la forma de la salida: los modelos de detección end-to-end generan (1, 300, 6), mientras que los tradicionales generan (1, nc + 4, 8400). Para ver las formas de otras tareas, consulta las preguntas frecuentes sobre formas de salida.
Link to this section¿Es compatible end-to-end con tareas de segmentación de instancias, pose y OBB?#
Sí. Las variantes de tareas estilo detección de YOLO26 — detección, segmentación de instancias, estimación de pose y detección de objetos orientados (OBB) — soportan inferencia end-to-end por defecto. La alternativa end2end=False también está disponible para estas tareas.
Cada tarea extiende la salida de detección base con datos específicos de la tarea:
| Tarea | Modelo | Salida de extremo a extremo |
|---|---|---|
| Detección | yolo26n.pt | (N, 300, 6) |
| Segmentación de instancias | yolo26n-seg.pt | (N, 300, 38) + proto (N, 32, 160, 160) |
| Pose | yolo26n-pose.pt | (N, 300, 57) |
| OBB | yolo26n-obb.pt | (N, 300, 7) |