Persönliches Projekt · Computer Vision
Football Analysis System
Ein Programm, das sich einen Spielausschnitt anschaut und daraus selbst herausliest, wer auf dem Feld steht, zu welchem Team er gehört, wie schnell er läuft und welches Team gerade den Ball hat.
Das Ergebnis: jeder Spieler bekommt eine Ellipse in seiner Teamfarbe und eine eigene Nummer, darunter Tempo und zurückgelegte Strecke. Das grüne Dreieck ist der Ball, das rote markiert den Spieler, der ihn gerade führt. Unten rechts läuft der Ballbesitz beider Teams mit.
Über das Projekt
Ich schaue selbst gern Fussball, und mich hat schon lange interessiert, wie die Analysen entstehen, die man im Sportfernsehen eingeblendet sieht: Laufwege, Sprintgeschwindigkeiten, Ballbesitzanteile. Also habe ich mir vorgenommen, so etwas selbst zu bauen, mit einem 30-Sekunden-Ausschnitt aus einer TV-Übertragung als Testmaterial.
Herausgekommen ist eine Verarbeitungskette in Python: Sie liest das Video Bild für Bild ein, erkennt darin Personen und den Ball, verfolgt sie über die Zeit hinweg, teilt die Spieler anhand der Trikotfarbe in zwei Teams, rechnet die Bildpunkte in echte Meter auf dem Spielfeld um und schreibt am Ende ein fertig beschriftetes Video zurück.
Das Ganze läuft komplett auf der CPU meines Laptops, ohne Grafikkarte und ohne selbst trainiertes Modell. Genau diese Einschränkung hat den grössten Teil der Arbeit ausgemacht: Ein kleines, allgemeines Modell liefert unsaubere Ergebnisse, und die musste ich in der Nachverarbeitung wieder gerade ziehen.
In Zahlen
901
Einzelbilder, die pro Durchlauf verarbeitet werden
7
Verarbeitungsschritte vom Rohvideo bis zum fertigen Ergebnis
96
verbliebene Spieler-IDs nach dem Tracking-Fix (vorher waren es 2217)
Wie ich vorgegangen bin
Ich habe nicht versucht, alles auf einmal zum Laufen zu bringen, sondern eine Schicht nach der anderen gebaut und nach jeder Schicht Einzelbilder herausgeschrieben und angeschaut. So habe ich jeden Fehler dort gefunden, wo er entstanden ist, und nicht erst am fertigen Video.
Video ein- und auslesen: die Grundlage, auf der alles andere aufsetzt.
Erkennen und Verfolgen: YOLOv8 findet Personen und Ball in jedem Bild, ByteTrack verbindet sie über die Bilder hinweg zu durchgehenden Spuren.
Teams zuordnen: ein Clustering-Verfahren teilt die Trikotfarben in zwei Gruppen und weist so jedem Spieler ein Team zu.
Kameraschwenks herausrechnen: sonst „läuft" ein stehender Spieler, sobald die Kamera mitzieht.
Perspektive umrechnen: aus der schrägen Kameraansicht wird eine Draufsicht, damit Bildpunkte zu echten Metern werden.
Tempo und Strecke: aus den Positionen in Metern über die Zeit ergeben sich Geschwindigkeit und zurückgelegte Distanz.
Ballbesitz: der Spieler, der dem Ball am nächsten ist, bekommt ihn zugeordnet; daraus wächst der Ballbesitzanteil beider Teams.
Probleme und wie ich sie gelöst habe
Die Spielernummern sprangen im Sekundentakt
Beim ersten Durchlauf vergab das Programm 169 verschiedene Nummern für rund 22 Spieler in 30 Sekunden. Eine Nummer hielt im Schnitt etwa eine Sekunde, dann galt derselbe Spieler als neue Person. Damit war jede Distanzmessung wertlos.
Meine erste Änderung machte es schlimmer: Plötzlich waren es 2217 Nummern. Ich hatte den Schwellwert in die falsche Richtung gedreht. Statt weiter zu raten, habe ich in der Dokumentation nachgelesen und dort den entscheidenden Satz gefunden: Ein niedrigerer Wert führt zu mehr Zerfall, nicht zu weniger.
Lösung: Den Wert in die andere Richtung angehoben und dem Verfahren zusätzlich erlaubt, einen kurz verdeckten Spieler länger im Gedächtnis zu behalten. Ergebnis: 96 statt 2217 Nummern, und eine Spur hält jetzt im Median gut doppelt so lange.
Spieler mit 89 km/h
Nach dem Tracking-Fix stimmten die Nummern, aber einzelne Spieler rannten laut Anzeige schneller als der Weltrekord über 100 Meter. Die Ursache liegt in der Umrechnung von Bildpunkten in Meter: Sie beruht auf vier Eckpunkten des Spielfelds, die ich von Auge gesetzt habe. Kleine Ungenauigkeiten wirken sich je nach Bildbereich unterschiedlich stark aus.
Lösung: Eine Plausibilitätsgrenze. Alles über 38 km/h (deutlich über Spitzensprinter-Tempo) wird als Mess- oder Kalibrierfehler verworfen, statt angezeigt und in die Gesamtstrecke eingerechnet zu werden. Die Werte sind damit realistisch, aber ich schreibe bewusst dazu: sie sind geschätzt, nicht vermessen.
Die Kamera bewegt sich, die Spieler scheinbar auch
Bei einer TV-Übertragung schwenkt die Kamera dem Ball hinterher. Für das Programm sieht das zunächst so aus, als würde sich das ganze Spielfeld verschieben: Ein stehender Spieler sammelt so Strecke, ohne einen Schritt zu machen.
Lösung: Ich messe die Kamerabewegung selbst. Dafür verfolge ich markante Punkte in Bildbereichen, die zum Spielfeldrand gehören und sich nicht von selbst bewegen. Deren Verschiebung von Bild zu Bild ist die Kamerabewegung, und die ziehe ich von allen Spielerpositionen wieder ab.
Kein Grafikprozessor, kein Fussball-Modell
Mein Laptop hat keine dedizierte Grafikkarte, und ein fertig trainiertes Modell, das Spieler, Schiedsrichter und Ball unterscheidet, stand mir nicht zur Verfügung. Selbst eines zu trainieren hätte beschriftete Trainingsdaten und Rechenzeit gebraucht, die ich beide nicht hatte.
Lösung: Ich nehme das kleinste allgemeine Modell, das bereits „Person" und „Ball" kennt, und hole alles Weitere aus der Nachverarbeitung: Teams über die Trikotfarbe, Ballzuordnung über die Distanz. Das läuft auf der CPU. Der Preis dafür sind unruhigere Erkennungen, genau die Ungenauigkeit, gegen die die drei Punkte oben ankämpfen.