Ir al contenido

Comprensión de la detección de extremo a extremo en Ultralytics

Introducción

Si vas a actualizar a YOLO26 desde un modelo anterior como YOLOv8 o YOLO11, uno de los cambios más notables es la eliminación de la supresión no máxima (NMS). YOLO tradicionales generan miles de predicciones superpuestas que requieren un paso NMS independiente para filtrarlas hasta obtener las detecciones finales. Esto aumenta la latencia, complica los gráficos de exportación y puede comportarse de forma inconsistente 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 de forma predeterminada en todos los modelos de YOLO26. El resultado es un proceso de implementación más sencillo, una menor latencia y una inferencia hasta un 43 % más rápida en CPU.

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 YOLO anteriores.

Para conocer más a fondo los motivos que han llevado a este cambio arquitectónico, consulta la entradaUltralytics sobre por qué YOLO26 elimina NMS.

Resumen rápido

  • ¿Utilizas la Ultralytics o CLI Ultralytics ? No es necesario realizar ningún cambio: solo tienes que cambiar el nombre del modelo por yolo26n.pt.
  • ¿Utilizas código de inferencia personalizado (ONNX , TensorRT, etc.)? Actualiza tu posprocesamiento: ahora el resultado de la detección es (N, 300, 6) en xyxy formato, sin NMS . Otras tareas añaden datos adicionales (coeficientes de máscara, puntos clave o ángulo).
  • ¿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 y Edge TPU) recurren automáticamente a la salida tradicional debido a restricciones de operadores no compatibles (por ejemplo, torch.topk).

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

YOLO26 utiliza una arquitectura de doble cabeza durante el entrenamiento. Ambas cabezas comparten la misma columna vertebral y el mismo cuello, pero generan resultados de formas diferentes:

HeadPropósitoSalida de detecciónPosprocesamiento
Uno a uno (predeterminado)Inferencia de extremo a extremo(N, 300, 6)Solo umbral de confianza
Uno a muchosYOLO tradicional de YOLO(N, nc + 4, 8400)Requiere NMS

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

TareaResultado de principio a finDatos adicionales
Detección(N, 300, 6)
Segmentación(N, 300, 6 + nm) + proto (N, nm, H, W)nm coeficientes de máscara (por defecto: 32)
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 generar predicciones claras y sin solapamientos. Durante inferencia y export, solo el clase individual está activada de forma predeterminada y genera hasta 300 detecciones por imagen en el formato [x1, y1, x2, y2, confidence, class_id].

Cuando llames model.fuse(), agrupa las capas Conv y BatchNorm para acelerar la inferencia y, en los modelos de extremo a extremo, también elimina la cabeza «uno a muchos», lo que reduce el tamaño del modelo y los FLOP. Para obtener más detalles sobre la arquitectura de doble cabeza, consulta el Página del modelo YOLO26.

¿Tengo que cambiar mi código?

Uso de laPython o CLIPython Ultralytics

No es necesario realizar ningún cambio. Si utilizas la Python estándar Ultralytics Python o CLI, todo funciona automáticamente: la predicción, la validación y la exportación gestionan modelos de extremo a extremo desde el primer momento.

No es necesario modificar el código con la 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")
yolo predict model=yolo26n.pt source=image.jpg

Uso de código de inferencia personalizado

Sí, el formato de salida es diferente. Si has escrito una lógica de posprocesamiento personalizada para YOLOv8 o YOLO11 (por ejemplo, al ejecutar la inferencia con ONNX o TensorRT), tendrás que actualizarlo para que admita la nueva forma de salida:

YOLOv8 YOLO11YOLO26 (de extremo a extremo)
Salida de detección(N, nc + 4, 8400)(N, 300, 6)
Formato de cajaxywh (x central, y central, ancho, alto)xyxy (x superior izquierda, y superior izquierda, x inferior derecha, y inferior derecha)
DiseñoCoordenadas del cuadro + puntuaciones de las clases por punto de referencia[x1, y1, x2, y2, conf, class_id]
NMSNo
PosprocesamientoNMS filtro de confianzaSolo filtro de confianza

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

Dónde 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 posprocesamiento resulta mucho más sencillo; por ejemplo, al utilizar ONNX :

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!

Cambio al cabezal «uno a muchos»

Si necesitas el formato YOLO tradicional YOLO (por ejemplo, para reutilizar código de posprocesamiento NMS ya existente), puedes cambiar al cabezal «uno a muchos» en cualquier momento configurando end2end=False:

Uso del conector «uno a muchos» para la salida NMS tradicional

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)
yolo predict model=yolo26n.pt source=image.jpg end2end=False
yolo val model=yolo26n.pt data=coco.yaml end2end=False
yolo export model=yolo26n.pt 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 predeterminada, incluidos ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js y MNN.

Los siguientes formatos no admiten la relación «de uno a muchos» y pasan automáticamente a la relación «uno a muchos»: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX y Edge TPU.

¿Qué ocurre cuando no se admite el cifrado de extremo a extremo?

Al exportar a uno de estos formatos, Ultralytics cambia Ultralytics al cabezal «uno a muchos» y registra una advertencia, sin que sea necesaria ninguna intervención manual. Esto significa que necesitarás NMS tu canalización de inferencia para estos formatos, al igual que con YOLOv8 o YOLO11.

TensorRT INT8

TensorRT admite el proceso de principio a fin, pero es desactivado automáticamente al exportar con int8=True en TensorRT .3.0.

Comprobación entre precisión y velocidad

La detección de extremo a extremo ofrece importantes ventajas de implementación con un impacto mínimo en la precisión:

MétricaDe extremo a extremo (predeterminado)Uno a muchos + NMSend2end=False)
Velocidad de CPUHasta un 43 % más rápidoLínea de base
mAPaproximadamente 0,5 mAPIguala o supera a YOLO11
PosprocesamientoSolo filtro de confianzaNMS completa de NMS
Complejidad del despliegueMínimoRequiere NMS )

En la mayoría de las aplicaciones prácticas, el valor de ~0,5 mAP La diferencia es insignificante, sobre todo si se tienen en cuenta las ventajas en cuanto a velocidad y simplicidad. Si tu prioridad principal es la máxima precisión, siempre puedes recurrir al cabezal «uno a muchos» utilizando end2end=False.

Consulte las métricas de rendimiento de YOLO26 para ver comparativas detalladas de todos los tamaños de modelo (n, s, m, l, x).

Migración desde YOLOv8 YOLO11

Si vas a actualizar un proyecto existente a YOLO26, aquí tienes una breve lista de comprobación para garantizar una transición fluida:

  • CLI de Ultralytics y CLI de Ultralytics : No es necesario realizar ningún cambio; solo tienes que actualizar el nombre del modelo a yolo26n.pt (o yolo26n-seg.pt, yolo26n-pose.pt, yolo26n-obb.pt)
  • Código de posprocesamiento personalizado: Actualización para gestionar los nuevos formatos de salida — (N, 300, 6) para la detección, además de datos específicos de la tarea para segmentación, pose, y OBB. Fíjate también en el cambio de formato del cuadro de xywh a datos xyxy
  • Canales de exportación: consulta la sección sobre compatibilidad de formatos más arriba para conocer el formato de destino
  • TensorRT INT8: Comprueba que tu TensorRT sea superior a 10.3.0 para disfrutar de compatibilidad completa
  • Exportaciones FP16: Si necesitas que todas las salidas estén en FP16, exporta con end2end=False — véase ¿Por qué output0 sigue siendo FP32?
  • iOS CoreML: Se admite totalmente el proceso de principio a fin. Si necesitas compatibilidad con la vista previa de Xcode, utiliza end2end=False con nms=True
  • Dispositivos periféricos (NCNN, RKNN): Estos formatos pasan automáticamente al modo «uno a muchos», por lo que debes incluir NMS tu flujo de trabajo local.

Preguntas frecuentes

¿Puedo usar «end2end=True» y «nms=True» a la vez?

No. Estas opciones son mutuamente excluyentes. Si configuras nms=True en un modelo integral durante export, se forzará automáticamente a nms=False con una advertencia. El nodo de extremo a extremo ya se encarga internamente del filtrado de duplicados, por lo que no NMS necesario NMS externo.

Sin embargo, end2end=False junto con nms=True es una configuración válida: integra NMS tradicional NMS el gráfico de exportación. Esto puede resultar útil para CoreML exportaciones, ya que permite utilizar la función de vista previa de Xcode directamente con el modelo de detección.

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

El max_det El parámetro (valor predeterminado: 300) establece el número máximo de detecciones que el módulo «one-to-one» puede generar por imagen. Se puede ajustar en el momento de la inferencia o 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 puntos de control predeterminados de YOLO26 se entrenaron con max_det=300. Aunque puedes aumentar este valor, el modelo uno a uno se optimizó durante el entrenamiento para generar hasta 300 detecciones nítidas, por lo que las detecciones que superen ese límite pueden ser de menor calidad. Si necesitas más de 300 detecciones por imagen, considera volver a entrenar el modelo con un valor más alto max_det valor.

Mi ONNX exportado devuelve (1, 300, 6). ¿Es correcto?

Sí, ese es el formato de salida de extremo a extremo previsto para la detección: tamaño de lote de 1 a un máximo de 300 detecciones, cada una con 6 valores [x1, y1, x2, y2, confidence, class_id]. Solo tienes que filtrar por umbral de confianza y listo: no NMS .

En el caso de otras tareas, la estructura de los resultados varía:

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, además de 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 puedo comprobar si mi modelo exportado es de extremo a extremo?

Puedes comprobarlo utilizando laPython Ultralytics o examinando directamente los metadatos ONNX exportado:

Comprueba si un modelo es de extremo a extremo

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
import onnxruntime as ort

session = ort.InferenceSession("yolo26n.onnx")
metadata = session.get_modelmeta().custom_metadata_map
print(metadata.get("end2end"))  # 'True' if end-to-end is enabled

Como alternativa, comprueba la estructura de la salida: los modelos de detección de extremo a extremo generan (1, 300, 6), mientras que los modelos tradicionales generan (1, nc + 4, 8400). Para otras formas de tareas, consulte el Preguntas frecuentes sobre formas de salida.

¿Se admite el enfoque «de extremo a extremo» para las 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 la inferencia de extremo a extremo de forma predeterminada. El end2end=False La opción de reserva también está disponible en todas las tareas.

Cada tarea amplía la salida de detección básica con datos específicos de la tarea:

TareaModeloResultado de principio a fin
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)


📅 Creado hace 0 días ✏️ Actualizado hace 0 días
raimbekovm

Comentarios