Link to this sectionComprendere il rilevamento end-to-end in Ultralytics YOLO26#
Link to this sectionIntroduzione#
Se stai passando a YOLO26 da un modello precedente come YOLOv8 o YOLO11, uno dei cambiamenti più significativi che noterai è la rimozione della Non-Maximum Suppression (NMS). I modelli YOLO tradizionali producono migliaia di previsioni sovrapposte che richiedono un passaggio di post-elaborazione NMS separato per filtrare le rilevazioni finali. Ciò aumenta la latenza, complica i grafi di esportazione e può comportarsi in modo incoerente su diverse piattaforme hardware.
YOLO26 adotta un approccio diverso. Produce le rilevazioni finali direttamente dal modello: non è richiesto alcun filtraggio esterno. Questo è noto come object detection end-to-end ed è abilitato per impostazione predefinita in tutti i modelli YOLO26. Il risultato è una pipeline di distribuzione più semplice, una latenza inferiore e fino al 43% di inferenza più veloce sulle CPU.
Questa guida ti illustra cosa è cambiato, se devi aggiornare il tuo codice, quali formati di esportazione supportano l'inferenza end-to-end e come migrare agevolmente dai vecchi modelli YOLO.
Per uno sguardo più approfondito alla motivazione dietro questo cambiamento architetturale, vedi il post del blog di Ultralytics sul perché YOLO26 rimuove NMS.
- Stai usando l'API o la CLI di Ultralytics? Nessuna modifica necessaria: basta cambiare il nome del tuo modello in
yolo26n.pt. - Stai usando un codice di inferenza personalizzato (ONNX Runtime, TensorRT, ecc.)? Aggiorna la tua post-elaborazione: l'output di rilevamento ora è
(N, 300, 6)in formatoxyxy, senza necessità di NMS. Altri task aggiungono dati extra (coefficienti di maschera, keypoint o angolo). - Stai esportando? La maggior parte dei formati supporta l'output end-to-end nativamente. Tuttavia, alcuni formati (NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU e QNN) tornano automaticamente all'output tradizionale a causa di vincoli degli operatori non supportati (ad esempio
torch.topk). I flussi di lavoro Hailo HEF compilano da ONNX con script specifici per Hailo, quindi verifica la head di rilevamento e la configurazione NMS per il tuo modello.
Link to this sectionCome funziona il rilevamento end-to-end#
YOLO26 utilizza un'architettura a doppia head durante l'addestramento. Entrambe le head condividono lo stesso backbone e neck, ma producono output in modi diversi:
| Head | Scopo | Output di rilevamento | Post-elaborazione |
|---|---|---|---|
| One-to-One (predefinito) | Inferenza end-to-end | (N, 300, 6) | Solo soglia di confidenza |
| One-to-Many | Output YOLO tradizionale | (N, nc + 4, 8400) | Richiede NMS |
Le forme sopra indicate sono per il rilevamento. Altri task estendono l'output one-to-one con dati aggiuntivi per ogni rilevamento:
| Compito | Output end-to-end | Dati extra |
|---|---|---|
| Rilevamento | (N, 300, 6) | — |
| Segmentazione di istanze | (N, 300, 6 + nm) + proto (N, nm, H, W) | Coefficienti di maschera nm (predefinito 32) |
| Pose | (N, 300, 57) | 17 keypoint × 3 (x, y, visibilità) |
| OBB | (N, 300, 7) | Angolo di rotazione |
Durante l'addestramento, entrambe le head funzionano simultaneamente: la head one-to-many fornisce un segnale di apprendimento più ricco, mentre la head one-to-one impara a produrre previsioni pulite e non sovrapposte. Durante l'inferenza e l'esportazione, solo la one-to-one head è attiva per impostazione predefinita, producendo fino a 300 rilevazioni per immagine nel formato [x1, y1, x2, y2, confidence, class_id].
Quando chiami model.fuse(), esso combina i livelli Conv + BatchNorm per un'inferenza più rapida e, nei modelli end-to-end, rimuove anche la head one-to-many, riducendo le dimensioni del modello e i FLOP. Per maggiori dettagli sull'architettura a doppia head, vedi la pagina del modello YOLO26.
Link to this sectionDevo modificare il mio codice?#
Link to this sectionUtilizzo dell'API Python o della CLI di Ultralytics#
Nessuna modifica necessaria. Se utilizzi l'API Python standard di Ultralytics o la CLI, tutto funziona automaticamente: previsione, validazione ed esportazione gestiscono tutti i modelli end-to-end senza configurazioni aggiuntive.
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 sectionUtilizzo di codice di inferenza personalizzato#
Sì, il formato di output è diverso. Se hai scritto una logica di post-elaborazione personalizzata per YOLOv8 o YOLO11 (ad esempio, durante l'esecuzione dell'inferenza con ONNX Runtime o TensorRT), dovrai aggiornarla per gestire la nuova forma di output:
| YOLOv8 / YOLO11 | YOLO26 (end-to-end) | |
|---|---|---|
| Output di rilevamento | (N, nc + 4, 8400) | (N, 300, 6) |
| Formato bbox | xywh (centro x, centro y, larghezza, altezza) | xyxy (x in alto a sinistra, y in alto a sinistra, x in basso a destra, y in basso a destra) |
| Layout | Coordinate box + punteggi di classe per ancoraggio | [x1, y1, x2, y2, conf, class_id] |
| NMS richiesta | Sì | No |
| Post-elaborazione | NMS + filtro di confidenza | Solo filtro di confidenza |
Per i task di segmentazione, pose e OBB, YOLO26 aggiunge dati specifici del task a ogni rilevamento: vedi la tabella delle forme di output qui sopra.
Dove N è la dimensione del batch e nc è il numero di classi (ad esempio 80 per COCO).
Con i modelli end-to-end, la post-elaborazione diventa molto più semplice: ad esempio, quando si utilizza 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 sectionPassaggio alla Head One-to-Many#
Se hai bisogno del formato di output YOLO tradizionale (ad esempio, per riutilizzare il codice di post-elaborazione basato su NMS esistente), puoi passare alla head one-to-many in qualsiasi momento impostando 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 sectionCompatibilità del formato di esportazione#
La maggior parte dei formati di esportazione supporta l'inferenza end-to-end nativamente, inclusi ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js e MNN.
I seguenti formati non supportano end-to-end e tornano automaticamente alla head one-to-many: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU e Qualcomm QNN.
Per Hailo HEF, il passaggio di compilazione avviene al di fuori di model.export(format=...) dopo un'esportazione ONNX. Utilizza i log di Hailo DFC, lo script del modello .alls e il JSON NMS che corrispondono esattamente al tuo modello di rilevamento; se un grafo YOLO26 end-to-end non è supportato dalla tua toolchain Hailo, esporta il modello ONNX con end2end=False e compila la head di rilevamento tradizionale.
TensorRT supporta end-to-end, ma è automaticamente disabilitato quando si esporta con int8=True su TensorRT 10.3.0 su JetPack 6.
Link to this sectionCompromessi tra precisione e velocità#
Il rilevamento end-to-end offre significativi vantaggi di distribuzione con un impatto minimo sull'accuratezza:
| Metrica | End-to-End (predefinito) | One-to-Many + NMS (end2end=False) |
|---|---|---|
| Velocità di inferenza CPU | Fino al 43% più veloce | Baseline |
| Impatto mAP | ~0.5 mAP inferiore | Eguaglia o supera YOLO11 |
| Post-elaborazione | Solo filtro di confidenza | Pipeline NMS completa |
| Complessità di distribuzione | Minima | Richiede implementazione NMS |
Per la maggior parte delle applicazioni reali, la differenza di ~0.5 mAP è trascurabile, specialmente se consideri i guadagni in termini di velocità e semplicità. Se la massima accuratezza è la tua priorità assoluta, puoi sempre tornare alla head one-to-many usando end2end=False.
Vedi le metriche di prestazione di YOLO26 per benchmark dettagliati su tutte le dimensioni dei modelli (n, s, m, l, x).
Link to this sectionMigrazione da YOLOv8 o YOLO11#
Se stai aggiornando un progetto esistente a YOLO26, ecco una lista di controllo rapida per garantire una transizione agevole:
- Utenti API / CLI di Ultralytics: Nessuna modifica necessaria: aggiorna semplicemente il nome del modello in
yolo26n.pt(oyolo26n-seg.pt,yolo26n-pose.pt,yolo26n-obb.pt) - Codice di post-elaborazione personalizzato: Aggiorna per gestire le nuove forme di output:
(N, 300, 6)per il rilevamento, più dati specifici del task per segmentazione, pose e OBB. Nota anche il cambio di formato del box daxywhaxyxy - Pipeline di esportazione: Controlla la sezione sulla compatibilità del formato sopra per il tuo formato di destinazione
- TensorRT + INT8: Su JetPack 6, TensorRT 10.3.0 disabilita automaticamente end-to-end con
int8=True: usa una versione diversa di TensorRT per mantenere end-to-end - Esportazioni FP16: Se hai bisogno di tutti gli output in FP16, esporta con
end2end=False: vedi perché output0 rimane FP32 - iOS / CoreML: End-to-end è completamente supportato. Se hai bisogno del supporto per l'anteprima di Xcode, usa
end2end=Falseconnms=True - Dispositivi edge (NCNN, RKNN): Questi formati tornano automaticamente a one-to-many, quindi includi NMS nella tua pipeline on-device
Link to this sectionFAQ#
Link to this sectionPosso usare end2end=True e nms=True insieme?#
No. Queste opzioni si escludono a vicenda. Se imposti nms=True su un modello end-to-end durante l'esportazione, verrà forzato automaticamente a nms=False con un avviso. La head end-to-end gestisce già internamente il filtraggio dei duplicati, quindi una NMS esterna non è necessaria.
Tuttavia, end2end=False combinato con nms=True è una configurazione valida: incorpora la NMS tradizionale nel grafo di esportazione. Questo può essere utile per le esportazioni CoreML perché ti consente di utilizzare direttamente la funzione di anteprima in Xcode con il modello di rilevamento.
Link to this sectionCosa controlla il parametro max_det nei modelli end-to-end?#
Il parametro max_det (predefinito: 300) imposta il numero massimo di rilevamenti che la head one-to-one può produrre per immagine. Puoi regolarlo al momento dell'inferenza o dell'esportazione:
model.predict("image.jpg", max_det=100) # fewer detections, slightly faster
model.export(format="onnx", max_det=500) # more detections for dense scenesNota che i checkpoint predefiniti di YOLO26 sono stati addestrati con max_det=300. Sebbene tu possa aumentare questo valore, la head one-to-one è stata ottimizzata durante l'addestramento per produrre fino a 300 rilevamenti puliti, quindi i rilevamenti oltre tale limite potrebbero avere una qualità inferiore. Se ti servono più di 300 rilevamenti per immagine, valuta la possibilità di riaddestrare con un valore di max_det più elevato.
Link to this sectionIl mio modello ONNX esportato restituisce (1, 300, 6) — è corretto?#
Sì, è il formato di output end-to-end previsto per il rilevamento: batch size di 1, fino a 300 rilevamenti, ciascuno con 6 valori [x1, y1, x2, y2, confidence, class_id]. Filtra semplicemente in base alla soglia di confidenza e il gioco è fatto: non è necessario alcun NMS.
Per altre attività, la forma dell'output varia:
| Compito | Forma dell'output | Descrizione |
|---|---|---|
| Rilevamento | (1, 300, 6) | [x1, y1, x2, y2, conf, class_id] |
| Segmentazione | (1, 300, 38) + (1, 32, 160, 160) | 6 valori del box + 32 coefficienti di maschera, più un tensore di maschera prototipo |
| Pose | (1, 300, 57) | 6 valori del box + 17 keypoints × 3 (x, y, visibilità) |
| OBB | (1, 300, 7) | 6 valori del box + 1 angolo di rotazione |
Link to this sectionCome posso verificare se il mio modello esportato è end-to-end?#
Puoi verificare utilizzando l'API Python di Ultralytics o ispezionando direttamente i metadati del modello ONNX esportato:
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 enabledIn alternativa, controlla la forma dell'output: i modelli di rilevamento end-to-end restituiscono (1, 300, 6), mentre i modelli tradizionali restituiscono (1, nc + 4, 8400). Per le forme di altre attività, consulta le FAQ sulle forme di output.
Link to this sectionL'end-to-end è supportato per le attività di segmentazione dell'istanza, posa e OBB?#
Sì. Le varianti delle attività in stile rilevamento di YOLO26 — rilevamento, segmentazione dell'istanza, stima della posa e rilevamento di oggetti orientati (OBB) — supportano l'inferenza end-to-end per impostazione predefinita. Anche il fallback end2end=False è disponibile per queste attività.
Ogni attività estende l'output di rilevamento di base con dati specifici dell'attività:
| Compito | Modello | Output end-to-end |
|---|---|---|
| Rilevamento | yolo26n.pt | (N, 300, 6) |
| Segmentazione dell'istanza | 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) |