Module 3 — Détection en une étape : YOLO et SSD
Le module 2 a exposé la famille R-CNN, qui propose puis classe. Sur le carrefour, un flux à 25 images par seconde donne 40 millisecondes par image pour tout faire, à quoi s'ajoutent le décodage vidéo, le suivi et l'affichage. Faster R-CNN à 15 images par seconde ne tient pas ce budget. Les détecteurs en une étape existent pour ça.
Le principe : prédire directement sur une grille
Un détecteur en une étape découpe l'image en une grille régulière — par exemple 20 × 20 sur une entrée à 640 pixels. À chaque cellule, plusieurs prédictions sortent en parallèle : classe, boîte englobante, score. Il n'y a plus de deuxième étape, plus de propositions à filtrer. Le calcul est identique quelle que soit la scène : deux personnes ou trois cents, c'est le même temps.
L'entraînement se fait bout à bout avec une perte multi-tâches qui somme :
- Une perte de classification sur les logits par classe.
- Une perte de régression sur la position et la taille de la boîte, souvent une IoU généralisée aujourd'hui (CIoU ou DIoU) plutôt que la distance L1 du modèle originel.
- Un terme d'objectness qui distingue les cellules qui contiennent un objet des autres.
L'évolution de YOLO
YOLO v1 (2016) posait le principe et produisait une grille 7 × 7 avec deux boîtes par cellule. Sa faiblesse était le rappel sur les objets regroupés — deux vélos côte à côte partageaient une cellule et perdaient l'un des deux.
YOLOv2, v3 puis v4 ont introduit les ancres (module 4), le tronc Darknet-53, la prédiction multi-échelle sur trois cartes de tailles différentes et une perte plus stable. L'écart de précision avec R-CNN s'est resserré à mesure qu'ils gagnaient en vitesse.
YOLOv5 puis YOLOv8 d'Ultralytics ont proposé un cadre sans ancre (anchor-free) sur les objets petits et moyens, ainsi qu'une tête découplée qui sépare classification et régression. YOLOv8 se pilote par une petite bibliothèque Python compacte, qui masque presque toute l'infrastructure.
from ultralytics import YOLO
modele = YOLO("yolov8n.pt") # petit modele preentraine sur COCO
resultats = modele("carrefour.jpg") # une image ou un chemin
for boite in resultats[0].boxes:
x1, y1, x2, y2 = boite.xyxy[0].tolist()
classe = int(boite.cls[0])
score = float(boite.conf[0])
print(classe, score, round(x1), round(y1), round(x2), round(y2))
Sur une carte grand public, YOLOv8n tourne à 300 images par seconde en demi-précision, ce qui laisse une marge confortable pour le pipeline aval.
SSD : la première version publiée en 2016
SSD (Single Shot MultiBox Detector) a proposé le même principe que YOLO, mais avec une prédiction dense issue de plusieurs cartes de résolutions décroissantes. Une image de 300 pixels produit des prédictions à 38 × 38, 19 × 19, 10 × 10, 5 × 5, 3 × 3 et 1 × 1. Les grandes résolutions couvrent les petits objets, les petites résolutions couvrent les grands.
Cette prédiction pyramidale est une préfiguration du Feature Pyramid Network généralisé plus tard. SSD reste utilisé quand on veut un détecteur simple, portable sur mobile, et compréhensible ligne par ligne.
Le déséquilibre positif contre négatif
Un détecteur en une étape prédit des dizaines de milliers d'ancres par image. Sur une scène de carrefour où figurent vingt objets, cela laisse par définition des dizaines de milliers d'ancres qui n'appartiennent à aucun objet. Le rapport négatif contre positif dépasse allègrement le millier pour un.
La perte de classification standard, l'entropie croisée, se laisse dominer par les négatifs. Même bien classés, ils accumulent une contribution qui noie le signal utile.
RetinaNet (2017) a introduit la focal loss, qui pondère chaque terme par pour atténuer les exemples faciles. Un négatif classifié avec voit son terme presque annulé par le facteur à .
Le résultat pratique : un détecteur en une étape atteint le niveau de précision d'un Faster R-CNN sans changer d'échantillonnage.
Avec trop grand, la focal loss annule aussi les positifs faciles et l'entraînement stagne. Les valeurs par défaut et sont un bon point de départ mais méritent un balayage sur un jeu déséquilibré autrement. Un à zéro rend la focal loss équivalente à l'entropie croisée pondérée.
Choisir entre les familles
| Situation | Bon candidat |
|---|---|
| Comptage sur flux vidéo en direct | YOLOv8 |
| Contrôle qualité industriel hors ligne | Faster R-CNN |
| Objets très petits et nombreux | Faster R-CNN + FPN |
| Détection sur appareil embarqué | SSD MobileNet ou YOLOv8n quantifié |
| Prototypage rapide sur COCO | YOLOv8 préentraîné |
Le carrefour du fil rouge tombe dans la première ligne. Le module 10 détaille l'affinage d'un YOLOv8n sur des images maison. Le tableau ci-dessus n'est pas fermé — pour un projet donné, mesurez toujours la précision et la latence sur vos données avant de vous engager sur un modèle.
Sortie normalisée entre les familles
Une bonne hygiène de projet est de normaliser la sortie de tous les détecteurs vers un même format, quel que soit le modèle sous-jacent.
def normaliser(detections, image_h, image_w):
"""Renvoie [(classe, score, x1, y1, x2, y2)] en pixels absolus."""
resultat = []
for det in detections:
classe = int(det["classe"])
score = float(det["score"])
x1, y1, x2, y2 = det["boite"]
x1 = max(0.0, min(x1, image_w))
y1 = max(0.0, min(y1, image_h))
x2 = max(0.0, min(x2, image_w))
y2 = max(0.0, min(y2, image_h))
resultat.append((classe, score, x1, y1, x2, y2))
return resultat
Ce point paraît anodin mais évite l'accumulation de « x en pixels ici, en
fraction là, en centre plus taille ailleurs » qui ronge tout projet vidéo au
bout de six semaines.
YOLOv8 gère 640 × 640 par défaut, Faster R-CNN accepte 800 × 800. L'important est de fixer la résolution d'entraînement et d'évaluation, et de ne pas changer d'échelle d'appel en appel. Une seule modification passe inaperçue en développement puis rend l'évaluation incomparable.
En résumé
- Un détecteur en une étape prédit sur une grille dense en un seul passage : latence constante et bien plus rapide qu'un pipeline R-CNN.
- YOLO est aujourd'hui la référence temps réel. Sa version 8, sans ancre et à tête découplée, offre un cadre compact utilisable en cinq lignes de Python.
- SSD a préfiguré la prédiction multi-échelle et reste un choix simple pour l'embarqué ; RetinaNet introduit la focal loss qui règle le déséquilibre positif contre négatif.
- Le choix entre R-CNN et une étape se fait sur la latence cible et la taille des objets, jamais sur la seule métrique globale. Fixer la résolution d'entrée dès le début épargne beaucoup d'ennuis en évaluation.
Module suivant : les ancres, la suppression des non-maxima et les seuils — les trois réglages qui décident du visage réel du détecteur.