Zahlen erkennen
-
Hallo!
Ich suche einen Ansatz um Zahlen zu erkennen. Die Bedingungen sind immer gleich:
Selbe Schrift
Schwarz auf weiß
Nur Zahlen von 0-9Segmentierung bekomm ich schon hin, es geht lediglich umdas identifizieren.
Was ist ein einfacher aber brauchbarer Ansatz?
-
Größe konstant?
Zahlen gedreht?
-
da war mal was auf einem Forentreffen.
-
hmmhmhmm schrieb:
Hallo!
Ich suche einen Ansatz um Zahlen zu erkennen.
Die Bedingungen sind immer gleich:Selbe Schrift
Schwarz auf weiß
Nur Zahlen von 0-9Segmentierung bekomm ich schon hin, es geht lediglich umdas identifizieren.
Was ist ein einfacher aber brauchbarer Ansatz?
Ich habe so etwas schon einmal programmiert. Die Anforderungen waren allerdings etwas höher (unterschiedliche Farbe, Gesamtes Alphabet, Unterschiedlich Ausrichtung).
Und zwar läßt sich das für deinen Fall sehr einfach lösen:
1. Du segmentierst den Buchstaben
2. Buchstaben ausschneiden, so das nur der Buchstabe überbleibt (Farbe Schwarz/Weiß)
3. Du verkleinerst/vergrößerst den Buchstaben auf z.B. 10x10 Pixel
4. Du erstellst dir ein Array was für jeden Buchstaben eine Matrix hat
Beispiel für eine 1 bei einer 4x4 Matrix (Alle Buchstaben werden auf 4x4 Pixel transformiert):
-1 +1 +1 +1 +1 -1 -1 +1 -1 -1 -1 +1 -1 -1 -1 +1
Die Stelle, die die Zahl eins belegt werden mit 1 gewertet, alle anderen mit -1
Du gehst nun dieses Array durch und errechnest für jede dieser Matrix den Wert.
int output[10]; // 10 Ausgänge, da 10 Zahlen for i = 0 to 10 for x = 0 to IMG_X for y = 0 to IMG_Y if (Image.GetPixel(x, y) != COLOR_WHITE) // Weiß = Wird nicht vom Buchstaben belegt output[i] += Matrix[i][x][y]; end if end for end for end for
Nun hat jeder der Ausgänge einen Wert. Du überprüfst nun welcher dieser Ausgänge den höchsten Wert hat.
Damit hast du dann ermittelt, worum es sich handelt. Man könnte die Matrix natürlich auch in einer Datei speichern und sich selber anpassen lassen. Damit hätte man dann sogar eine mehr oder weniger lernfähige Erkennung.
Bei sehr ähnliche Buchstaben muss man eventuell anstatt 1 und -1 größere bzw. kleinere Werte nehmen. Eine 0 hat zum Beispiel in der Mitter definitiv nichts. Das wäre also ein Kriterium dafür, dass es sich nicht um eine 0 handelt:
+1 +1 +1 +1 +1 -5 -5 +1 +1 -5 -5 +1 +1 +1 +1 +1
-
ist die schriftart immer gleich? sind die zahlen in bilddateien?
gut, dann mach einen einfachen bitmapvergleich. bei größenänderungen können infos flöten gehen und dann wird die zahl u.u. nicht erkannt.
-
also die Zahlen sind nicht gedreht, aber mal größer und mal kleiner. Das lässt sich ja transformieren.
Die erste Idee hier klingt doch schon ganz gut
-
Hast du schon ocrad probiert? (http://www.gnu.org/software/ocrad/ocrad.html)
Das ist gut genug um das captcha von rapidshare zu lesen, es sollte also gar kein Problem sein damit eine normale handschriftliche Zahl zu erkennen.
-
@Dummie Die Methode ist schon ziemlich gut, aber man kann noch ne Menge am Vergleichsmaß drehen. Das erste Problem ist, dass du dir nur die Pixel anschaust die im Bild schwarz sind. Interessant sind aber auch die Pixel die in der Matrix schwarz sind im Bild aber nicht. Ein anderes Problem ist, dass bereits leichte Abweichungen zu riesigen Unterschieden führen können. Zum Beispiel wenn ein Buchstabe leicht kleiner ist.
Für Binärbilder kann man sehr gut das Chamfer-Matching verwenden. Hierbei wird das Ursprungsbild so transformiert dass bei jedem Pixel die nächste Entfernung zu einem schwarzen Pixel angegeben wird. Dann geht man mit dem Binärtemplate über dieses Bild und addiert die Distanzen an den Stellen wo das Binärbild schwarze Pixel hat. Die minimale Entfernung entspricht dem besten Match. Vorteil ist, dass leichte Skalierungsfehler oder eine leichte Veränderung des Zeichens keine so drastische Auswirkung haben.
//edit beim Chamfer--Matching kann es noch ganz sinnvoll sein, die Ergebnisse mit der Anzahl der schwarzen Pixel zu skalieren, da sonst Masken mit vielen schwarzen Pixeln gegenüber Masken mit wenig Pixeln benachteiligt werden würden)
-
Ich bin heute mal dazu gekommen, deinen Ansatz zu verfolgen. Das Ergebnis ist bescheiden, was wohl aber an meinen Zahlvorlagen liegt. Ich hab mir mit Paint Vergleichszahlen erstellt (10x10) Pixel. Die sind wohl nicht sehr eindeutig/gut, deswegen wollte ich dich fragen wie du genau deine Matrizen zum vergleichen erstellt hast?
Hier ist mal das Ergebnis meiner Segmentierung
http://www.abload.de/img/bescheidenes_ergebnis9g6k.png
Die 3 wird z.B. für eine 8 gehalten, die 6 für eine 4, die 8 für eine 9... das einzig die 4 und die 9 werden korrekt erkannt.
Ich würde das gerne optimieren und da liegt der Schlüssel erstmal in den Vergleichsmatrizen
Wäre für Hilfe zur Erstellung selbiger sehr dankbar
-
hmmhmhmm schrieb:
Das lässt sich ja transformieren.
Die erste Idee hier klingt doch schon ganz gutdas kannste vergessen. bei der transformierung gehen infos flöten. was du braucht sind alle bitmaps von allen schriftgrößen um einen vergleich durchführen zu können.
-
Ein anderer Ansatz für die Character Recognition wäre ein Neuronales Netz zu verwenden. Ich habe mal ein simples Backpropagation Network zum erkennen von handgeschriebenen Zeichen entwickelt, mit etwas Forschungsarbeit kann man damit schon gute Ergebnisse erzielen. Fertige NN Libs gibt es im Netz, Abstracts über Methoden auch.
-
Das was Dummie gepostet hat ist schon ein grundlegenes NN mit einer Ebene.
-
hmhmhmmmhmmm schrieb:
Ich bin heute mal dazu gekommen, deinen Ansatz zu verfolgen. Das Ergebnis ist bescheiden, was wohl aber an meinen Zahlvorlagen liegt. Ich hab mir mit Paint Vergleichszahlen erstellt (10x10) Pixel. Die sind wohl nicht sehr eindeutig/gut, deswegen wollte ich dich fragen wie du genau deine Matrizen zum vergleichen erstellt hast?
Hier ist mal das Ergebnis meiner Segmentierung
http://www.abload.de/img/bescheidenes_ergebnis9g6k.png
Die 3 wird z.B. für eine 8 gehalten, die 6 für eine 4, die 8 für eine 9... das einzig die 4 und die 9 werden korrekt erkannt.
Ich würde das gerne optimieren und da liegt der Schlüssel erstmal in den Vergleichsmatrizen
Wäre für Hilfe zur Erstellung selbiger sehr dankbar
Tut mir leid, dass ich erst jetzt antworte. Habe das gerade zufällig gesehen. Ich habe mir damals je eine Funktion geschrieben, die die Eingabematrizen aus einer Datei ausliest und auch wieder speichern kann. Ich habe mir dann ein Verzeichnis für jede Zahl angelegt und dort einige Beispieleingaben für einzelne Zahlen als Bilder abgespeichert. Diese Eingaben habe ich dann automatisch einlesen und auswerten lassen, hat das Ergebnis nicht gestimmt, habe ich die Matrizen verändern lassen. Die von der Eingabe belegten Bereichen wurden um beispielsweise 1 verstärkt, und die nicht belegten Bereiche um -1 verringert.
Ich habe ja bereits bei meiner anfänglichen Erklärung ein Beispiel für eine Matrix gegeben. Diese bestand ja nur aus +1 und -1. Das ist natürlich unzureichend, wenn die anderen Matrizen auch aus nur aus +1 und -1 bestehen.
Durch das Programm wurden diese Werte dann erst weiter angepasst und verfeinert, so dass es vorkam, dass ein bestimmter Bereich eine Gewichtung von -5 oder +5 hat, während ein anderer Bereich nur bei +1 und -1 lag.Dadurch wurde dem Programm beigebracht, wie so etwas aussieht, und wo die wesentlichen Merkmale liegen. Extreme Verwechselungen wurden damit ausgeschlossen und die von dir gezeigten Eingaben müssten ohne Probleme erkannt werden. Ich hatte das damals sogar so programmiert, das handgezeichnete Zahlen erkannt wurden. Das klappe nach einer gewissen Traingszeit auch hervorragend.
wissser schrieb:
Das was Dummie gepostet hat ist schon ein grundlegenes NN mit einer Ebene.
Ja, der Meinung war ich auch immer, da ich mein Programm ja auch trainieren konnte
PS: Ich bin mir bewusst, dass ich diesen Thread wiederbelebe. Aber falls mal jemand danach sucht, hilft das eventuell weiter.