📍 Guide principal : Détection d’objets en 2026 : pipeline YOLO v11 + Ultralytics + Roboflow. À faire en amont : Entraîner YOLO v11 et éventuellement fine-tuner.
Un modèle au format PyTorch .pt est parfait pour l’expérimentation et la recherche, beaucoup moins pour la production. PyTorch en inférence garde un overhead Python, supporte mal les optimisations matérielles bas niveau, et entraîne des dépendances lourdes dans le runtime. ONNX et TensorRT règlent le problème : ONNX standardise le format pour qu’on puisse exécuter le modèle sur n’importe quel runtime compatible (ONNX Runtime CPU/GPU, OpenVINO, DirectML, Core ML), et TensorRT compile spécifiquement pour les GPU NVIDIA en exploitant la précision FP16 ou INT8 et la fusion de couches. Sur YOLO v11s, le passage de PyTorch GPU à TensorRT FP16 divise la latence par deux à trois sans perte mesurable de précision.
Prérequis
- Un modèle YOLO v11 entraîné, fichier
.ptà disposition (ex.best.ptissu d’une session de fine-tuning). - Ultralytics installé dans un environnement virtuel actif.
- Pour TensorRT : carte NVIDIA, CUDA 12.x, TensorRT 10.x installé (la version livrée avec JetPack 6 sur Jetson, ou via le SDK NVIDIA sur PC).
- Pour ONNX : le package
onnxetonnxruntime-gpu(ouonnxruntimeCPU). - Niveau attendu : à l’aise avec la chaîne YOLO v11 standard.
- Temps estimé : 20 à 40 minutes selon la taille du modèle et le matériel.
Étape 1 — Choisir le format de cible
Le bon format dépend de la cible matérielle, pas d’une préférence personnelle. ONNX est le format le plus universel et la première étape recommandée systématiquement, parce qu’il sert de pivot pour à peu près toutes les autres conversions. TensorRT est la cible qui maximise la vitesse sur GPU NVIDIA (serveur ou Jetson). OpenVINO cible les CPU Intel et donne souvent des gains de 2x sur les machines sans GPU. CoreML est nécessaire pour iOS et macOS Apple Silicon, TFLite pour Android et microcontrôleurs.
Pour un déploiement serveur classique avec GPU NVIDIA, la chaîne typique est : .pt → ONNX (validation cross-platform) → TensorRT engine (production). Pour un Jetson Orin, idem mais l’engine doit être compilé sur la machine cible parce que TensorRT verrouille l’engine au modèle de GPU exact. Pour un service multi-cloud sans GPU, ONNX Runtime CPU ou OpenVINO suffit.
La table ci-dessous résume les choix selon la cible matérielle. Pour une démarche plus complète, la documentation export d’Ultralytics liste tous les formats supportés avec leurs flags exactes.
| Cible | Format recommandé | Précision |
|---|---|---|
| Serveur GPU NVIDIA | TensorRT | FP16 (par défaut), INT8 si calibration |
| Serveur CPU Intel | OpenVINO | FP16 ou INT8 |
| Jetson Orin / Nano | TensorRT (compilé sur la cible) | FP16 sur Orin, INT8 conseillé sur Nano |
| Navigateur (WebGPU) | ONNX | FP16 |
| Mobile Android | TFLite | FP16 ou INT8 |
| iOS / Apple Silicon | CoreML | FP16 |
Étape 2 — Exporter en ONNX
L’export ONNX d’Ultralytics est le plus fiable et le mieux testé. Il fonctionne sans dépendance native exotique et produit un fichier que vous pouvez inspecter avec Netron pour visualiser le graphe de calcul. Lancez :
from ultralytics import YOLO
model = YOLO("./runs/finetune/finetune-v1/weights/best.pt")
model.export(
format="onnx",
imgsz=640, # taille fixe utilisée à l'inférence
opset=17, # version d'opérateurs ONNX (17+ recommandé en 2026)
simplify=True, # passe d'optimisation onnx-simplifier
dynamic=False, # batch et imgsz fixes pour des perfs stables
half=True # poids en FP16 pour réduire la taille de moitié
)
L’output attendu est un fichier best.onnx placé à côté de best.pt, avec une taille divisée par deux par rapport au .pt. Ultralytics imprime un récap du genre « ONNX: export success, saved as best.onnx (10.2 MB) ». Vérifiez ensuite que le modèle exporté donne les mêmes résultats que l’original sur quelques images de test :
onnx_model = YOLO("./runs/finetune/finetune-v1/weights/best.onnx")
results_onnx = onnx_model("test.jpg")
results_pt = model("test.jpg")
# Comparer manuellement le nombre et les coordonnées des boîtes
Si les boîtes diffèrent significativement (plus de 1-2 % de coordonnées), c’est un signal de bug dans l’export — vérifier la version d’onnxruntime et d’onnx, mettre à jour si nécessaire avec pip install -U onnx onnxruntime.
Étape 3 — Compiler un engine TensorRT
TensorRT prend l’ONNX et le compile en un binaire optimisé spécifiquement pour la carte sur laquelle vous compilez. L’engine produit ne tourne que sur ce modèle de GPU précis ; déplacer un engine d’une RTX 3060 à une T4 demandera une recompilation. C’est un trade-off entre portabilité et vitesse — vous gagnez 2 à 3x en latence, vous payez en flexibilité.
Ultralytics encapsule la compilation TensorRT derrière le même model.export :
from ultralytics import YOLO
model = YOLO("./runs/finetune/finetune-v1/weights/best.pt")
model.export(
format="engine", # alias TensorRT
imgsz=640,
half=True, # FP16 — quasi pas de perte, gain x2
workspace=4, # 4 Go d'espace de travail pour la compilation
dynamic=False,
batch=1
)
La compilation prend 3 à 10 minutes selon la taille du modèle et la puissance du GPU. La sortie liste les couches fusionnées et les optimisations appliquées. À la fin, un fichier best.engine apparaît à côté de best.pt. Ce fichier est le binaire de production à embarquer dans le service d’inférence.
Pour utiliser l’engine immédiatement, Ultralytics charge directement le format .engine via la même API YOLO(), ce qui évite de réécrire du code spécifique TensorRT. La latence d’inférence affichée par yolo predict sur l’engine doit être divisée par 2 ou plus par rapport au .pt de départ.
Étape 4 — Quantification INT8 pour gagner encore en vitesse
FP16 est le compromis par défaut pour la plupart des projets. Pour des cas extrêmes (Jetson Nano, throughput maximal sur T4), INT8 divise encore la latence par 1,5 à 2 et la taille du modèle par deux. Le coût : il faut calibrer le modèle sur un échantillon représentatif d’images, sinon la perte de précision peut atteindre 5 à 10 points de mAP.
Avec Ultralytics et TensorRT, la calibration se fait via le flag int8=True et data qui pointe vers le data.yaml du jeu de validation. TensorRT prend un échantillon d’images, profile les distributions d’activation, puis génère les tables de quantification :
model.export(
format="engine",
imgsz=640,
int8=True,
data="./mon-dataset/data.yaml",
workspace=4
)
La compilation est plus longue (10 à 20 minutes) à cause de la phase de calibration. Validez impérativement la mAP du modèle INT8 avec model.val() sur le jeu de validation. Si la perte est inférieure à 2 points de mAP par rapport au FP16, l’INT8 est viable. Au-delà de 5 points, il vaut mieux rester en FP16 ou agrandir le jeu de calibration.
Étape 5 — Vérifier la fidélité numérique de l’export
Un export réussi en taille de fichier ne garantit pas que les détections sont identiques. Avant de pousser un modèle exporté en production, lancez systématiquement une validation comparée sur le jeu de validation. La métrique parle d’elle-même : si la mAP du .engine est dans une fourchette de ±1 % par rapport au .pt d’origine, l’export est sain. Au-delà, quelque chose s’est dégradé.
from ultralytics import YOLO
# Référence
m_pt = YOLO("./best.pt")
metrics_pt = m_pt.val(data="./mon-dataset/data.yaml")
print("mAP50 .pt:", metrics_pt.box.map50)
# Engine TensorRT
m_engine = YOLO("./best.engine")
metrics_engine = m_engine.val(data="./mon-dataset/data.yaml")
print("mAP50 .engine:", metrics_engine.box.map50)
L’écart attendu est inférieur à 0,5 % en FP16, jusqu’à 2 % en INT8 bien calibré. Au-delà, il y a un problème — généralement une option d’export inadaptée (dynamic shapes mal configurées, opset incompatible, calibration sur trop peu d’images).
Étape 6 — Embarquer l’engine dans un service d’inférence
Une fois l’engine validé, il s’intègre dans le service de la même façon que n’importe quel modèle YOLO. Si le service est en Python, charger l’engine via YOLO("best.engine") et appeler .predict(). Si le service est en C++ pour des raisons de latence ultime, utiliser directement l’API TensorRT C++ et la documentation officielle. Pour la majorité des cas, Python avec ONNX Runtime ou Ultralytics suffit largement et la latence reste dominée par le GPU, pas par le glue Python.
Côté Docker, ne pas embarquer l’engine dans l’image car il dépend du modèle de GPU. Le mieux : compiler l’engine au démarrage du conteneur sur la machine cible, en montant le .onnx via volume et en générant .engine au boot. C’est légèrement plus lent au démarrage mais portable d’une machine à l’autre.
Pièges classiques de l’export
| Symptôme | Cause probable | Action |
|---|---|---|
| mAP qui chute brutalement après export | opset trop ancien ou incompatibilité TensorRT/ONNX | Ré-exporter avec opset=17, mettre à jour TensorRT et onnx. |
| « Engine cannot be deserialized » au chargement | Engine compilé sur un autre modèle de GPU | Recompiler sur la machine cible. |
| INT8 avec perte mAP > 5 points | Jeu de calibration trop petit ou non représentatif | Calibrer sur 200+ images variées, ou rester en FP16. |
| Export ONNX avec dynamic=True qui plante TensorRT | Shapes dynamiques mal configurées | Exporter avec dynamic=False et batch fixe en production. |
| Engine 10x plus lent qu’attendu | Pré-traitement Python qui domine la latence | Vectoriser le pré-traitement avec cv2 ou batch les images. |
| Compilation TensorRT qui échoue OOM | workspace trop petit | Augmenter workspace=8 ou plus. |
À lire dans la continuité
- Inférence YOLO v11 sur Jetson Orin — application directe de TensorRT sur edge.
- Servir YOLO v11 derrière une API FastAPI — pour exposer l’engine en HTTP.
- YOLO v11 dans le navigateur via WebGPU — l’export ONNX comme socle d’inférence côté client.
Sources et documentation
- 🔝 Vue d’ensemble : Pipeline YOLO v11
- Documentation export Ultralytics : docs.ultralytics.com/modes/export
- NVIDIA TensorRT Developer Guide : docs.nvidia.com/deeplearning/tensorrt
- ONNX opset reference : onnx.ai/onnx/operators
- Visualiseur Netron : netron.app
Avec un engine TensorRT validé, le modèle est prêt à être déployé sur la cible matérielle. Les deux scénarios suivants — Jetson Orin pour l’embarqué et FastAPI pour le serveur — bénéficient directement de cet artefact.