Aller au contenu

Détection d'objets avec YOLO

Place à l’apprentissage profond : YOLO (You Only Look Once) localise et classe plusieurs objets en une seule passe. Vous l’utiliserez d’abord pré-entraîné, puis vous l’entraînerez sur vos propres objets grâce à un dataset généré dans la simulation.

Fenêtre de terminal
pip install ultralytics # tire torch/torchvision automatiquement

Un modèle pré-entraîné sur COCO (80 classes courantes : person, bottle, cup…) se charge en une ligne :

from ultralytics import YOLO
model = YOLO("yolo11n.pt") # téléchargé automatiquement au 1er appel
results = model("capture.png") # inférence
results[0].show() # affiche l'image annotée

Lancez le monde et faites apparaître un objet « réaliste » que COCO connaît (trash_bottle → classe bottle) :

Fenêtre de terminal
ros2 launch bootcamp_vision vision_world.launch.py
ros2 launch bootcamp_vision spawn_object.launch.py object_type:=yolo

Chaque détection expose sa classe, son score et sa boîte (xyxy) :

for box in results[0].boxes:
cls = model.names[int(box.cls)] # ex. "bottle"
conf = float(box.conf) # score de confiance
x1, y1, x2, y2 = box.xyxy[0].tolist()
print(f"{cls} ({conf:.2f}) — bbox=({x1:.0f},{y1:.0f},{x2:.0f},{y2:.0f})")

Entraîner un détecteur demande beaucoup d’images annotées (objet + boîte + classe). Les annoter à la main est fastidieux. L’atout de la simulation : on connaît la position des objets, donc on peut générer ET labelliser automatiquement des milliers d’images en variant la pose, l’éclairage et les distracteurs (domain randomization).

bootcamp_vision fournit un outil qui fait exactement cela :

Fenêtre de terminal
# Génère un dataset YOLO auto-labellisé pour 5 classes, 300 images chacune
ros2 run bootcamp_vision capture_dataset \
--classes coffee_pack_1 coffee_pack_2 coffee_pack_3 trash_bottle trash_can \
--per-class 300 --out ~/yolo_ds --val-split 0.2

→ Vous obtenez une arborescence au format ultralytics :

~/yolo_ds/
images/train/ images/val/ # les .png capturés
labels/train/ labels/val/ # un .txt YOLO par image (classe + bbox normalisée)
data.yaml # noms de classes + chemins
Fenêtre de terminal
yolo detect train model=yolo11n.pt data=~/yolo_ds/data.yaml epochs=30 imgsz=640

YOLO part du modèle pré-entraîné (transfer learning) et l’adapte à vos classes. Les poids du meilleur modèle sont sauvegardés dans runs/detect/train/weights/best.pt.

model = YOLO("runs/detect/train/weights/best.pt")
results = model("capture.png")
results[0].show()

Spawnez un coffee_pack_2 et vérifiez que votre modèle le détecte alors que le modèle COCO en était incapable.

On réutilise le squelette du socle commun. Le modèle est chargé une fois dans le constructeur ; à chaque image, on ajoute une Detection par boîte (make_det y est défini). YOLO fournit directement la classe, le score et la boîte.

from ultralytics import YOLO
# ... (imports rclpy / Node / Image / Point / cv_bridge / Detection, DetectionArray)
class YoloDetector(Node):
def __init__(self):
super().__init__("yolo_detector")
self.bridge = CvBridge()
self.model = YOLO("best.pt") # votre modèle entraîné (ou "yolo11n.pt")
self.pub = self.create_publisher(DetectionArray, "/detections", 10)
self.create_subscription(Image, "/camera/image_raw", self.on_image, 10)
def on_image(self, msg):
frame = self.bridge.imgmsg_to_cv2(msg, "bgr8")
out = DetectionArray()
out.header = msg.header
for box in self.model(frame, verbose=False)[0].boxes:
if float(box.conf) < 0.5:
continue
x1, y1, x2, y2 = box.xyxy[0].tolist()
u, v = (x1 + x2) / 2, (y1 + y2) / 2 # centre de la boîte
w, h = x2 - x1, y2 - y1
out.detections.append(self.make_det(
self.model.names[int(box.cls)], int(box.cls), float(box.conf), u, v, w, h))
self.pub.publish(out)
Fenêtre de terminal
ros2 run mon_projet_vision yolo_detector
ros2 topic echo /detections # class_name = label, pose.position = centre back-projeté
  • Augmentez --per-class et le nombre d’epochs, comparez la précision obtenue.
  • Ajoutez des distracteurs lors de la capture et observez l’effet sur la robustesse.
  • Envie d’entraîner un réseau de zéro ? Tentez l’atelier Chiffres (CNN). Sans IA : Formes ou ArUco.

Cours conçu et animé par Etienne Schmitz