Computer-Schach per PiCam

Ich wollte gerne gegen einen elektronischen Schachgegner auf einem konventionellen Brett spielen. Die Züge sollten nicht per Hand in eine Software eingegeben, sondern automatisch übermittelt werden, ohne das Spiel mit Sensoren und Elektronik zu versehen und verkabeln zu müssen. Ein wertiges Schachbrett und Figuren waren auch schon da, da wollte ich nicht mit diversen Umbauten eingreifen.

Deshalb sollte eine Kamera die Überwachung der Spielfläche übernehmen. Ein Raspberry Pi mit PiCam erschien als richtig gut geeignet. Nutzt man Python, kann man schließlich auch eine Reihe von Chess-Engines als virtuellen Gegner einbinden.

So ist im Projekt ein Aufbau entstanden, bei dem der Pi mit seiner Kamera von oben auf die Spielfläche schaut, mittels Imagemagick die Bilder aufbereitet und die erkannten Züge der Schachengine Stockfish übermittelt.

Das für unsere „chess cam“ erdachte, recht einfache Konzept für die Erkennung der Züge hat nach einigen wenigen Anpassungen gut funktioniert. Zuerst wird eine Aufnahme der Grundstellung gemacht. Ist unsere Software bereit, fordert sie zum Zug auf. Hat man gezogen, quittiert man das mit einer Taste, analog dem Tippen auf die Schachuhr. Damit weiß die Anwendung, dass sie ein nächstes Foto machen kann.
Dann werden erste und zweite Aufnahme verglichen, indem ein Differenzbild erstellt wird. Das wird dann Ausschnitt für Ausschnitt abgetastet, so dass man hinterher weiß, auf welchen Feldern sich etwas verändert hat. Diese Felder sind also Anfang und Ende des Zuges einer Spielfigur. Wo sich der Anfang befindet, kann die Software leicht feststellen, denn die Positionen jeder Spielfigur sind in einer Matrix vermerkt. Die wird jetzt aktualisiert und der ermittelte Zug an die Chess-Engine übergeben.

Jetzt macht der Computergegner seinen Zug. Ist er fertig, bekommt man den Zug über das Display mitgeteilt. Die gegnerischen Figuren muss man jetzt nachrücken. Ist das gemacht, quittiert man wieder. Und jetzt darf alles von vorn losgehen, bis der Computergegner das Ende der Partie festgestellt hat.

Nun muss man dafür sorgen, dass die Konstruktion in ausreichender Höhe angebracht ist, so dass die Kamera das Bild komplett erfassen kann. Da ist man gut beraten, Beleuchtung und Bilderstellung separat zu testen. Um zum Beispiel festzustellen, ob genügend Kontrast zwischen Figuren und Feldern vorhanden ist, damit die Auswertung auch funktioniert. Für den Aufbau des Ganzen braucht es wie immer etwas handwerkliches Geschick, die benötigten Teile zusammenzufügen.

Bei uns sitzt der Pi rückwärtig am TFT-Display, für das in der oberen Gehäuseplatte ein Ausschnitt eingeschnitten wurde. Für die Nutzereingaben per Funktastatur steckt ein Sender an einem USB-Port vom Pi.

Das Gehäuse enthält noch einen DC/DC-Wandler, der die 12V für die LED-Beleuchtung nach unten bereitstellt. Somit braucht es nur eine Verbindung nach draußen zu einem 5V-Steckernetzteil und alles ist sehr übersichtlich. Im unteren Gehäusedeckel sitzt auch noch eine kreisrunde Aussparung für die Kamera.

Unsere Software ist ein Python-Skript, welches nach dem Einschalten und Hochfahren des Pi gestartet wird. Dafür haben wir es in /etc/rc.local untergebracht.

Die Aufbereitung der Bilder mit Imagemagick umfasst bei uns das Zurechtschneiden, Entzerren und einen Weißabgleich. Zum Beispiel schneiden wir uns am Anfang aus der ersten Aufnahme der PiCam das eigentliche Schachbrett quadratisch heraus:

$ envstr=“convert „+basedir+“start.jpg“+“ -crop 1400×1400+517+20 „+basedir+“start_crop.jpg“
$ os.popen(envstr)

Erst am Ende geschieht die Differenzbildung mit dem Vorgängerbild. Am Ende erhält man ein Differenzbild mit nur zwei Farben, im Bild hier Weiß und Rot für die veränderlichen Bestandteile. Das kann man nun über alle 8×8 Felder abtasten.

Ausgewertet wird bei uns, ob sich ein bestimmter Prozentsatz an Pixeln im Zentrum einer der 64 Felder vor und nach einem Zug geändert hat. Die Ergebnisse gehen in ein Koordinatensystem über. So werden auch Rochaden bemerkt.

Wie alles genau geschieht, ist aus dem Quelltext ersichtlich. Das Skript für den RPi findet man auf Git-Hub unter https://github.com/swenae/chesscam .

Die Voreinstellungen sind so, dass man selbst mit den weißen Figuren spielt. Im folgenden Bild hat gerade Schwarz einen Springer von g8 nach f6 gezogen. Unser Display zeigt nach einem Zug von Weiß oder Schwarz jeweils ein neues Board in ASCII-Grafik an.

Dadurch kann auch in einem Terminalfenster auf einem Rechner im Netzwerk gespielt werden, wo man sich vorher per ssh auf dem RPi eingeloggt und das chesscam-Skript gestart hat. Das Interface sieht im Terminal gleich aus.

Die Stockfish-Bibliothek ist fest eingebunden, aber man kann den Import auch modifizieren, um gegen andere Engines spielen zu können, die nach dem UCI-Standard funktionieren. Ein neues Game und Board lässt sich unter der chess-Bibliothek in Python so kreieren:

$ engine = chess.uci.popen_engine(„stockfish“)
$ command = engine.uci(async_callback=True)
$ command.result()

$ command = engine.ucinewgame(async_callback=True)
$ command.result()
$ board = chess.Board()

Als Hobby-Schachsportler wird man kaum gegen so eine Schachengine gewinnen können. Da hilft, die Zeiten für das „Nachdenken“ vom elektronischen Gegner herabzusetzen. Und man kann auch noch an weiteren Parametern drehen. Für mich mehr wichtig, dass die Kamera-Abtastung vom Schachbrett funktioniert hat.

Bei uns ist nun ein Aufbau entstanden, wo Gehäuse und Kamera etwa 60cm über dem Brett angebracht sind. Darauf ist auch die Kalibrierung bei der Bildverarbeitung abgestimmt. Ändert man seinen Aufbau bezüglich der Abstände oder der Brettgröße, muss man in der Programmierung wieder nachbessern.

Die zusätzliche Beleuchtung nach unten hilft, immer gleiche Lichtverhältnisse für die Aufnahmen zu haben. Steht das Ganze in einer schattigen Ecke im Raum, umso besser. Dass bei den Aufnahmen auch keine Hand störend im Bild ist, wird dadurch sichergestellt, dass immer knapp nach dem Quittieren fotografiert wird. Der Taster auf der Schachuhr ist bei uns eine Taste auf der angebundenen Funktastatur.

Nach dem Einschalten kann man gleich loslegen. Und es macht richtig Spaß zu sehen, wie der gerade bestätigte Zug erkannt und an die Chess-Engine übermittelt wird. Dass man deren Antwort nachsetzen muss, ist wohl nur ein kleiner Nachteil, wo man doch auf sämtliche Mechanik verzichten kann…

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.