Meet YOLO26: next-gen vision AI.

Link to this sectionComprendre la détection de bout en bout dans Ultralytics YOLO26#

Link to this sectionIntroduction#

Si tu passes à YOLO26 depuis un modèle plus ancien comme YOLOv8 ou YOLO11, l'un des changements les plus importants que tu remarqueras est la suppression de la Non-Maximum Suppression (NMS). Les modèles YOLO traditionnels produisent des milliers de prédictions qui se chevauchent, nécessitant une étape de post-traitement NMS séparée pour filtrer les détections finales. Cela ajoute de la latence, complique les graphes d'exportation et peut se comporter de manière incohérente selon les plateformes matérielles.

YOLO26 adopte une approche différente. Il génère les détections finales directement depuis le modèle, sans nécessiter de filtrage externe. C'est ce qu'on appelle la détection d'objet de bout en bout, et elle est activée par défaut dans tous les modèles YOLO26. Le résultat est un pipeline de déploiement plus simple, une latence réduite et une inférence jusqu'à 43 % plus rapide sur CPU.

Ce guide t'explique ce qui a changé, si tu dois mettre à jour ton code, quels formats d'exportation prennent en charge l'inférence de bout en bout, et comment migrer en douceur depuis les anciens modèles YOLO.

Pour un aperçu approfondi de la motivation derrière ce changement architectural, consulte l'article de blog d'Ultralytics sur les raisons pour lesquelles YOLO26 supprime NMS.

Résumé rapide
  • Tu utilises l'API ou la CLI Ultralytics ? Aucun changement nécessaire, remplace simplement le nom de ton modèle par yolo26n.pt.
  • Tu utilises un code d'inférence personnalisé (ONNX Runtime, TensorRT, etc.) ? Mets à jour ton post-traitement : la sortie de détection est désormais (N, 300, 6) au format xyxy, sans NMS requis. Les autres tâches ajoutent des données supplémentaires (coefficients de masque, keypoints ou angle).
  • Tu exportes ? La plupart des formats prennent en charge la sortie de bout en bout nativement. Cependant, quelques formats (NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU et QNN) reviennent automatiquement à la sortie traditionnelle en raison de contraintes liées aux opérateurs non pris en charge (par exemple, torch.topk). Les workflows Hailo HEF sont compilés à partir d'ONNX avec des scripts spécifiques à Hailo ; vérifie donc la tête de détection et la configuration NMS pour ton modèle.

Link to this sectionComment fonctionne la détection de bout en bout#

YOLO26 utilise une architecture à double tête pendant l'entraînement. Les deux têtes partagent la même backbone et le même neck, mais produisent des sorties de manières différentes :

TêteObjectifSortie de détectionPost-traitement
One-to-One (par défaut)Inférence de bout en bout(N, 300, 6)Seuil de confiance uniquement
One-to-ManySortie YOLO traditionnelle(N, nc + 4, 8400)Requiert NMS

Les formes ci-dessus concernent la détection. D'autres tâches étendent la sortie one-to-one avec des données supplémentaires par détection :

TâcheSortie de bout en boutDonnées supplémentaires
Détection(N, 300, 6)
Segmentation d'instance(N, 300, 6 + nm) + proto (N, nm, H, W)Coefficients de masque nm (32 par défaut)
Pose(N, 300, 57)17 keypoints × 3 (x, y, visibilité)
OBB(N, 300, 7)Angle de rotation

Pendant l'entraînement, les deux têtes fonctionnent simultanément : la tête one-to-many fournit un signal d'apprentissage plus riche, tandis que la tête one-to-one apprend à produire des prédictions propres, sans chevauchement. Pendant l'inférence et l'exportation, seule la tête one-to-one est active par défaut, produisant jusqu'à 300 détections par image au format [x1, y1, x2, y2, confidence, class_id].

Lorsque tu appelles model.fuse(), cela fusionne les couches Conv + BatchNorm pour une inférence plus rapide et, sur les modèles de bout en bout, supprime également la tête one-to-many, réduisant ainsi la taille du modèle et les FLOPs. Pour plus de détails sur l'architecture à double tête, consulte la page du modèle YOLO26.

Link to this sectionDois-je modifier mon code ?#

Link to this sectionUtilisation de l'API Python ou de la CLI Ultralytics#

Aucun changement nécessaire. Si tu utilises l'API Python Ultralytics standard ou la CLI, tout fonctionne automatiquement : la prédiction, la validation et l'exportation gèrent nativement les modèles de bout en bout.

Aucun changement de code requis avec l'API 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")

Link to this sectionUtilisation de code d'inférence personnalisé#

Oui, le format de sortie est différent. Si tu as écrit une logique de post-traitement personnalisée pour YOLOv8 ou YOLO11 (par exemple, lors de l'exécution d'une inférence avec ONNX Runtime ou TensorRT), tu devras la mettre à jour pour gérer la nouvelle forme de sortie :

YOLOv8 / YOLO11YOLO26 (bout en bout)
Sortie de détection(N, nc + 4, 8400)(N, 300, 6)
Format de boîtexywh (centre x, centre y, largeur, hauteur)xyxy (x haut-gauche, y haut-gauche, x bas-droite, y bas-droite)
DispositionCoordonnées des boîtes + scores de classe par ancre[x1, y1, x2, y2, conf, class_id]
NMS requisOuiNon
Post-traitementNMS + filtre de confianceFiltre de confiance uniquement

Pour les tâches de segmentation, de pose et d'OBB, YOLO26 ajoute des données spécifiques à la tâche à chaque détection ; consulte le tableau des formes de sortie ci-dessus.

N est la taille du lot et nc le nombre de classes (par ex. 80 pour COCO).

Avec les modèles de bout en bout, le post-traitement devient beaucoup plus simple, par exemple lors de l'utilisation d'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 sectionBasculer vers la tête One-to-Many#

Si tu as besoin du format de sortie YOLO traditionnel (par exemple, pour réutiliser un code de post-traitement basé sur NMS existant), tu peux basculer vers la tête one-to-many à tout moment en réglant end2end=False :

Utiliser la tête one-to-many pour une sortie traditionnelle basée sur 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)

Link to this sectionCompatibilité des formats d'exportation#

La plupart des formats d'exportation prennent en charge l'inférence de bout en bout nativement, y compris ONNX, TensorRT, CoreML, OpenVINO, TFLite, TF.js et MNN.

Les formats suivants ne prennent pas en charge le bout en bout et reviennent automatiquement à la tête one-to-many : NCNN, RKNN, PaddlePaddle, ExecuTorch, IMX, Edge TPU et Qualcomm QNN.

Que se passe-t-il lorsque le bout en bout n'est pas pris en charge

Lorsque tu exportes vers l'un de ces formats, Ultralytics bascule automatiquement vers la tête one-to-many et enregistre un avertissement ; aucune intervention manuelle n'est nécessaire. Cela signifie que tu auras besoin de NMS dans ton pipeline d'inférence pour ces formats, tout comme avec YOLOv8 ou YOLO11.

Pour Hailo HEF, l'étape de compilation se déroule en dehors de model.export(format=...) après une exportation ONNX. Utilise les logs Hailo DFC, le script de modèle .alls et le JSON NMS correspondant exactement à ton modèle de détection ; si un graphe YOLO26 de bout en bout n'est pas pris en charge par ta chaîne d'outils Hailo, exporte le modèle ONNX avec end2end=False et compile la tête de détection traditionnelle.

TensorRT + INT8

TensorRT prend en charge le bout en bout, mais il est automatiquement désactivé lors de l'exportation avec int8=True sur TensorRT ≤10.3.0.

Link to this sectionCompromis entre précision et vitesse#

La détection de bout en bout offre des avantages de déploiement significatifs avec un impact minimal sur la précision :

MétriqueBout en bout (par défaut)One-to-Many + NMS (end2end=False)
Vitesse d'inférence CPUJusqu'à 43 % plus rapideBaseline
Impact mAP~0.5 mAP de moinsÉgal ou supérieur à YOLO11
Post-traitementFiltre de confiance uniquementPipeline NMS complet
Complexité de déploiementMinimaleRequiert une implémentation NMS

Pour la plupart des applications réelles, la différence de ~0,5 mAP est négligeable, surtout compte tenu des gains de vitesse et de simplicité. Si la précision maximale est ta priorité absolue, tu peux toujours revenir à la tête one-to-many en utilisant end2end=False.

Consulte les métriques de performance YOLO26 pour des benchmarks détaillés sur toutes les tailles de modèles (n, s, m, l, x).

Link to this sectionMigration depuis YOLOv8 ou YOLO11#

Si tu mets à jour un projet existant vers YOLO26, voici une liste de contrôle rapide pour assurer une transition en douceur :

  • Utilisateurs de l'API / CLI Ultralytics : Aucun changement nécessaire, mets juste à jour le nom du modèle par yolo26n.pt (ou yolo26n-seg.pt, yolo26n-pose.pt, yolo26n-obb.pt)
  • Code de post-traitement personnalisé : Mets-le à jour pour gérer les nouvelles formes de sortie : (N, 300, 6) pour la détection, plus les données spécifiques à la tâche pour la segmentation, la pose et l'OBB. Note également le changement de format de boîte de xywh à xyxy
  • Pipelines d'exportation : Vérifie la section compatibilité des formats ci-dessus pour ton format cible
  • TensorRT + INT8 : Vérifie que ta version de TensorRT est supérieure à 10.3.0 pour une prise en charge complète.
  • Exportations FP16 : Si tu as besoin de toutes les sorties en FP16, exporte avec end2end=False — vois pourquoi output0 reste en FP32.
  • iOS / CoreML : La solution end-to-end est entièrement prise en charge. Si tu as besoin du support pour Xcode Preview, utilise end2end=False avec nms=True.
  • Appareils Edge (NCNN, RKNN) : Ces formats reviennent automatiquement au mode one-to-many, donc inclus le NMS dans ton pipeline sur l'appareil.

Link to this sectionFAQ#

Link to this sectionPuis-je utiliser end2end=True et nms=True ensemble ?#

Non. Ces options sont mutuellement exclusives. Si tu définis nms=True sur un modèle end-to-end lors de l'exportation, il sera automatiquement forcé à nms=False avec un avertissement. La tête end-to-end gère déjà le filtrage des doublons en interne, donc un NMS externe est inutile.

Cependant, end2end=False combiné avec nms=True est une configuration valide — cela intègre le NMS traditionnel dans le graphe d'exportation. Cela peut être utile pour les exportations CoreML car cela te permet d'utiliser la fonction Preview dans Xcode directement avec le modèle de détection.

Link to this sectionQue contrôle le paramètre max_det dans les modèles end-to-end ?#

Le paramètre max_det (par défaut : 300) définit le nombre maximal de détections que la tête one-to-one peut générer par image. Tu peux l'ajuster au moment de l'inférence ou de l'exportation :

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

Note que les points de contrôle par défaut de YOLO26 ont été entraînés avec max_det=300. Bien que tu puisses augmenter cette valeur, la tête one-to-one a été optimisée pendant l'entraînement pour produire jusqu'à 300 détections propres, donc les détections au-delà de cette limite pourraient être de moindre qualité. Si tu as besoin de plus de 300 détections par image, envisage un réentraînement avec une valeur max_det plus élevée.

Link to this sectionMon modèle ONNX exporté sort du (1, 300, 6) — est-ce correct ?#

Oui, c'est le format de sortie end-to-end attendu pour la détection : une taille de lot de 1, jusqu'à 300 détections, chacune avec 6 valeurs [x1, y1, x2, y2, confidence, class_id]. Il suffit de filtrer par seuil de confiance et c'est tout — pas besoin de NMS.

Pour d'autres tâches, la forme de la sortie diffère :

TâcheForme de sortieDescription
Détection(1, 300, 6)[x1, y1, x2, y2, conf, class_id]
Segmentation(1, 300, 38) + (1, 32, 160, 160)6 valeurs de boîte + 32 coefficients de masque, plus un tenseur de masque prototype
Pose(1, 300, 57)6 valeurs de boîte + 17 points clés × 3 (x, y, visibilité)
OBB(1, 300, 7)6 valeurs de boîte + 1 angle de rotation

Link to this sectionComment vérifier si mon modèle exporté est end-to-end ?#

Tu peux le vérifier en utilisant l'API Python d'Ultralytics ou en inspectant directement les métadonnées du modèle ONNX exporté :

Vérifier si un modèle est 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

Alternativement, vérifie la forme de la sortie — les modèles de détection end-to-end sortent du (1, 300, 6), tandis que les modèles traditionnels sortent du (1, nc + 4, 8400). Pour les formes d'autres tâches, consulte la FAQ sur les formes de sortie.

Link to this sectionL'end-to-end est-il pris en charge pour les tâches de segmentation d'instance, pose et OBB ?#

Oui. Les variantes de tâches de style détection de YOLO26 — détection, segmentation d'instance, estimation de pose et détection d'objet orienté (OBB) — prennent en charge l'inférence end-to-end par défaut. Le recours à end2end=False est également disponible pour ces tâches.

Chaque tâche étend la sortie de détection de base avec des données spécifiques à la tâche :

TâcheModèleSortie de bout en bout
Détectionyolo26n.pt(N, 300, 6)
Segmentation d'instanceyolo26n-seg.pt(N, 300, 38) + proto (N, 32, 160, 160)
Poseyolo26n-pose.pt(N, 300, 57)
OBByolo26n-obb.pt(N, 300, 7)

Commentaires