Dies ist eine alte Version des Dokuments!
Die Kamera könnte beim Erfassen von farbigen Spielfeldern Probleme aufweisen, da sie die Farbsättigung reduziert
Im Vordergrund zu sehen ist die Original-Flasche, während auf dem Bildschirm die blassere Version vorzufinden ist, welche doch eher der Medium-Wasserflasche daneben ähnelt.
import cv2
#bild aufnehmen c = cv2.VideoCapture(1) x=c.read() #bild anzeigen win=cv2.namedWindow("Anzeige") cv2.imshow("Anzeige",x[1]) cv2.waitKey(0) #damit gewartet wird, waerend das Bild angezeigt wird
Ziel bis nächste Woche:
Heute haben wir am Programmcode gearbeitet, sodass der Computer unser Bild in Graustufen, sowie Schwarz-Weiß, direkt von der Kamera wiedergibt. Mit der Harris Corner Detection aus OpenCV ist es uns außerdem gelungen sowohl maßgeschneiderte Beispielbilder eines Mühle-Spielbretts von Google, als auch unser selbsterstelltes Spielfeld erkennen zu lassen.
Die gefundenen schnittpunkte sind blau markiert
Finden von Schnittpunkten
import cv2 import numpy as np from matplotlib import pyplot as plt img= cv2.VideoCapture(1) x=img.read() farbbild = x[1] graubild = cv2.cvtColor(farbbild, cv2.COLOR_BGR2GRAY) graubild = np.float32(graubild) dst = cv2.cornerHarris(graubild,2,3,0.04) result is dilated for marking the corners, not important dst = cv2.dilate(dst,None) #Threshold for an optimal value, it may vary depending on the image. farbbild[dst>0.01*dst.max()]=[255,0,0] cv2.imshow('dst',farbbild) if cv2.waitKey(0) & 0xff == 27: cv2.destroyAllWindows()
Berechnung vom Schwellwertbild:
bild =x[1] ret,th1 = cv2.threshold(bild,127,255,cv2.THRESH_BINARY) th2 = cv2.adaptiveThreshold(bild,255,cv2.ADAPTIVE_THRESH_MEAN_C,\ cv2.THRESH_BINARY,11,2) th3 = cv2.adaptiveThreshold(bild,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\ cv2.THRESH_BINARY,11,2) titles = ['Original Image', 'Global Thresholding (v = 127)', #'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding'] images = [bild, th1, th2, th3] for i in xrange(4): plt.subplot(2,2,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
Zunächst haben wir das Spielbrett modifiziert, dass kein Kreis an Punkten mehr pro Ecke erkannt wird, sondern bestenfalls nur noch ein Punkt pro Ecke. Dazu haben wir auch eine USB-LED-Lampe verwendet, um den Einfluss von Licht und Schatten zu minimieren. Nebenbei gab es von Stefan einen kleinen Exkurs in die Mathematik, welche hinter der Harris-Corner Detection steckt. Auch eine Erklärung zur Homography in OpenCV war beinhaltet, da wir diese für später benötigen.
Nun gilt es die einzelnen Punkte (Pixel), welche wir auf einem Beispielbild ausgegeben bekommen (welches wir seit heute auch speichern können und wissen, wo es gespeichert wird), mit von uns ausgewählten Koordinaten zu verbinden. Diese haben wir in eine Liste gepackt:
mini_muele_punkte = [(0,0),(6,0),(12.25,0),(24.5,0), (0,6),(6,6),(12.25,6),(24.5,6), (0,12.25),(6,12.25),(12.25,12.25),(24.5,12.25), (0,24.5),(6,24.5),(12.25,24.5),(24.5,24.5)]
Allerdings gibt es gegenüber unserer 16 Punkte 480 computergenerierte, welche alle sehr nahe aneinander liegen, wie man an dieser Ausgabe sehen kann:
[[ 13.79937553 13.79937553 13.79937553 ..., -0.39828128 -0.39828128 -0.39828128] [ 13.79937553 13.79937553 13.79937553 ..., 138.36488342 138.36488342 35.59000015] [ 13.79937553 13.79937553 13.79937553 ..., 138.36488342 138.36488342 35.59000015] ..., [ 5.81878948 5.81878948 24.76422119 ..., 11.91031265 11.91031265 4.71875 ] [ 6.44175768 7.93257809 24.76422119 ..., 18.23632812 18.23632812 10.52464867] [ 6.44175768 7.93257809 7.93257809 ..., 18.23632812 18.23632812 10.52464867]]
Somit müssen für das nächste Mal 16 von den 480 Punkten behalten und der Rest entweder rausgeworfen oder ignoriert werden, damit der Computer spezifische Positionen hat, auf die er sich beziehen kann.
punkte=[] b,h=dst.shape maximum=dst.max() for j in range(0,h): for i in range(0,b): if dst[i,j]>0.01*maximum: punkte.append([i,j]) #graubild[dst>0.01*dst.max()]=2 #print graubild print punkte print len(punkte)
Größtenteils diente der Arbeitstag zunächst zur Organisation des weiteren Verlaufs des Projekts, sodass die Arbeit noch rechtzeitig beendet werden kann.
Danach entschieden wir in der Gruppe, die Arbeit an der Bilderkennung vorerst ruhen zu lassen, um ein funktionierendes Spiel auf die Beine zu stellen. Dabei verwenden wir die Regeln und den groben Ablauf, der hier zusammengefasst wurde: http://www.info-wsf.de/index.php/M%C3%BChle
Zur Ordnung des Spielfeldes und der Sortierung der Gewinnmöglichkeiten und Spielzüge, war viel Schreibarbeit via Stift und Zettel nötig. Diese Prinzipien haben wir nun versucht, in Programmcode zu übersetzen:
spielbrett_01 =[['A1',' ','A3','00','A5'], ['00','B2','B3','B4','00'], ['C1','C2','00','C3','C4'], ['00','D2','D3','D4','00'], ['E1','00','E3','00','E5']] spielbrett =[['W','-','x','-','S'], ['|','x','x','S','|'], ['W','S',' ','x','S'], ['|','W','S','W','|'], ['W','-','S','-','S']] # x:= echtes feld #0 := kein Feld
muehlen = [[(0,0),(0,2),(0,4)], [(0,0),(2,0),(4,0)], [(0,4),(2,4),(4,4)], [(1,1),(1,2),(1,3)], [(1,1),(2,1),(3,1)], [(1,3),(2,3),(3,3)], [(3,1),(3,2),(3,3)], [(4,0),(4,2),(4,4)]]
spielbrett[muehlen[0][0][0]][muehlen[0][0][1]]='W'
def zeige_brett(spiel): for i in spiel: print " ".join(i) def pruefe_gewinnpos(brett): '''gibt die muehlen auf dem aktuellen Feld in einer liste aus''' l=[] for situation in muehlen: feld1 = brett[situation[0][0]][situation[0][1]] feld2 = brett[situation[1][0]][situation[1][1]] feld3 = brett[situation[2][0]][situation[2][1]] if feld1 == feld3 and feld3 == feld2 and feld1 != 'x': l.append(situation) return l
def leere_felder(brett): ''' gibt eine liste mit allen leeren Spielfeldern''' l=[] for x in range(0,5): for y in range(0,5): if brett[x][y] == 'x': l.append((x,y)) return l
def spielstand(brett): ''' gibt die anzahl von weißen und schwarzen Figuren auf dem spielbrett aus''' weiss=0 schwarz=0 for n in brett: weiss += n.count('W') schwarz +=n.count('S') print 'weiss: ' +str(weiss) print 'schwarz: '+str(schwarz)