19 min Lesezeit

Erstelle ein Objekt-Erkennung-Datenset für Filmklappen

Aktualisiert am 12 Aug 2026

Als ich 2022 zum ersten Mal mit der Erstellung eigener Datasets für Paperdot herumexperimentiert habe, ging es noch um reine Klassifikation: Ein Modell sollte lernen, verschiedene Materialien zu unterscheiden. Richtig gute Tools, um den Labeling-Prozess zu beschleunigen, gab es damals kaum. Meistens hat man sich seine Scripts einfach selbst zusammengebaut. Vier Jahre später sieht das anders aus: Mittlerweile gibt es ein ganzes Ökosystem an Annotation-Tools genau für diesen Zweck (CVAT, Label Studio und Roboflow sind die, zu denen ich immer wieder zurückkomme).

In meinem aktuellen Forschungsprojekt ist die Sache nochmal einen Schritt weitergegangen - weg vom statischen Labeling, hin zu dynamischem Echtzeit-Tracking. Diesmal lautet das Ziel: Filmklappen tracken, also die Klappen, die den Anfang (oder das Ende) einer Einstellung markieren. Dieser Post dreht sich um den Teil, der eigentlich darüber entscheidet, ob der Rest des Projekts überhaupt funktioniert: die Erstellung des Datensets.


1. Die Grundüberlegung: Was tracken wir hier eigentlich?

Bevor wir auch nur ein einziges Bild annotieren, sollten wir klären, was man wirklich braucht - nicht, was sich bequem labeln lässt. Für die Erkennung von Filmklappen sahen die Anforderungen wie folgt aus:

  • Echtzeit-Geschwindigkeit - das Ganze muss live am Set laufen, nicht als Offline-Batch-Job.
  • Rotationsbewusstsein - Klappen werden nicht immer gerade gehalten. Fürs Kamerabild werden sie gekippt, und „End-Klappen" (auch „Tail Slates" genannt, gefilmt am Ende statt am Anfang einer Einstellung) werden oft um 180° gedreht in die Kamera gehalten.
  • Zustandserkennung - das System muss wissen, ob die Klappe offen oder geschlossen ist, denn genau dieser Moment markiert den eigentlichen Schnittpunkt.

Nur die ersten beiden Punkte sind wirklich Geometrie-Fragen. Der dritte ist ein Labeling-/Taxonomie-Problem, dazu komme ich im nächsten Abschnitt. Bevor man sich für eine Geometrie entscheidet, lohnt es sich, erst die einfachste Option auszuschließen und dann bei den verbleibenden, komplexeren bewusst abzuwägen:

  • Bildklassifikation (zuerst ausgeschlossen): Die einfachste Option auf dem Papier - keine Boxen, einfach das ganze Bild (oder einen Ausschnitt davon) in einen Klassifikator füttern und slate_open, slate_closed oder background als Ergebnis bekommen. Das ist gleichzeitig die ungenaueste Wahl für diesen Anwendungsfall, aus zwei Gründen, die sich gegenseitig verstärken. Erstens liefert ein Klassifikator keine Position - selbst eine korrekte Vorhersage „slate_open" auf einem 4K-Bild sagt dir nicht, wo sich die Klappe befindet, was nutzlos ist, wenn der eigentliche nächste Schritt das Zuschneiden und Entzerren der Klappe für die OCR ist. Zweitens sinkt die Klassifikationsgenauigkeit deutlich, sobald die Klappe nicht mehr den Großteil des Bildes einnimmt: In einer Weitwinkelaufnahme, in der die Klappe nur 5 % des Bildes ausmacht, geht das Signal im Rest des Bildes unter, das das Netzwerk mitverarbeiten muss - und genau in diesen realistischen Weitwinkelaufnahmen sinkt die Präzision am stärksten. Detection - in einer der drei folgenden Varianten - löst beide Probleme gleichzeitig, weil sie dir eine Position liefert und das Modell sich nur auf diesen Bereich konzentrieren kann, statt auf das gesamte Bild.
  • Horizontal Bounding Boxes (HBB) - der Standard, und warum er hier nicht ausreicht: Liefert ein achsenparalleles $x, y, w, h$-Rechteck. Da Klappen fast immer in einem Winkel gehalten werden, muss eine achsenparallele Box so groß werden, dass sie die gesamte gekippte Form umschließt - für eine um 30-45° gekippte Klappe gehen so leicht 30-40 % der Boxfläche als reine Polsterung drauf. Das kostet nicht nur Crop-Pixel, es verwirrt auch aktiv, was das Modell als „Aussehen einer Klappe" lernt, weil ein großer Teil jeder positiven Trainingsbox visuell einfach das ist, was gerade hinter der Hand der Person liegt, die die Klappe hält. Schlimmer noch: Eine HBB kann Rotation grundsätzlich nicht abbilden, dafür gibt es schlicht kein Feld, sodass nachgelagerte Schritte wie das Geraderücken der Klappe für die Texterkennung (OCR) keinerlei Hilfe vom Detektor bekommen. Und End-Klappen lassen sich damit auch nicht zuverlässig erkennen.
  • Instance Segmentation: Liefert pixelgenaue Masken, was das Rotationsproblem technisch lösen würde - allerdings sind die Annotationskosten brutal (statt vier Ecken zu ziehen, muss man pro Frame ein Polygon nachzeichnen), und eine pixelgenaue Maske ist mathematisch gesehen völliger Overkill, wenn du eigentlich nur ein sauberes Rechteck zum Zuschneiden und Entzerren brauchst. Dazu kommt: Die Inferenz ist langsamer - ein echtes Problem, wenn der ganze Sinn der Übung Echtzeit-Tracking ist.
  • Oriented Bounding Boxes (OBB): der Gewinner. Ein gedrehtes Rechteck, meist gespeichert als vier explizite Eckpunkte (Ultralytics-Format: class x1 y1 x2 y2 x3 y3 x4 y4, normalisiert) statt als Mittelpunkt plus Rotationswinkel $\theta$. Im Vergleich zu HBB bringt das einen engen Crop ohne verschwendeten Hintergrund (besseres Signal für den OCR-Schritt danach) und die Rotation quasi gratis dazu - die vier Eckpunkte sind der Winkel, da muss nichts extra berechnet werden. Im Vergleich zu Segmentierung bleibt die Annotation bei vier Klicks pro Box statt einem nachgezeichneten Polygon, und die Inferenz bleibt schnell genug für Echtzeit-Tracking. Für ein Objekt, das starr, immer annähernd rechteckig ist und nachgelagert entzerrt werden muss, ist OBB die Darstellung, die am wenigsten Annotationsaufwand kostet und den nützlichsten Output liefert.


2. Die eigene Regeln festlegen

Das ist der Schritt, den man am leichtesten überspringt - und der einen später am teuersten zu stehen kommt, weil er festlegt, was jede einzelne Annotation in deinem Dataset überhaupt bedeutet. „Klappe tracken" ist keine Kategorie. Du musst schriftlich festlegen, bevor du auch nur ein Label setzt:

  • Zwei vollwertige Klassen statt einer Klasse mit Attribut. Ich habe mich für slate_open und slate_closed als zwei komplett getrennte Labels entschieden, statt für eine einzelne slate-Klasse mit einem Offen/Geschlossen-Attribut nebenbei. Eine gemeinsame Klasse mit Attribut ist auf dem Papier die „sauberere" Modellierung - aber Attribute sind eine Funktion des jeweiligen Annotation-Tools und der Trainings-Pipeline, die du gerade benutzt. Sie überleben nicht zwangsläufig einen Wechsel des Exportformats oder eine andere Modellarchitektur. Zwei einfache Klassen sind dagegen der kleinste gemeinsame Nenner: Sie funktionieren später mit so gut wie jedem Setup, auf das du dein Dataset ansetzt - und wenn ein zukünftiges Modell sich nur für einen der beiden Zustände interessiert, kann es einfach nur auf dieser Klasse trainieren und die andere ignorieren.
  • Die Grenze ist einfacher zu ziehen, als es klingt - weil es sie im Grunde kaum gibt. In der Praxis ist eine Klappe ein Scharnier mit zwei Ruhepositionen und verhält sich damit wie ein binärer Schalter: Ist am Scharnier auch nur ein winziger Spalt sichtbar, ist die Klappe slate_open - Punkt, egal wie klein der Spalt ist. Du bewertest keine Öffnungsgrade, du prüfst nur, ob sie bündig zu ist oder nicht. Diese eine Regel löst so gut wie jedes Frame ohne Ermessensspielraum, inklusive der kurzen „gerade erst am Zuklappen"-Frames.
  • Lege auch für Verdeckungen und Teilsichtbarkeit eine explizite Regel fest. Eine Hand, die die Klappe hält, eine Klappe, die halb aus dem Bild ragt, eine Klappe, die sich im Hintergrund in einem Spiegel oder Monitor spiegelt - definiere eine Regel (z. B. annotieren bis zu einem bestimmten Mindest-Sichtbarkeitsanteil, sonst überspringen) und wende sie konsequent an, statt bei jedem Frame neu zu entscheiden.

Warum nicht einfach nur eine slate-Klasse?

Es lohnt sich, hier ehrlich zu sein, denn dieser Trade-off ist nicht umsonst. Wenn man fragt „Performt eine Klasse oder zwei besser", lautet die ehrliche Antwort: Eine Klasse gewinnt meistens, besonders bei einem kleinen bis mittelgroßen Dataset. Ein Ein-Klassen-Modell muss auf Ebene der Kandidaten-Box nur eine binäre Frage beantworten: „Ist das eine Klappe oder Hintergrund?" Ein Zwei-Klassen-Modell muss eine Drei-Wege-Frage beantworten: „Ist das slate_open, slate_closed oder Hintergrund?" - ein bei gleicher Datenmenge strikt schwierigeres Unterscheidungsproblem.

Die Kosten sind konkret. Ein visuell klar erkennbares Objekt in Unterkategorien aufzuteilen zwingt das Modell dazu, die feinen Nuancen zwischen den Zuständen zu lernen (den genauen Scharnierwinkel einer offenen gegenüber einer geschlossenen Klappe), statt einfach zu lernen, was eine Klappe grundsätzlich ausmacht. Ist dein Dataset nicht riesig, wird das Modell slate_open und slate_closed bei Grenzfällen oder ungünstigen Blickwinkeln immer wieder verwechseln - und diese Verwechslung führt nicht nur zu falschen Labels, sondern drückt die Konfidenzwerte insgesamt nach unten, was sich als verpasste Erkennungen (False Negatives) zeigt, weil die meisten Inferenz-Pipelines schon vor der eigentlichen Klassenzuordnung nach einem Konfidenz-Schwellenwert filtern.

Warum diesen Preis in diesem Projekt trotzdem zahlen? Weil hier der Zustand selbst das eigentliche Ziel ist - offen gegenüber geschlossen ist genau das Schnittpunkt-Signal, für das die ganze Pipeline existiert. Eine einzelne slate-Klasse würde das Problem nur eine Stufe weiter nach hinten verschieben: Du bräuchtest trotzdem ein zweites Modell oder eine handgeschriebene Heuristik, die nachträglich genau die eine Frage beantwortet, um die es von Anfang an ging. Wenn dein Use Case nur „hier ist eine Klappe, schneide sie aus" braucht und der Offen/Geschlossen-Zustand das Problem von jemand anderem weiter unten in der Pipeline ist, ist eine einzelne Klasse die bessere Wahl - sie trainiert schneller, konvergiert mit weniger Daten und liefert dir Boxen mit höherer Konfidenz für die zweite Stufe, die du dahinter baust. Zwei Klassen sind eine Entscheidung, die du triffst, weil der Zustand das eigentliche Ergebnis ist - nicht ein Standard, zu dem man automatisch greift.

Das Ganze muss kein offizielles Dokument sein - ein paar Stichpunkte neben deinem Annotation-Tool reichen völlig. Es geht nur darum, dass die Regel existiert und bei Frame 1 genauso gilt wie bei Frame 10.000.


3. Eine durchdachte Sampling-Strategie für Video-Clips

Filmklappen stehen entweder still oder bewegen sich in kurzen, vorhersehbaren Schüben. Wenn man rohes 25-fps-Videomaterial direkt in ein Annotation-Tool kippst, annotierst du am Ende tausende Frames, die optisch praktisch identisch mit ihren Nachbarn sind - und verbrennst damit Stunden an Labeling-Zeit für so gut wie keinen zusätzlichen Informationsgewinn.

  • Der Basis-Clip: In den meisten unserer letzten geshooteten Takes ist die Klappe rund 2 Sekunden im Bild (bei 25 fps also etwa 50 Rohframes).
  • Das Sampling-Intervall: Da wir nicht jedes Bild annotieren wollen und die Datenqualität davon abhängt, dass sich die Bilder tatsächlich unterscheiden, samplen wir jedes 2. Bild. Das ergibt rund 25 annotierte Frames pro Clip - genug, um den kompletten Ablauf abzudecken: offen, in Bewegung, der Moment des Zuschlagens, dann der stabile geschlossene Zustand, ohne Redundanz. Gehst du gröber vor (z. B. nur jedes 5. Frame), riskierst du, genau den kurzen „leicht geschlossen, noch in Bewegung"-Zustand zu überspringen - und das ist exakt der Übergang, von dem dein Modell die meisten Beispiele braucht.
  • Sample nicht blind durch statische Haltephasen. Das Intervall oben setzt Bewegung voraus. Wird die Klappe in einem Take für ein, zwei Sekunden völlig ruhig im Bild gehalten, bevor geklappt wird, erzeugt ein 2er-Sampling dort nur eine Serie von Fast-Duplikaten. Ein kurzer Blick hilft, visuell identische Serien auszudünnen - die investierten paar Minuten sind an anderer Stelle besser angelegt, etwa für ein anderes Lichtsetup oder einen weiteren Take.
  • Hintergrund- und Negativ-Frames: Trainiere einen Model nie ausschließlich mit positiven Beispielen (nur Bilder mit klappen), sonst fängt er an, überall Phantom-Klappen zu halluzinieren. Ziel sind 15-20 % deines Datasets als leere Frames - rund 4-6 pro Clip. Ganz ohne eine Box.
  • Lass deine Negativ-Beispiele als Hard Negatives zählen, nicht nur als leere Räume. Eine schlichte Aufnahme einer Wand bringt dem Modell fast nichts, was es nicht ohnehin schon weiß. Frames mit anderen rechteckigen, kontrastreichen Objekten - Klemmbretter, Laptops, Monitore, Whiteboards, Notizbücher - sind deutlich wertvollere Negativbeispiele, weil genau das die Dinge sind, die dein Modell später am ehesten mit einer Klappe verwechselt.
  • Diversität auf jeder Achse - nicht nur bei der Frame-Anzahl. Kameraabstand und -winkel, Lichtsetup (Tageslicht, Kunstlicht, Low-Light-Bedingungen am Set), das physische Design der Klappe (Kreide, Whiteboard, digitale/Smart Slate), Hände und Hautfarben der Personen, die die Klappe halten, sowie das Ausmaß an Motion-Blur beim Zuklappen wirken sich stärker auf die Generalisierung aus als die reine Bildanzahl. Zwanzig Takes über fünf verschiedene Lichtsetups schlagen hundert Takes aus demselben Raum - immer.


4. Splits erstellen, ohne in die Zukunft zu spicken

Das ist der Teil, den man bei videobasierten Daten wirklich leicht übersieht - und der Fehler zeigt sich nicht als offensichtlicher Bug, sondern als Validation Score, der fantastisch aussieht, während das Modell bei echtem, ungesehenem Material still und leise schlechter performt.

Die Falle: Wenn du 25 Frames aus einem Clip samplest und dann Frames zufällig auf Train/Val aufteilst, landet zum Beispiel Frame 14 im Training und Frame 15 - fast pixelidentisch - in der Validation. Deine Validation-Metrik misst dann, wie gut sich das Modell genau diesen einen Take gemerkt hat, nicht wie gut es generalisiert. Sieht fantastisch aus, sagt aber kaum etwas aus.

  • Splitte nach Take/Clip, nie nach Frame. Alle Frames eines Clips gehören komplett ins Training, komplett in die Validation oder komplett ins Test-Set - niemals aufgeteilt auf zwei davon.
  • Ein vernünftiges Startverhältnis liegt bei 70-80 % Training / 15-20 % Validation / 10-15 % Test, auf Clip-Ebene, anpassbar, sobald du siehst, wie viele unterschiedliche Takes du tatsächlich hast. Tendiere erst dann zum oberen Ende der Trainings-Spanne, wenn du genug Clips hast, dass Validation und Test trotzdem noch eine statistisch aussagekräftige Anzahl an Takes enthalten - ein 90/5/5-Split klingt effizient, aber wenn die 5 % Test nur zwei Clips sind, kann ein einziger ungewöhnlicher Take dein Test-mAP massiv verschieben, ohne dass du sagen kannst, ob das real ist oder nur Rauschen.
  • Jeder Split sollte das gleiche Verhältnis von gelabelten zu negativen Frames beibehalten wie das Gesamt-Dataset, nicht nur die gleiche Gesamtgröße. Ziel sind rund 90-95 % gelabelte (positive) Frames zu 5-10 % ungelabelten/negativen Frames in Training, Validation und Test einzeln betrachtet - siehe Abschnitt 5 für die genaue Berechnung, statt es nur über den Daumen zu peilen. Landen deine Negativbeispiele alle im Training, weil du sie dort zuletzt ergänzt hast, testen Validation und Test gar nicht mehr, ob das Modell Phantom-Klappen vermeidet - sondern nur, ob es das bei den Takes richtig macht, mit denen es trainiert wurde.
  • Stratifiziere den Split über deine Diversitäts-Achsen, nicht nur zufällig nach Clip. Landen zufällig alle deine Low-Light-Takes oder Takes mit ungewöhnlichem Klappendesign im Training, sieht dein Validation Score besser aus als die Realität - und du merkst es erst beim Deployment.
  • Halte mindestens ein bis zwei Clips mit einem Klappendesign oder Setup zurück, das das Modell sonst nirgendwo zu sehen bekommt - exklusiv fürs Test-Set. Das ist dein eigentlicher Generalisierungs-Check, unabhängig von der Frage „hat es diese konkreten Takes gelernt", die Train/Val beantwortet.


5. Dataset-Größe und die Mehr-ist-besser-Falle

Wie viele Bilder brauchst du eigentlich wirklich? Weil eine Filmklappe einen hohen visuellen Kontrast und eine starre, klar definierte Struktur hat, brauchst du keine Millionen Bilder für solide Performance.

  • Proof of Concept: 200-300 Bilder (etwa 8-12 vollständig annotierte Takes) reichen, um ein Basismodell zum Laufen zu bringen und die gesamte Pipeline zu validieren.
  • Der Production-Grade-Sweetspot: 500-1.000 Bilder (20-40 Takes plus Backgrounds). Ab hier bekommst du echte Varianz bei Licht, Brennweite und Motion-Blur - genug, um auch mit unordentlichen Realweltbedingungen klarzukommen.
  • Ist mehr immer besser? (Die 2.000+-Bilder-Frage): Technisch gesehen kannst du ein modernes YOLO-Modell bei 2.000+ Bildern nicht komplett overfitten. Aber du landest schnell im Bereich, in dem mehr daten keinen großen Ertrag bringen. Filmklappen und Set-Umgebungen sind von Natur aus visuell repetitiv, weshalb dir tausende zusätzliche, ähnliche Frames nur sehr wenig zusätzlichen mAP (Mean Average Precision - die Standard-Genauigkeitsmetrik für Detection-Modelle, gemittelt über Klassen und Konfidenz-Schwellenwerte) einbringen, dafür aber jede Menge zusätzliche Annotationszeit kosten. Ein diverses, gut gesampeltes Set aus 600-800 Bildern schlägt in der Regel ein größeres, aber repetitives Set.
  • Diese Zahlen gelten pro Klasse, nicht pro Dataset. Mit slate_open und slate_closed als zwei getrennten Klassen braucht jede ihren eigenen Anteil an soliden Beispielen - 600 Bilder, die sich 90/10 auf beide verteilen, sind kein 600-Bilder-Dataset, sondern faktisch ein 60-Bilder-Dataset für den unterrepräsentierten Zustand. Da eine geschlossene Klappe pro Take nur einen Bruchteil der Zeit im Bild ist, die eine offene Klappe im Bild ist (das Sampling-Intervall aus Abschnitt 3 fängt naturgemäß mehr „offen"- als „geschlossen"-Frames ein), behalte die Klassen-Anzahl unterwegs im Blick, nicht nur die Gesamtsumme.

Ein Rechenbeispiel: von Klassen-Zielwerten zu Split-Zahlen

Die Zahlen oben sind als Zielwerte hilfreich, aber „600-800 Bilder pro Klasse" in eine tatsächliche Ordnerstruktur über Train/Val/Test zu übersetzen, braucht ein paar Rechenschritte. Hier die Formel, danach ein Rechenbeispiel mit dem slate_open/slate_closed-Split aus diesem Projekt.

Schritt 1 - Gesamtzahl gelabelter Bilder. Addiere deine Zielwerte pro Klasse (angepasst, wie oben erwähnt, weil slate_closed pro Take naturgemäß unterrepräsentiert ist):

plaintext
Gesamt gelabelt = Summe der Zielwerte pro Klasse
Beispiel: slate_open 1.500 + slate_closed 1.000 = 2.500 gelabelte Bilder

Schritt 2 - Die Negativ-Frames zurückrechnen. Negative Frames sind ein Prozentsatz des gesamten Datasets (Abschnitt 3), nicht nur des gelabelten Anteils, also nach dem Gesamtwert auflösen:

plaintext
Gesamt-Dataset = Gelabelte Bilder / (1 - Negativ-Anteil)
Beispiel bei 8 % Negativen: 2.500 / 0,92 ~= 2.717 -> aufgerundet 2.720 gesamt, ~220 negativ

Schritt 3 - Das Split-Verhältnis auf Clip-Ebene anwenden (Abschnitt 4). Bei 75/15/10 als Mittelwert der obigen Spannen:

  • Training (75 %): 2.040 Bilder
  • Validation (15 %): 408 Bilder
  • Test (10 %): 272 Bilder

Schritt 4 - Klassenverteilung und Negative innerhalb jedes Splits proportional verteilen - nicht nur über das Gesamt-Dataset hinweg:

Split

slate_open

slate_closed

Negative

Gesamt

Training (75 %)

1.125

750

165

2.040

Validation (15 %)

225

150

33

408

Test (10 %)

150

100

22

272

Gesamt

1.500

1.000

220

2.720

Bei dieser Tabelle anzukommen ist keine reine Rechnerei im Nachhinein - genau deshalb sind die Regeln aus Abschnitt 4, „nach Clip splitten, nicht nach Frame" und „über die Diversitäts-Achsen stratifizieren", in der Praxis so wichtig. Um auf diese Zahlen zu kommen, musst du beim Annotieren pro Clip mitverfolgen, wie viele Frames jeder Klasse und wie viele Negative er beisteuert - nicht erst am Ende auf einen Trainingsordner schauen und hoffen, dass die Verhältnisse gepasst haben.


6. Annotationsqualität: enge Boxen, konsistente Ecken

Volumen und Sampling-Strategie sorgen für diverse Daten - das hier ist es, was jede einzelne Annotation tatsächlich wertvoll macht.

  • Ziehe die Boxen eng an die physischen Kanten der Klappe, nicht an ihren Motion-Blur-Schleier. Das ist bei OBB wichtiger als es je bei achsenparallelen Boxen war, weil das Modell nicht nur „Objekt hier" lernt, sondern aus deiner Eckenplatzierung den exakten Rotationswinkel - schlampige Ecken bringen ihm einen schlampigen Winkel bei.
  • Halte die Reihenfolge der Eckpunkte über alle Frames hinweg konsistent. Da OBB als vier explizite Eckpunkte gespeichert wird, kodiert die Reihenfolge dieser Punkte implizit die Ausrichtung. Kippt diese Reihenfolge von einem Frame zum nächsten (was bei unachtsamer manueller Korrektur exportierter Labels passieren kann), bringst du dem Modell für eine eigentlich glatte, kontinuierliche Rotation zwei widersprüchliche Vorstellungen davon bei, wohin die Box „zeigt". Die meisten Annotation-Tools halten die Reihenfolge standardmäßig automatisch konsistent - der Fehler entsteht so gut wie immer durch nachträgliches manuelles Bearbeiten der Label-Dateien, nicht durch das Tool selbst.
  • Nutze Interpolation bei Video, aber vertrau ihr nicht blind. Die meisten modernen Annotation-Tools können die Position einer Box zwischen zwei manuell gesetzten Keyframes interpolieren - bei einer bewegten Klappe eine riesige Zeitersparnis. Stichprobe die interpolierten Frames trotzdem, besonders im schnellen Teil der Bewegung rund um den Aufschlag - genau dort neigt lineare Interpolation dazu, von der tatsächlichen Position abzudriften.
  • Labeln mehrere Personen, schreibt eure Regeln auf (siehe Abschnitt 2) und macht regelmäßig Stichproben im Team. Drift zwischen den Personen, die labeln, bei einem unscharfen Grenzfall bleibt unsichtbar - bis du vor einer Confusion Matrix sitzt und dich fragst, warum sich das Modell nicht entscheiden kann.


7. Der Active-Learning-Loop: das Modell beim Labeln mithelfen lassen

Jedes Frame von Grund auf von Hand zu labeln skaliert nicht, und ab einem gewissen Punkt musst du das auch gar nicht mehr. Sobald du auch nur ein grobes Modell hast, ist es ein schnellerer Annotator als du selbst - deine Aufgabe verschiebt sich vom Zeichnen der Boxen zum Korrigieren. Das ist der Loop, mit dem dieses Dataset tatsächlich entstanden ist:

  1. Clips schneiden. Shutter Encoder, um die rohen Takes auf die rund 2-Sekunden-Fenster mit der Klappe aus Abschnitt 3 zuzuschneiden, damit du nicht Stunden an totem Material in dein Annotation-Tool importierst.
  2. Die Clips importieren und einen Seed-Set von Hand labeln. Die Clips in CVAT laden und den ersten Batch manuell annotieren - rund 100 gelabelte Frames reichen zum Start. Nutze CVATs Rectangle Tracking (Interpolation zwischen manuell gesetzten Keyframes, siehe Abschnitt 6), sodass du Boxen nur auf dem ersten und letzten Frame einer Bewegung setzt und das Tool den Rest auffüllt, statt jedes einzelne Frame von Hand zu annotieren.
  3. Exportieren und trainieren. Den gelabelten Datensatz mit meinem eigenen Tool, Dataset Studio, exportieren und ein erstes Modell trainieren. Bei rund 100 Bildern wird dieses Modell noch grob sein, muss es aber auch nicht - es muss nur besser sein als gar keine Annotation.
  4. Den nächsten Batch automatisch annotieren lassen. Das erste Modell auf den nächsten Batch ungelabelter Clips ansetzen, statt wieder komplett von Hand zu zeichnen, und die Auto-Annotation anstoßen. CVAT unterstützt modellgestützte Annotation direkt, oder du servierst dein eigenes Modell über Nuclio und bindest es als richtige, serverlose Annotationsfunktion in CVAT ein statt als Einmal-Script - so oder so schlägt das Modell die Boxen vor, und du korrigierst nur noch, statt von null zu erstellen, was ein großer Geschwindigkeitsgewinn ist, sobald die Konfidenz des Modells bei der Mehrheit der einfachen Frames hoch genug ist.
  5. Prüfen, korrigieren, neu trainieren, wiederholen. Korrigiere, was das Modell falsch gemacht hat - das ist gleichzeitig dein bestes Signal dafür, wo die Taxonomie oder die Sampling-Strategie aus den Abschnitten 2-3 noch Schwächen hat; scheitert das Modell ständig an gekippten End-Klappen, geh und finde mehr gekippte End-Klappen. Den korrigierten Batch in den Trainingsdatensatz einfließen lassen und neu trainieren. Jeder Zyklus vergrößert sowohl das Dataset als auch verbessert das Modell, das die Vor-Annotation übernimmt - der Loop verstärkt sich also selbst, spätere Batches kosten nur noch einen Bruchteil des manuellen Aufwands der ersten 100 Bilder.

Worauf du achten solltest: Lass die Fehler des Modells nicht stillschweigend zu Trainingsdaten werden. Eine falsch automatisch annotierte Box, die unkorrigiert bleibt, bringt dem nächsten Modell denselben Fehler mit noch mehr Konfidenz bei. Prüfe automatisch annotierte Batches mindestens so sorgfältig wie die erste Arbeitswoche einer neuen annotierenden Person - eher noch sorgfältiger, denn ein Modell wird nicht automatisch besser, nur weil man ihm im Nachhinein „richtig" oder „falsch" sagt - jemand muss überhaupt erst bemerken, dass eine Korrektur nötig war.


Quellen und hilfreiche Videos

Dataset mit CVAT erstellen | YOLO Object-Detection-Modelle trainieren | CVAT - Annotation mit Hugging Face beschleunigen