import gpanel #um bilder einzulesen import os #um Verzeichnisse zu listen import csv #um CSV-Dateien zu lesen. # Pfad zu den Bilddateien digitsdirectory = 'C:/temp/digits/' def getPixeListFromFilePath(filepath): img = gpanel.getImage(filepath) w = img.getWidth() h = img.getHeight() pixellist = [] for y in range(h): for x in range(w): # color is ein Objekt mit verschiedenen Attributen, u.a. red, green, blue. # bei grau sind rot=gruen=blau, d.h., eine Farbe auslesen reicht. # siehe auch https://docs.oracle.com/javase/7/docs/api/java/awt/Color.html color = img.getPixelColor(x, y) # umlegen auf das Intervall [-1,1] zwecks Normalisierung value = color.red / 255 * 2 - 1 # an liste anhaengen pixellist.append(value) return pixellist # Lese Ziffer aus Dateiname aus. def getDigitFromFileName(filename): return int(filename.split('_', 3)[2]) # leere Liste fuer alle Trainingsdaten der Form [-0.93,0.331,....,0.99,3] trainingset = [] # durch alle files im Ziffernverzeichnis loopen for filename in [filename for filename in os.listdir(digitsdirectory) if filename.endswith("gif")]: # Ziffer auslesen currdigit = getDigitFromFileName(filename) # Pixelliste von Datei auslesen currpixellist = getPixeListFromFilePath(digitsdirectory + filename) # Der Pixelliste die Ziffer anhaengen currpixellist.append(currdigit) # Gesamte Liste dem trainingsset anhaengen. trainingset.append(currpixellist) # Das Trainingsset kann jetzt verwendet werden # print(trainingsset) # Alternative: Einlesen von Datei # trainingset = list(csv.reader(open('C:/temp/digitsdata.csv', 'r'), delimiter=',', quoting=csv.QUOTE_NONNUMERIC)) # Funktion, die einem Punkt eine Klasse auf Grund der k naechsten Nachbarn zuweist. def assignClass(point, k): # Liste um die Distanzen zu speichern. distlist = [] # Fuer jeden den Punkt point die Distanzen zu allen Punkten in datalist berechnen. for i in range(len(trainingset)): dist = 0 # schlaufe ueber die 256 pixel for j in range(255): dist += (point[j] - trainingset[i][j]) ** 2 distlist.append([trainingset[i][256], sqrt(dist)]) # das waere ein sehr Pythonesquer Weg mit Lambda-Funktionen # nearest = sorted(distlist,key=lambda result:result[1]) # definiere eine Funktion, welche das zweite Element zurueckgibt. def sortFunction(item): return item[1] # Sortiere die liste! Achtung: Man koennte auch ohne key Arbeiten, wenn Distanz an 1. Stelle waere nearest = sorted(distlist, key=sortFunction) # Zaehle k naechsten Klassennummern und entscheide ueber Klasse. # Liste die die Anzahl Vorkommen von 0,1,2,...,9 enthaelt. An Stelle 0 die Null, an Stelle 1 die Eins etc. classcounts = [0] * 10 # Loope durch die k naechsten Nachbarn und erhoehe den classcount jeweils um 1 # wenn eine Ziffer (Klasse) der jeweiligen Ziffer gefunden worden ist. for j in range(k): classcounts[int(nearest[j][0])] += 1 # Rueckggabe der Anzahl/Klasse. # Wenn anstelle der Anzahl/Klasse die eigentlich Ziffer zurueckgegeben werden soll, # kann dies mit classcounts.index(max(classcounts)) passieren. return classcounts # Teste das Programm testpoint = getPixeListFromFilePath(digitsdirectory + 'testimg_993918225911_2_.gif') print assignClass(testpoint, 100) testpoint = getPixeListFromFilePath(digitsdirectory + 'testimg_899286188295_1_.gif') print assignClass(testpoint, 100) testpoint = getPixeListFromFilePath(digitsdirectory + 'testimg_809996871457_8_.gif') print assignClass(testpoint, 100) testpoint = getPixeListFromFilePath('C:/temp/man1.gif') print assignClass(testpoint, 5)