End-to-End-Erkennung in Ultralytics YOLO26 verstehen#
Wenn du von einem früheren Modell wie YOLOv8 oder YOLO11 auf YOLO26 aktualisierst, wirst du als eine der größten Änderungen bemerken, dass die Non-Maximum Suppression (NMS) wegfällt. Herkömmliche YOLO-Modelle erzeugen Tausende von überlappenden Vorhersagen, die einen separaten NMS-Nachbearbeitungsschritt erfordern, um sie auf die endgültigen Detektionen zu reduzieren. Dies erhöht die Latenz, verkompliziert Exportgraphen und kann sich auf verschiedenen Hardwareplattformen unterschiedlich verhalten.
YOLO26 verfolgt einen anderen Ansatz. Es gibt die endgültigen Detektionen direkt aus dem Modell aus – es ist keine externe Filterung erforderlich. Dies wird als End-to-End-Objekterkennung bezeichnet und ist standardmäßig in allen YOLO26-Modellen aktiviert. Das Ergebnis ist eine einfachere Bereitstellungspipeline, eine geringere Latenz und eine bis zu 43 % schnellere Inferenz auf CPUs.
Dieser Leitfaden führt dich durch die Änderungen, erklärt, ob du deinen Code aktualisieren musst, welche Exportformate die End-to-End-Inferenz unterstützen und wie du problemlos von älteren YOLO-Modellen migrierst.
Einen tieferen Einblick in die Motivation hinter diesem architektonischen Wandel findest du im Blogbeitrag von Ultralytics darüber, warum YOLO26 NMS entfernt.
- Verwendest du die Ultralytics API oder CLI? Es sind keine Änderungen erforderlich – ändere einfach deinen Modellnamen in
yolo26n.pt. - Verwendest du benutzerdefinierten Inferenzcode (ONNX Runtime, TensorRT usw.)? Aktualisiere deine Nachbearbeitung – die Detektionsausgabe ist jetzt
(N, 300, 6)im Formatxyxy, ganz ohne NMS. Andere Aufgaben hängen zusätzliche Daten an (Maskenkoeffizienten, Schlüsselpunkte oder Winkel). - Exportierst du? Die meisten Formate unterstützen die End-to-End-Ausgabe nativ. Einige wenige Formate (NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU und QNN) greifen aufgrund von Einschränkungen nicht unterstützter Operatoren (z. B.
torch.topk) jedoch automatisch auf die traditionelle Ausgabe zurück. Hailo-HEF-Workflows werden aus ONNX mit Hailo-spezifischen Skripten kompiliert. Überprüfe daher den Detektionskopf und die NMS-Konfiguration für dein Modell.
Wie End-to-End-Erkennung funktioniert#
YOLO26 verwendet während des Trainings eine Architektur mit zwei Köpfen. Beide Köpfe teilen sich dasselbe Backbone und denselben Neck, erzeugen die Ausgaben jedoch auf unterschiedliche Weise:
| Kopf | Zweck | Erkennungsausgabe | Nachbearbeitung |
|---|---|---|---|
| One-to-One (Standard) | End-to-End-Inferenz | (N, 300, 6) | Nur Konfidenz-Schwellenwert |
| One-to-Many | Herkömmliche YOLO-Ausgabe | (N, nc + 4, 8400) | Erfordert NMS |
Die obigen Formen gelten für die Detektion. Andere Aufgaben erweitern die 1:1-Ausgabe um zusätzliche Daten pro Detektion:
| Aufgabe | End-to-End-Ausgabe | Zusätzliche Daten |
|---|---|---|
| Detektion | (N, 300, 6) | — |
| Instanzsegmentierung | (N, 300, 6 + nm) + Proto (N, nm, H, W) | nm Maskenkoeffizienten (Standard 32) |
| Pose | (N, 300, 57) | 17 Keypoints × 3 (x, y, Sichtbarkeit) |
| OBB | (N, 300, 7) | Rotationswinkel |
Während des Trainings laufen beide Köpfe gleichzeitig – der 1:viele-Kopf liefert ein reichhaltigeres Lernsignal, während der 1:1-Kopf lernt, saubere, sich nicht überschneidende Vorhersagen zu erzeugen. Während der Inferenz und des Exports ist standardmäßig nur der 1:1-Kopf aktiv, der bis zu 300 Detektionen pro Bild im Format [x1, y1, x2, y2, confidence, class_id] liefert.
Wenn du model.fuse() aufrufst, werden Conv- und BatchNorm-Schichten für eine schnellere Inferenz zusammengelegt, und bei End-to-End-Modellen wird außerdem der 1:viele-Kopf entfernt, wodurch Modellgröße und FLOPs reduziert werden. Weitere Einzelheiten zur Architektur mit zwei Köpfen findest du auf der YOLO26-Modellseite.
Muss ich meinen Code ändern?#
Verwendung der Ultralytics Python API oder CLI#
Keine Änderungen erforderlich. Wenn du die Standard-Ultralytics Python API oder CLI verwendest, funktioniert alles automatisch – Vorhersage, Validierung und Export verarbeiten End-to-End-Modelle von Haus aus.
from ultralytics import YOLO
# Load a YOLO26 model
model = YOLO("yolo26n.pt")
# Predict — no NMS step, no code changes
results = model.predict("image.jpg")Verwendung von benutzerdefiniertem Inferenzcode#
Ja, das Ausgabeformat ist anders. Wenn du benutzerdefinierte Nachbearbeitungslogik für YOLOv8 oder YOLO11 geschrieben hast (z. B. beim Ausführen der Inferenz mit ONNX Runtime oder TensorRT), musst du diese aktualisieren, um die neue Ausgabeform zu verarbeiten:
| YOLOv8 / YOLO11 | YOLO26 (End-to-End) | |
|---|---|---|
| Erkennungsausgabe | (N, nc + 4, 8400) | (N, 300, 6) |
| Box-Format | xywh (Zentrum x, Zentrum y, Breite, Höhe) | xyxy (oben links x, oben links y, unten rechts x, unten rechts y) |
| Layout | Box-Koordinaten + Klassen-Scores pro Anker | [x1, y1, x2, y2, conf, class_id] |
| NMS erforderlich | Ja | Nein |
| Nachbearbeitung | NMS + Konfidenz-Filter | Nur Konfidenz-Filter |
Bei Segmentierungs-, Posen- und OBB-Aufgaben hängt YOLO26 aufgabenspezifische Daten an jede Detektion an – siehe die Tabelle der Ausgabeformen.
Wobei N die Batch-Größe und nc die Anzahl der Klassen ist (z. B. 80 für COCO).
Mit End-to-End-Modellen wird die Nachbearbeitung viel einfacher – zum Beispiel bei der Verwendung von 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!Umschalten auf den One-to-Many-Kopf#
Wenn du das traditionelle YOLO-Ausgabeformat benötigst (z. B. um bestehenden NMS-basierten Nachbearbeitungscode wiederzuverwenden), kannst du zum 1:viele-Kopf wechseln, sofern dieser verfügbar ist, indem du end2end=False einstellst:
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)Kompatibilität der Exportformate#
Die meisten Exportformate unterstützen die End-to-End-Inferenz von Haus aus, darunter ONNX, TensorRT, CoreML, OpenVINO, LiteRT und MNN.
Die folgenden Formate unterstützen End-to-End nicht und greifen automatisch auf den 1:viele-Kopf zurück: NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU und Qualcomm QNN.
Für Hailo HEF findet der Kompilierschritt außerhalb von model.export(format=...) nach einem ONNX-Export statt. Verwende die Hailo-DFC-Protokolle, das .alls-Modellskript und das NMS-JSON, die genau zu deinem Detektionsmodell passen; wenn ein End-to-End-YOLO26-Graph von deiner Hailo-Toolchain nicht unterstützt wird, exportiere das ONNX-Modell mit end2end=False und kompiliere den traditionellen Detektionskopf.
TensorRT unterstützt End-to-End, ist jedoch bei einem Export mit quantize=8 auf TensorRT 10.3.0 unter JetPack 6 automatisch deaktiviert.
Kompromisse bei Genauigkeit und Geschwindigkeit#
End-to-End-Detektion bietet erhebliche Vorteile bei der Bereitstellung bei minimalen Auswirkungen auf die Genauigkeit:
| Metrik | End-to-End (Standard) | 1:viele + NMS (end2end=False) |
|---|---|---|
| CPU-Inferenzgeschwindigkeit | Bis zu 43 % schneller | Basislinie |
| mAP-Auswirkung | ~0,5 mAP niedriger | Entspricht oder übertrifft YOLO11 |
| Nachbearbeitung | Nur Konfidenz-Filter | Vollständige NMS-Pipeline |
| Bereitstellungskomplexität | Minimal | Erfordert NMS-Implementierung |
Für die meisten realen Anwendungen ist der Unterschied von ~0,5 mAP vernachlässigbar, insbesondere wenn man die Geschwindigkeits- und Einfachheitsgewinne berücksichtigt. Wenn maximale Genauigkeit deine oberste Priorität ist, kannst du jederzeit mit end2end=False auf den 1:viele-Kopf zurückgreifen.
Siehe die YOLO26-Leistungsmetriken für detaillierte Benchmarks über alle Modellgrößen hinweg (n, s, m, l, x).
Migration von YOLOv8 oder YOLO11#
Wenn du ein bestehendes Projekt auf YOLO26 aktualisierst, findest du hier eine kurze Checkliste für einen reibungslosen Übergang:
- Benutzer von Ultralytics API / CLI: Keine Änderungen erforderlich – aktualisiere einfach den Modellnamen auf
yolo26n.pt(oderyolo26n-seg.pt,yolo26n-pose.pt,yolo26n-obb.pt) - Benutzerdefinierter Nachbearbeitungscode: Aktualisiere ihn zur Verarbeitung der neuen Ausgabeformen –
(N, 300, 6)für die Detektion sowie aufgabenspezifische Daten für Segmentierung, Pose und OBB. Beachte auch die Änderung des Box-Formats vonxywhzuxyxy - Exportpipelines: Überprüfe den Abschnitt zur Formatkompatibilität für dein Zielformat
- TensorRT + INT8: Unter JetPack 6 deaktiviert TensorRT 10.3.0 End-to-End mit
quantize=8automatisch – verwende eine andere TensorRT-Version, um End-to-End beizubehalten - FP16-Exporte: Wenn du alle Ausgaben in FP16 benötigst, exportiere mit
end2end=False– siehe warum output0 FP32 bleibt - iOS / CoreML: End-to-End wird vollständig unterstützt. Wenn du Xcode-Vorschauunterstützung benötigst, verwende
end2end=Falsemitnms=True - Edge-Geräte (NCNN, RKNN): Diese Formate fallen automatisch auf One-to-Many zurück, also füge NMS in deine On-Device-Pipeline ein
Fazit#
Die End-to-End-Detektion ist in YOLO26 der Standard und erfordert keine Codeänderungen, wenn du die Ultralytics Python API oder CLI verwendest. Lediglich benutzerdefinierte Nachbearbeitungspipelines müssen aktualisiert werden, um die neue (N, 300, 6)-Ausgabe zu lesen und den NMS-Schritt wegzulassen – mit Ausnahme von Exportformaten, die auf die 1:viele-Ausgabe zurückgreifen (wie NCNN und RKNN), welche weiterhin NMS auf dem Gerät erfordern. Detaillierte Geschwindigkeits- und Genauigkeits-Benchmarks über alle Modellgrößen hinweg findest du auf der YOLO26-Modellseite und den vollständigen Satz an Exportoptionen und -formaten in der Dokumentation zum Export-Modus.
FAQ#
Kann ich end2end=True und nms=True zusammen verwenden?#
Nein. Diese Optionen schließen sich gegenseitig aus. Wenn du nms=True bei einem End-to-End-Modell während des Exports einstellst, wird es mit einer Warnung automatisch auf nms=False gezwungen. Der End-to-End-Kopf verarbeitet die Duplikatfilterung bereits intern, sodass ein externer NMS nicht erforderlich ist.
Die Kombination aus end2end=False und nms=True ist jedoch eine gültige Konfiguration – sie integriert traditionelles NMS in den Exportgraphen. Dies kann für CoreML-Exporte nützlich sein, da du dadurch die Vorschaufunktion in Xcode direkt mit dem Detektionsmodell verwenden kannst.
Was steuert der max_det-Parameter in End-to-End-Modellen?#
Der Parameter max_det (Standard: 300) legt die maximale Anzahl der pro Bild zurückgegebenen Detektionen fest. Du kannst ihn zum Zeitpunkt der Inferenz oder des Exports anpassen:
model.predict("image.jpg", max_det=100) # fewer detections
model.export(format="onnx", max_det=500) # more detections for dense scenesBeachte, dass die standardmäßigen YOLO26-Checkpoints mit max_det=300 trainiert wurden. Zwar kannst du diesen Wert erhöhen, jedoch wurde der 1:1-Kopf während des Trainings darauf optimiert, bis zu 300 saubere Detektionen zu erzeugen, sodass Detektionen über dieses Limit hinaus möglicherweise von geringerer Qualität sind. Wenn du mehr als 300 Detektionen pro Bild benötigst, solltest du ein erneutes Training mit einem höheren max_det-Wert in Betracht ziehen.
Mein exportiertes ONNX-Modell gibt (1, 300, 6) aus – ist das korrekt?#
Ja, das ist das erwartete End-to-End-Ausgabeformat für die Detektion: Batch-Größe von 1, bis zu 300 Detektionen, jeweils mit 6 Werten [x1, y1, x2, y2, confidence, class_id]. Einfach nach Konfidenzschwellenwert filtern und fertig – kein NMS erforderlich.
Für andere Aufgaben unterscheidet sich die Ausgabeform:
| Aufgabe | Ausgabeform | Beschreibung |
|---|---|---|
| Detektion | (1, 300, 6) | [x1, y1, x2, y2, conf, class_id] |
| Segmentierung | (1, 300, 38) + (1, 32, 160, 160) | 6 Box-Werte + 32 Masken-Koeffizienten sowie ein Prototyp-Masken-Tensor |
| Pose | (1, 300, 57) | 6 Box-Werte + 17 Keypoints × 3 (x, y, Sichtbarkeit) |
| OBB | (1, 300, 7) | 6 Box-Werte + 1 Rotationswinkel |
Wie prüfe ich, ob mein exportiertes Modell End-to-End ist?#
Du kannst dies entweder über die Ultralytics Python API oder durch direktes Überprüfen der Metadaten des exportierten ONNX-Modells tun:
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 enabledAlternativ kannst du die Ausgabeform überprüfen – End-to-End-Detektionsmodelle geben (1, 300, 6) aus, während traditionelle Modelle (1, nc + 4, 8400) ausgeben. Informationen zu anderen Aufgabenformen findest du in den FAQ zu den Ausgabeformen.
Wird End-to-End für Instanzsegmentierung, Pose- und OBB-Aufgaben unterstützt?#
Ja. YOLO26-Aufgabenvarianten im Detektionsstil – Detektion, Instanzsegmentierung, Posenschätzung und ausgerichtete Objekterkennung (OBB) – unterstützen die End-to-End-Inferenz standardmäßig. Der end2end=False-Fallback ist ebenfalls über diese Aufgaben hinweg verfügbar.
Jede Aufgabe erweitert die Basis-Detektionsausgabe um aufgabenspezifische Daten:
| Aufgabe | Modell | End-to-End-Ausgabe |
|---|---|---|
| Detektion | yolo26n.pt | (N, 300, 6) |
| Instanzsegmentierung | 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) |