Hochwertige, repräsentative Daten sammeln
Sammle Bilder unter realen Einsatzbedingungen, halte Aufnahmemetadaten in jedem Dateinamen fest, verfolge die Abdeckung anhand der Spezifikation und wähle Videobilder aus, ohne den Datensatz aufzublähen.
Die meisten Probleme mit Datensätzen entstehen beim Sammeln. Ein Team nimmt eine Woche lang saubere Beispiele mit einer Kamera auf, die Validierung sieht hervorragend aus, und am zweiten Standort versagt das Modell. Die Datensammlung setzt die Obergrenze: Weder Labelqualität noch Augmentierung oder Hyperparameter können dem Modell eine Szene beibringen, die im Datensatz nie vorkam.
Praxisnah
Variabilität schlägt Umfang#
Vergleiche zwei Datensätze für denselben Einsatz:
| Datensatz | Validierungsergebnis | Im Produktivbetrieb |
|---|---|---|
| 10.000 nahezu identische Einzelbilder, eine Kamera, nur zur Mittagszeit | Hoch: Validierungsbilder ähneln den Trainingsbildern | Die Leistung sinkt bei einer anderen Kamera und in der Abenddämmerung |
| 1.500 Einzelbilder, verteilt auf 12 Szenarien der Spezifikation | Weniger beeindruckend | Funktioniert zuverlässig, weil der Produktivbetrieb den Daten ähnelt |
Der Validierungswert des ersten Datensatzes ist nur deshalb hoch, weil die Validierung die einzige darin abgedeckte Bedingung misst. Im Produktivbetrieb ist ein Modell nur so gut wie das am schlechtesten abgedeckte Szenario, dem es begegnet. Optimiere die Datensammlung zuerst auf die Abdeckung der Spezifikation und erst danach auf den Umfang.
Quellen in der richtigen Reihenfolge auswählen#
Der Großteil des Datensatzes sollte aus der realen Produktionsumgebung stammen. Der Leitfaden zur Datensammlung und Annotation beschreibt jede Quelle ausführlicher:
| Quelle | Wann sie hilfreich ist | Wann sie nachteilig ist |
|---|---|---|
| Produktionskameras, live | Am ähnlichsten zum späteren Einsatz | Langsam; möglicherweise sind Datenvereinbarungen erforderlich |
| Produktionskameras, archiviert | Schnell große Variabilität | Älteres Filmmaterial entspricht möglicherweise nicht mehr der aktuellen Einrichtung |
| Öffentliche Datensätze (COCO, Open Images, VOC) | Aufbau einer Grundlage für gängige Klassen | Domänenverschiebung gegenüber deinen Szenen |
| Inszenierte Aufnahmen | Bestimmte Sonderfälle gezielt aufnehmen | Zu sauber; man verlässt sich leicht zu sehr darauf |
| Synthetische oder generierte Bilder | Seltene Gefahren und Fehler, auf die du nicht warten kannst | Das Modell kann den Stil des Generators lernen |
| Web Scraping | Kostengünstige Vielfalt | Uneinheitliche Qualität und Lizenzrisiken |
Verwende inszenierte, öffentliche und synthetische Bilder, um bestimmte, klar benannte Lücken in der Spezifikation zu schließen, und verfolge ihren Anteil am Datensatz, damit du messen kannst, ob sie helfen. Auf der Ultralytics Platform fügt Ähnliche Bilder generieren einem Datensatz generierte Varianten eines vorhandenen Bildes hinzu, unbeschriftet und bereit zur Annotation.
Metadaten im Dateinamen festhalten#
Jedes Bild benötigt mindestens eine Kamera-ID, den Aufnahmetag und eine Einzelbild- oder Clipnummer. Ohne diese Angaben kannst du später nicht nach Gruppen aufteilen, eine Regression bis zu ihrer Quelle zurückverfolgen oder mehr Material für ein unterrepräsentiertes Szenario sammeln. Der dauerhafteste Speicherort dafür ist der Dateiname: cam2_2026-05-01_000124.jpg bleibt bei jedem Tool, Export und Upload erhalten. Die Datensatzsuche der Ultralytics Platform findet Dateinamen und benutzerdefinierte Metadaten, sodass diese Schlüssel auch nach dem Upload durchsuchbar bleiben.
Dieses Skript erstellt den Übungsdatensatz, der im restlichen Kurs verwendet wird. Es kopiert die beschrifteten Bilder aus COCO128 und benennt sie so um, als hätten vier Kameras sie über vier Tage aufgenommen, wobei cam1 überrepräsentiert ist, wie es bei einer praktischen Kamera oft der Fall ist:
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
Beim Upload auf die Ultralytics Platform bleiben diese Dateinamen erhalten. Im Upload-Dialog kannst du auch Videos und vollständige Datensätze hochladen; zu den Einstellungen gehört außerdem das Unkenntlichmachen von Gesichtern zum Schutz der Privatsphäre.
Abdeckung anhand der Spezifikation verfolgen#
Mit Metadaten in den Dateinamen lässt sich die Abdeckung einfach zählen. Lege die Kontingente anhand deiner Spezifikation fest und lass dir vom Skript sagen, was als Nächstes gesammelt werden soll:
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}Die Entscheidungsregel: Sammle nicht weiter aus Quellen, deren Kontingent erreicht ist, und richte den Aufwand auf die Lücken. Hier enthält cam1 bereits 40 % der Bilder. Eine weitere Woche mit diesem Filmmaterial würde zwar den Umfang vergrößern, aber keine neue Abdeckung schaffen.
Videobilder auswählen, ohne den Datensatz aufzublähen#
Video ist die günstigste Quelle und lässt sich am leichtesten falsch einsetzen. Bei 30 Bildern pro Sekunde liefert eine Minute 1.800 nahezu identische Einzelbilder, und denselben Moment zweimal zu beschriften kostet Geld und verzerrt die Kennzahlen. Behalte ein Einzelbild nur dann, wenn sich die Szene seit dem letzten behaltenen Einzelbild verändert hat:
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 keptDer zwei Sekunden lange Clip enthält 62 Einzelbilder, aber nur 6 visuell unterschiedliche Momente. Das Skript vergleicht kleine Graustufenminiaturen und ist deshalb auch bei stundenlangem Filmmaterial schnell. Erhöhe den Schwellenwert von 10, um bei statischen Kameras weniger Einzelbilder zu behalten; senke ihn für Szenen mit schnellen Bewegungen. Verteile das Kontingent außerdem auf mehrere Clips: 20 Einzelbilder aus jedem von 50 Clips sind besser als 1.000 Einzelbilder aus einem einzigen Clip.
Zwei Bilder im Abstand von einer Sekunde haben dieselbe Beleuchtung, denselben Hintergrund und meist dieselben Objekte. Wenn sie sowohl im Trainings- als auch im Validierungssatz landen, wird das Modell in der Validierung anhand von Bildern bewertet, die es praktisch schon gesehen hat. Nimm die Clip-ID in jeden Dateinamen auf, damit Datensatz korrekt aufteilen alle Bilder eines Clips zusammenhält.
Fallstricke bei der Datenerhebung vermeiden#
| Fallstrick | Symptom | Lösung |
|---|---|---|
| Datenerhebung innerhalb einer Woche | Hoher mAP auf den Validierungsdaten, aber Fehler in anderen Jahreszeiten oder bei Schichtwechseln | Verteile die Aufnahmen auf mehrere Wochen oder Monate |
| Nur eine Kamera | Funktioniert mit der zweiten Kamera nicht | Nimm Bilder mit allen Kameratypen auf, die du einsetzt |
| Nur inszenierte Daten | Funktioniert bei realem Durcheinander nicht | Halte inszenierte Bilder in der Minderheit und erfasse ihren Anteil |
| Doppelte Frames | Aufgeblähte Kennzahlen und unnötiger Beschriftungsaufwand | Stichproben nach Szenenwechseln; die Ultralytics Platform überspringt beim Hochladen außerdem exakte Kopien |
| Nur eine Bedienperson oder Schicht | Ungeplante Erscheinungsbilder und unausgewogene Klassenverteilung | Ziehe Stichproben über verschiedene Schichten, Standorte und Personen hinweg |
| Seltene Fälle fehlen | Die wichtigsten Sicherheitsvorfälle werden übersehen | Gezielte Aufnahmen, Inszenierung oder Ergänzung mit synthetischen Daten |
Verzerrungen und Einwilligung#
Verzerrungen sind ein Problem der Datenerhebung, kein Modellierungsproblem: Kein Hyperparameter kann eine Gruppe berücksichtigen, die in den Daten nie enthalten war. Der Leitfaden zur Datenerhebung nennt vier Ansatzpunkte: vielfältige Quellen, ausgewogene Repräsentation, regelmäßige erneute Prüfungen der Abdeckung und Maßnahmen zur Abhilfe, etwa Überstichproben für unterrepräsentierte Gruppen.
Wenn Bilder Gesichter, Nummernschilder oder andere personenbezogene Daten enthalten, brauchst du vor Beginn der Datenerhebung eine Einwilligung und eine Aufbewahrungsrichtlinie. Der Glossareintrag zu Datenschutz ist ein guter Ausgangspunkt; Datenschutz, Regionen und Compliance behandelt, wie du Daten mit dataRegion in der richtigen Rechtsordnung hältst.
Lösung anzeigen
Für den Übungsdatensatz ergibt der Abdeckungsbericht einen konkreten Plan:
| Quelle | Anzahl / Kontingent | Maßnahme |
|---|---|---|
cam1 | 52 / 30 | Beende die Datenerhebung; auf diese Quelle entfallen bereits 40 % aller Bilder |
cam2 | 26 / 30 | Erfasse 4 weitere |
cam3 | 25 / 30 | Erfasse 5 weitere |
cam4 | 25 / 30 | Erfasse 5 weitere |
Jede Kamera deckt alle vier Tage ab, daher beziehen sich die Lücken auf die Kameras, nicht auf die Tage. Verteile die 14 neuen Bilder auf mindestens zwei neue Tage, damit sie eine neue Bedingung abdecken und nicht noch mehr vom selben Nachmittag zeigen. Kann eine Kamera ihre Lücke nicht schließen (etwa weil sie ausschließlich Nachtaufnahmen liefert), ergänze die Spezifikation um eine Zeile für die fehlende Bedingung und halte fest, ob inszenierte oder generierte Bilder die Lücke füllen, damit sich die Auswirkungen später messen lassen.