Ultralytics YOLO27 : Inscris-toi sur la liste d’attente.
Get Started
Leçondébutant

Collecter des données représentatives de haute qualité

Recueille des images dans les conditions réelles de déploiement, intègre les métadonnées de capture à chaque nom de fichier, suis la couverture par rapport à la spécification et échantillonne les vidéos sans saturer le jeu de données.

La plupart des échecs des jeux de données sont dus à la collecte. Une équipe capture des exemples nets avec une seule caméra en une semaine, obtient d’excellents résultats en validation, puis le modèle s’effondre sur le deuxième site. La collecte fixe le plafond : aucune qualité d’annotation, augmentation ou valeur d’hyperparamètre ne peut apprendre au modèle une scène absente du jeu de données.

Résultat

Crée un jeu de données dont les noms de fichiers indiquent la caméra, le jour et l’image, mesure sa couverture par rapport aux quotas de ta spécification et réduis l’échantillonnage vidéo à des images distinctes.

Parcours accéléré
Si tu connais déjà les bases, voici la version courte.
  1. Capture des images avec les caméras de production sur lesquelles le modèle sera exécuté.

  2. Nomme chaque fichier camera_day_frame pour pouvoir ensuite les regrouper et les auditer.

  3. Compte les images par caméra, jour et scénario par rapport à la spécification, puis collecte les éléments manquants.

  4. Échantillonne les vidéos pour ne conserver que les images où la scène a changé.

  5. N’utilise des images publiques, mises en scène ou synthétiques que pour combler des lacunes précises.

Pratique

La diversité prime sur le volume#

Compare deux jeux de données destinés au même déploiement :

Jeu de donnéesRésultat de validationEn production
10 000 images presque identiques, une seule caméra, uniquement à midiÉlevé : les images de validation ressemblent aux images d’entraînementLes performances chutent avec une autre caméra et au crépuscule
1 500 images réparties entre 12 scénarios de la spécificationPlus modesteTient la route, car la production ressemble aux données

Le score de validation du premier jeu de données est élevé uniquement parce que la validation mesure la seule condition qu’il couvre. En production, un modèle n’est performant qu’à la hauteur du scénario qu’il couvre le moins bien. Optimise d’abord la collecte pour couvrir la spécification, puis pour augmenter le volume.

Choisis les sources dans le bon ordre#

La majeure partie du jeu de données devrait provenir de la configuration de production réelle. Le guide de collecte et d’annotation des données décrit chaque source plus en détail :

SourceQuand c’est utileQuand c’est nuisible
Caméras de production, en directAu plus près du déploiementLent ; des accords sur les données peuvent être nécessaires
Caméras de production, archivesBeaucoup de diversité en peu de tempsLes anciennes vidéos peuvent ne pas correspondre à la configuration actuelle
Jeux de données publics (COCO, Open Images, VOC)Démarrage avec des classes courantesDécalage de domaine par rapport à tes scènes
Captures mises en scèneCas limites précis à la demandeTrop propres ; risque de trop s’y fier
Images synthétiques ou généréesDangers et défaillances rares que tu ne peux pas attendreLe modèle peut apprendre le style du générateur
Collecte de données sur le WebDiversité à faible coûtQualité inégale et risques liés aux licences

Utilise des images mises en scène, publiques et synthétiques pour combler des lacunes précises et nommées dans la spécification, et suis leur proportion dans le jeu de données pour mesurer leur utilité. Sur Ultralytics Platform, Générer des images similaires ajoute à un jeu de données des variantes générées à partir d’une image existante, non annotées et prêtes à être annotées.

Intègre les métadonnées au nom de fichier#

Chaque image doit contenir au minimum un ID de caméra, un jour de capture et un numéro d’image ou de séquence vidéo. Sans ces informations, tu ne peux pas créer ensuite des partitions par groupe, retracer l’origine d’une régression ni collecter davantage de données pour un scénario sous-représenté. Le nom de fichier est le moyen le plus durable de les conserver : cam2_2026-05-01_000124.jpg résiste à tous les outils, exportations et téléversements. La recherche de jeux de données d’Ultralytics Platform fonctionne avec les noms de fichiers et les métadonnées personnalisées ; ces clés restent donc consultables après le téléversement.

Ce script crée le jeu de données d’entraînement utilisé dans le reste du cours. Il copie les images annotées de COCO128 et les renomme comme si quatre caméras les avaient capturées sur quatre jours, en surreprésentant cam1, comme c’est souvent le cas avec une caméra facile d’accès :

import shutil
from pathlib import Path

from ultralytics.data.utils import check_det_dataset, img2label_paths

data = check_det_dataset("coco128.yaml")  # 128 COCO images stand in for your camera captures
out = Path("datasets/practice")
(out / "images").mkdir(parents=True, exist_ok=True)
(out / "labels").mkdir(parents=True, exist_ok=True)

for i, image in enumerate(sorted(Path(data["train"]).glob("*.jpg"))):
    camera = ("cam1", "cam1", "cam2", "cam3", "cam4")[i % 5]  # cam1 over-collected, like a real site
    name = f"{camera}_2026-05-0{i // 32 + 1}_{i:06d}"  # camera, capture day, frame number
    shutil.copy(image, out / "images" / f"{name}.jpg")
    label = Path(img2label_paths([str(image)])[0])
    if label.exists():
        shutil.copy(label, out / "labels" / f"{name}.txt")

print(len(list((out / "images").glob("*.jpg"))), "images written to", out)
128 images written to datasets/practice

Boîte de dialogue Nouveau jeu de données d’Ultralytics Platform : dépose des images, des vidéos ou des jeux de données au format YOLO, COCO ou NDJSON, puis définis le nom, l’URL, la description, le type de tâche, la licence, le floutage des visages et la visibilité du jeu de données

Le téléversement vers Ultralytics Platform conserve ces noms de fichiers. La boîte de dialogue de téléversement accepte également les vidéos et les jeux de données complets ; ses paramètres comprennent le floutage des visages pour protéger la vie privée.

Suis la couverture par rapport à la spécification#

Avec les métadonnées intégrées aux noms de fichiers, la couverture se mesure par un décompte. Définis les quotas à partir de ta spécification et laisse le script indiquer ce qu’il faut collecter ensuite :

from collections import Counter
from pathlib import Path

QUOTA = {"cam1": 30, "cam2": 30, "cam3": 30, "cam4": 30}  # images per camera, from your spec

images = sorted(Path("datasets/practice/images").glob("*.jpg"))
cameras = Counter(p.stem.split("_")[0] for p in images)
days = Counter(p.stem.split("_")[1] for p in images)

for camera, quota in QUOTA.items():
    gap = quota - cameras[camera]
    print(f"{camera}: {cameras[camera]:3d} / {quota}  {'ok' if gap <= 0 else f'collect {gap} more'}")
print("days:", dict(sorted(days.items())))
cam1:  52 / 30  ok
cam2:  26 / 30  collect 4 more
cam3:  25 / 30  collect 5 more
cam4:  25 / 30  collect 5 more
days: {'2026-05-01': 32, '2026-05-02': 32, '2026-05-03': 32, '2026-05-04': 32}

La règle de décision : arrête de collecter auprès de toute source qui dépasse son quota et concentre tes efforts sur les lacunes. Ici, cam1 représente déjà 40 % des images. Une semaine supplémentaire de vidéos provenant de cette source augmenterait le volume, mais n’améliorerait pas la couverture.

Échantillonne les vidéos sans saturer le jeu de données#

La vidéo est la source la moins coûteuse et la plus facile à mal exploiter. À 30 images par seconde, une minute produit 1 800 images presque identiques ; annoter deux fois le même moment coûte cher et gonfle les métriques. Ne conserve une image que si la scène a changé depuis la dernière image conservée :

from pathlib import Path

import cv2

from ultralytics.utils.downloads import safe_download

video = "solutions_ci_demo.mp4"  # a short public demo clip; swap in your own footage
safe_download(f"https://github.com/ultralytics/assets/releases/download/v0.0.0/{video}")
Path("frames").mkdir(exist_ok=True)

cap = cv2.VideoCapture(video)
fps = cap.get(cv2.CAP_PROP_FPS)
read = kept = 0
last = None
while True:
    ok, frame = cap.read()
    if not ok:
        break
    thumb = cv2.cvtColor(cv2.resize(frame, (64, 64)), cv2.COLOR_BGR2GRAY).astype(float)
    if last is None or abs(thumb - last).mean() > 10:  # keep a frame only when the scene has changed
        cv2.imwrite(f"frames/clip01_{read:06d}.jpg", frame)  # the clip ID stays in the filename
        kept, last = kept + 1, thumb
    read += 1

print(f"{read} frames at {fps:.0f} FPS -> {kept} kept")
62 frames at 30 FPS -> 6 kept

La séquence de deux secondes contient 62 images, mais seulement 6 moments visuellement distincts. Le script compare de minuscules vignettes en niveaux de gris ; il est donc rapide même sur plusieurs heures de vidéos. Augmente le seuil de 10 pour conserver moins d’images provenant de caméras fixes ; réduis-le pour les scènes où les éléments se déplacent rapidement. Répartis aussi le budget entre les séquences : 20 images de chacune de 50 séquences valent mieux que 1 000 images d’une seule.

Les images d’un même clip forment un seul échantillon, pas plusieurs

Deux images séparées d’une seconde partagent le même éclairage, le même arrière-plan et généralement les mêmes objets. Si elles se retrouvent à la fois dans l’entraînement et dans la validation, la validation évalue le modèle sur des images qu’il a déjà pratiquement vues. Conserve l’identifiant du clip dans chaque nom de fichier pour que Répartir correctement le jeu de données puisse garder chaque clip ensemble.

Évite les pièges lors de la collecte#

PiègeSymptômeCorrectif
Collecte sur une seule semainemAP de validation élevée, mais échecs lors d’autres saisons ou changements de conditionsÉtale la collecte sur plusieurs semaines ou mois
Une seule caméraÉchec avec la deuxième caméraCollecte des images avec chaque type de caméra que tu déploies
Données uniquement mises en scèneÉchec face à un désordre réelGarde les images mises en scène minoritaires et suis leur proportion
Images dupliquéesMétriques artificiellement gonflées, travail d’annotation gaspilléÉchantillonne selon les changements de scène ; Ultralytics Platform ignore aussi les copies exactes lors du téléversement
Un seul opérateur ou créneau de travailApparence imprévisible et déséquilibre des classesÉchantillonne sur plusieurs créneaux, sites et personnes
Cas rares manquantsLes événements de sécurité les plus importants passent inaperçusCollecte ciblée, mise en scène ou complément de données synthétiques

Le biais est un problème de collecte, pas de modélisation : aucun hyperparamètre ne peut corriger l’absence d’un groupe dans les données. Le guide de collecte des données présente quatre leviers : la diversité des sources, une représentation équilibrée, des réévaluations régulières de la couverture et des mesures d’atténuation comme le suréchantillonnage des groupes sous-représentés.

Si les images contiennent des visages, des plaques d’immatriculation ou d’autres données personnelles, tu dois obtenir le consentement et définir une politique de conservation avant le début de la collecte. L’entrée du glossaire confidentialité des données est un bon point de départ, et Confidentialité, régions et conformité explique comment conserver les données dans la juridiction appropriée avec dataRegion.

Essayer

Exécute make_practice_set.py, puis modifie les quotas dans coverage.py pour les adapter à tes propres spécifications (ou conserve les quotas d’exercice) et exécute le script. Pour ton vrai projet, renomme 50 images récentes selon le modèle camera_day_frame et calcule la même couverture pour celles-ci. Livrable : un rapport de couverture et un plan de collecte indiquant chaque source qui dépasse son quota et chaque lacune, avec son ampleur.

Terminé lorsque
Tu as terminé la leçon lorsque tous les éléments suivants sont réunis.
  • Chaque nom de fichier image indique une caméra (ou une source), un jour de capture et un numéro d’image ou de séquence vidéo.

  • Un rapport de couverture compare le nombre d’images par caméra, jour ou scénario aux quotas définis dans les spécifications.

  • Les vidéos sont échantillonnées en fonction des changements de scène, et les images retenues conservent leur identifiant de séquence.

Afficher la solution

Pour le jeu d’exercice, le rapport de couverture indique directement les actions à prendre :

SourceNombre / quotaAction
cam152 / 30Arrête la collecte : elles représentent déjà 40 % de toutes les images
cam226 / 30Collecte-en 4 de plus
cam325 / 30Collecte-en 5 de plus
cam425 / 30Collecte-en 5 de plus

Chaque caméra couvre les quatre jours ; les lacunes concernent donc chaque caméra, et non chaque jour. Répartis les 14 nouvelles images sur au moins deux nouveaux jours pour qu’elles apportent une nouvelle condition plutôt que davantage d’images du même après-midi. Si une caméra ne peut pas combler sa lacune (par exemple, si elle ne voit que la nuit), ajoute une ligne aux spécifications pour la condition manquante et indique si des images mises en scène ou générées la comblent, afin de pouvoir en mesurer l’effet par la suite.

Et ensuite ?

Une fois les images collectées, la prochaine leçon t’apprend à créer des annotations cohérentes dès le départ.