Estimation de pose et OBB
Lis les points clés et les boîtes orientées de YOLO26, définis une règle à partir de chacun et repère quand la posture ou l’angle est le véritable signal.
Une maison de retraite doit savoir si quelqu’un est tombé ; un port doit compter les navires serrés les uns contre les autres sur une image de drone. Les boîtes classiques échouent dans les deux cas : une boîte n’indique pas si une personne est debout, et une boîte droite autour d’un navire en diagonale couvre surtout de l’eau. L’estimation de pose et les OBB sont conçues précisément pour résoudre ces deux problèmes.
Pratique
Pose : quand la posture est le signal#

Un modèle de pose renvoie une boîte pour chaque personne, ainsi qu’une liste fixe de points clés. Les modèles entraînés sur COCO-Pose prédisent 17 points par personne — nez, yeux, oreilles, épaules, coudes, poignets, hanches, genoux et chevilles — toujours dans le même ordre : l’indice 0 correspond donc au nez, le 11 à la hanche gauche et le 15 à la cheville gauche. Chaque point clé a également un score de confiance.
La règle utile la plus simple : un corps debout est plus haut que large ; un corps allongé au sol est plus large que haut. Voici son application à l’image du bus, en utilisant uniquement les points clés pour lesquels le modèle a une confiance suffisante :
from ultralytics import YOLO
model = YOLO("yolo26n-pose.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]
for xy, conf in zip(result.keypoints.xy, result.keypoints.conf):
visible = xy[conf > 0.5] # drop keypoints the model couldn't see
width = float(visible[:, 0].max() - visible[:, 0].min())
height = float(visible[:, 1].max() - visible[:, 1].min())
posture = "unknown" if len(visible) < 5 else "lying" if width > height else "upright"
print(f"{len(visible):2d}/17 keypoints visible, body {width:3.0f} px wide x {height:3.0f} px tall -> {posture}")16/17 keypoints visible, body 117 px wide x 427 px tall -> upright
6/17 keypoints visible, body 80 px wide x 359 px tall -> upright
16/17 keypoints visible, body 91 px wide x 384 px tall -> upright
1/17 keypoints visible, body 0 px wide x 0 px tall -> unknown
2/17 keypoints visible, body 3 px wide x 6 px tall -> unknownTrois personnes sont clairement debout. Les deux dernières lignes correspondent à la personne coupée par le bord gauche et à un doublon de faible confiance : avec seulement un ou deux points clés visibles, il n’y a rien à évaluer, alors la règle répond « inconnu » au lieu de deviner. Un détecteur de chute utilisé en production ajoute une dimension temporelle — être allongé pendant plus de quelques secondes après une chute rapide — grâce au suivi.
Symptôme : des squelettes avec les poignets en l’air et des règles de posture qui se déclenchent pour des personnes à moitié visibles. Cause : keypoints.xy renvoie une position pour chacun des 17 points clés, même ceux que le modèle ne pouvait pas voir. Solution : filtre avec keypoints.conf, comme ci-dessus, et exige un nombre minimal de points clés visibles avant de prendre une décision.
La pose est utile lorsque la réponse dépend de ce que fait le corps : chutes ou levage avec le dos courbé pour la sécurité, angles des articulations et nombre de répétitions en sport comme dans le suivi des entraînements, ou posture du bétail et repères fixes sur des pièces avec une disposition personnalisée des points clés. Pour répondre à « y a-t-il une personne ici ? », utilise la détection classique.
OBB : quand l’angle compte#

Les côtés d’une boîte classique sont parallèles à ceux de l’image. Une boîte englobante orientée ajoute une rotation, représentée par le centre, la largeur, la hauteur et l’angle (xywhr). Dans les images en vue plongeante — satellite, drone, caméras de convoyeur en hauteur — les objets sont orientés dans toutes les directions, et une boîte droite autour d’un objet en diagonale couvre surtout l’arrière-plan, comme ce serait le cas pour les yachts ci-dessus. Mesure l’écart sur une vue par drone d’une marina :
from ultralytics import YOLO
model = YOLO("yolo26n-obb.pt")
result = model("https://ultralytics.com/images/boats.jpg", verbose=False)[0]
obb = result.obb
rotated_area = obb.xywhr[:, 2] * obb.xywhr[:, 3] # width x height of each rotated box
x1, y1, x2, y2 = obb.xyxy.T # the axis-aligned box that would enclose the same object
upright_area = (x2 - x1) * (y2 - y1)
print(f"{len(obb)} objects, classes: {sorted({result.names[int(c)] for c in obb.cls})}")
cx, cy, w, h, angle = obb.xywhr[0].tolist()
print(f"first box: center=({cx:.0f}, {cy:.0f}) size={w:.0f}x{h:.0f} angle={angle:.2f} rad")
ratio = float((upright_area / rotated_area).median())
print(f"an axis-aligned box would be {ratio:.1f}x larger (median)")173 objects, classes: ['harbor', 'ship']
first box: center=(619, 850) size=33x108 angle=-0.25 rad
an axis-aligned box would be 2.1x larger (median)Une boîte droite couvre environ deux fois la surface de la boîte orientée qui entoure le même bateau, et la surface supplémentaire correspond à de l’eau. Cela pose deux problèmes : la NMS détecte le chevauchement des boîtes droites de bateaux voisins et peut supprimer des détections réelles, et toute estimation de taille est gonflée. Les modèles OBB entraînés sur des jeux de données aériens comme DOTA traitent directement ces scènes. Note que l’angle est en radians : -0.25 rad équivaut à environ -14°.
Choisir entre détection, pose et OBB#
| Scénario | Tâche la plus adaptée | Pourquoi |
|---|---|---|
| Compter les personnes sur un trottoir | Détection | La présence et l’emplacement suffisent comme réponse |
| Détecter une chute dans une maison de retraite | Pose | L’orientation du corps est le signal |
| Compter les squats dans une salle de sport | Pose | Les angles du genou et de la hanche sont le signal |
| Compter les bateaux amarrés depuis un drone | OBB | Les bateaux sont en diagonale et très rapprochés |
| Colis sur un convoyeur, vus d’en haut | OBB | L’orientation varie et les objets voisins se touchent |
| Voitures au niveau de la rue | Détection | Les voitures apparaissent globalement droites dans le cadre |
La pose ajoute des points clés à chaque boîte ; OBB ajoute un angle. Si ton code ne lit jamais les points clés ni l’angle, un détecteur classique est plus rapide à annoter et à exécuter, et plus facile à déboguer.
Afficher la solution
from ultralytics import YOLO
image = "https://ultralytics.com/images/boats.jpg"
upright = YOLO("yolo26n.pt")(image, verbose=False)[0]
rotated = YOLO("yolo26n-obb.pt")(image, verbose=False)[0]
print(f"axis-aligned detector: {len(upright.boxes)} boxes")
print(f"OBB model: {len(rotated.obb)} rotated boxes")axis-aligned detector: 0 boxes
OBB model: 173 rotated boxesLa majeure partie de l’écart vient des données d’entraînement, pas de la géométrie. yolo26n.pt a été entraîné sur COCO, où les bateaux sont surtout photographiés de côté ; vus d’en haut, il ne détecte rien avec le seuil par défaut (réduis conf à 0.05 : il en classe quelques-uns comme des bouteilles). Le modèle OBB a été entraîné sur des images aériennes. La géométrie compte tout de même : même un détecteur entraîné sur des bateaux vus du ciel produirait des boîtes environ deux fois trop grandes et aurait du mal avec la NMS dans des rangées très serrées. La tâche et les données d’entraînement doivent correspondre aux conditions de déploiement.