Bogenschießen

Ein Freund von mir ist hobbymäßig Bogenschütze. Er fragte mich, ob ich nicht eine App schreiben kann, so dass er mit dem Handy ein Bild von der Zielscheibe machen kann und automatisch daraus erkannt wird, welche Pfeile wo getroffen haben, und wie viele Punkte er damit bekäme. Hier ist der aktuelle Stand:

Erstmal hat er mir ein paar Beispielbilder geschickt, wie das überhaupt aussieht:

Meine Idee für die Verarbeitung:

Erst finden wir die Zielscheibe im Bild, um die es geht (die in der Mitte). Dann finden wir die Pfeile in der Scheibe und zuletzt bestimmen wir wie viele Punkte jeder Pfeil bekommt. Dabei gilt: Pfeile im gelben Bereich bringen 10 Punkte, im roten Bereich 8 und im blauen Bereich 6. Wenn Pfeile genau auf den Rand zwischen zwei Bereichen treffen, dann soll der größere Wert zählen.

Ansatz 1: Zielscheibe finden durch Finden von Ellipsen

Wir wollen erstmal die Zielscheibe finden. Diese besteht ja im Wesentlichen aus Kreisen verschiedener Größe um den gleichen Mittelpunkt. Aber weil die Bilder nicht direkt von Vorne aufgenommen werden, sondern von zum Beispiel links oben, ist die Darstellung verzerrt. Und das, was von Vorne ein Kreis gewesen wäre, ist jetzt eine Ellipse. Dafür gibt es auch schon vorgefertigte Funktionen, um diese in Bildern zu erkennen. Das sieht dann zum Beispiel so aus:

Ich habe die gefundenen Ellipsen in einer ähnlichen Farbe eingezeichnet, wie der Bereich, den sie umfassen sollen. Ich fand das Ergebnis nicht gut genug. Es gibt zu viele Ellipsen, die gar nicht passen, und die anderen passen nur sehr grob. Deshalb habe ich diesen Ansatz verworfen.

Ansatz 2: Zielscheibe finden durch Vergleich mit einer Musterzielscheibe.

Wir nehmen das Bild einer Musterzielscheibe, und legen dieses über unser Bild, der schon beschossenen Scheibe.

Dann schieben wir das Muster über das ganze Bild, bis es am besten passt – also bis der Ausschnitt, den wir gerade betrachten, dem Muster möglichst ähnlich ist. Dabei gibt es mehrere Schwierigkeiten: Das Muster hat eine feste Größe und ist von vorne aufgenommen, das Bild der beschossenen Scheibe aber nicht. Das Bild mit den Pfeilen ist nicht von exakt vorne aufgenommen, sondern im Beispiel etwas von links oben, und je nachdem von wie nah ist die Scheibe eben größer oder kleiner. Also erstellen wir uns viele Musterzielscheiben, in verschiedenen Größen! Und es gibt Funktionen, die das Bild so verzerren (warpen), dass es aussieht, als hätte man es nicht von vorne, sondern zum Beispiel von 10° oben und 2° links aufgenommen. Und für viele verschiedene Perspektiven und Größen erstellen wir viele Muster. Und von allen diesen Mustern schauen wir, was am besten zum Bild passt. Wir gehen davon aus, dass der Fotograf die Kamera so hält, dass einer der Bildränder nach unten zeigt. Andernfalls müssten wir auch noch Drehungen um die optische Achse beachten.

Finden wir damit die Zielscheibe?

Das sieht doch gut aus! Jetzt haben wir schonmal den Bildausschnitt mit der Zielscheibe gefunden – später verwenden wir das, um das Bild zurecht zu schneiden.

Wie gut passt das Muster auf das Bild? Dafür habe ich das Original genommen, und das am besten passende Muster darüber gelegt und dann das Muster vom Original ‚abgezogen‘. Das heißt da wo das Ergebnis schwarz ist, waren Muster und Original gleich, und wo nicht, da hat sich etwas unterschieden.

Und wie man sieht, sind sich die beiden Bilder zwar ähnlich, aber es gibt noch Unterschiede: Klar, die Pfeile sind auffällig, aber auch die Kreise passen nicht genau. Beim gelben Kreis gibt es oben und unten die Bereiche in grün, weiter Außen vier Bereiche in pink und ganz weit außen Bereiche in Orange, die zeigen, wo die beiden Bilder noch nicht passen. Um exakt zu bestimmen, wo der Pfeil genau getroffen hat, ist das noch nicht gut genug.

Ansatz 3: Farbbasiertes finden der Trefferzonen auf der Zielscheibe

Wir wissen ja, die Zielscheibe ist innen gelb, dann rot, dann blau. Das nutzen wir. In Pixel-Farben, zum Beispiel mit RGB ausgedrückt, ist aber gar nicht so leicht festzulegen, was als blau zählt und was nicht. Man muss wegen der Beleuchtung flexibel sein und deshalb Farbbereiche angeben, um bei beliebigen Lichtverhältnissen die Bereiche richtig zu erkennen. So erstellen wir Filter, welche nur die Bereiche zeigen, bei denen ihre Farbe im Original zu sehen ist. Das sieht dann für gelb so aus, wir machen das aber auch für rot und blau.

Wenn man das für alle drei Farben macht, und daraus ein Bild erstellt, dann sieht das so aus:

Da sieht man gut die farbigen Zonen der Zielscheiben. Der Hintergrund und auch die Pfeile sind großteils schwarz, so dass man die Pfeile erkennen kann. Als nächstes wollen aber nicht wir selbst, sondern unser Programm soll die Pfeile erkennen. Dazu nutzen wir zunächst ein Verfahren zur Kantenerkennung. Dafür suchen wir nach zwei fast parallelen Kanten, die nah beieinander liegen, und die in der Nähe der Bildmitte plötzlich aufhören – das entspricht nämlich genau den schmalen, langen Pfeilen, die in der Zielscheibe in der Bildmitte enden.

Die gefundenen Kanten habe ich grün markiert, und da, wo eine Kante endet, habe ich einen kleinen Punkt eingefügt. Wenn da nur eine Kante aufhört, dann ist der Punkt rot und die Kante gehört nicht zu einem Pfeil. Blaue Punkte sind solche, für die es zwei Kanten gibt, die also zu einem Pfeil gehören. Wir haben also die Pfeile erkannt!

Bleibt noch die Frage wie viele Punkte jeder Pfeil gibt! Dazu nehmen wir das Kantenpaar von einem Pfeil und schauen uns die beiden Endpunkte an. Außerdem verwenden wir nochmal unsere Masken von vorhin. Und zwar schauen wir, welche Maske genau da aktiv war, wo die Endpunkte liegen. Und je nachdem, ob gelb rot, oder blau, werden die Punkte für die Pfeile erkannt. Im blauen Bereich 6 Punkte, im roten 8 und im gelben 10 Punkte. Und wenn die beiden Enden in verschiedenen Bereichen liegen, dann zählt der Bereich, der mehr Punkte bringt.

Um zu prüfen, welcher Pfeil wie viele Punkte gebracht hat, haben wir die blauen Punkte da gelassen und die Punktzahlen zu den Pfeilenden geschrieben. Funktioniert!

Vielen Dank an alle Beteiligten für die Mithilfe beim Fotografieren und beim Entwickeln der Software! Wir haben Python und OpenCV verwendet.