Benutzer-Werkzeuge

Webseiten-Werkzeuge


ss17:erkennung_gedruckter_geschrift_einen_kassenbon_lesen

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
ss17:erkennung_gedruckter_geschrift_einen_kassenbon_lesen [2017/09/21 09:52]
Jan_Philipps [Symbol-Finder]
ss17:erkennung_gedruckter_geschrift_einen_kassenbon_lesen [2017/10/18 09:13] (aktuell)
Jan_Philipps [Symbol-Finder]
Zeile 41: Zeile 41:
  
 =="​Main"​-Methode== =="​Main"​-Methode==
-__Name im Code: SymbolScanner.__ Diese Methode wird vom Primärteil des Programms (neuronales Netz usw.) aufgerufen ​und nutzt verschiedene Hilfsmethoden um möglichst alle Symbole auf dem Kassenbon zu finden und als kleine Bilder zu speichern.+__Name im Code: SymbolScanner.__ Diese Methode wird vom Primärteil des Programms (neuronales Netz usw.) aufgerufen. Sie nutzt verschiedene Hilfsmethoden um das Bild Zeile für Zeile zu durchsuchen und möglichst alle Symbole auf dem Kassenbon zu finden und als kleine Bilder zu speichern.
  
 Die gefundenen Symbole werden in Format //​Zeile//​_//​xKoordinate//​_//​yKoordinate//​.png gespeichert. Die gefundenen Symbole werden in Format //​Zeile//​_//​xKoordinate//​_//​yKoordinate//​.png gespeichert.
Zeile 65: Zeile 65:
  yMax=0 #​Obere Grenze fuer das Programm, damit nichts doppelt gescannt wird.  yMax=0 #​Obere Grenze fuer das Programm, damit nichts doppelt gescannt wird.
   
- Zeit1=time() #​Startet Zeitmessung+ #Zeit1=time() #​Startet Zeitmessung. Auskommentiert weil meist sinnlos, aber manchmal doch ganz nett zu wissen.
   
  while EndPage==False:​ #Diese Schleife wird ausgefuehrt,​ solange die Seite nicht bis zum Ende ueberprueft wurde  while EndPage==False:​ #Diese Schleife wird ausgefuehrt,​ solange die Seite nicht bis zum Ende ueberprueft wurde
Zeile 100: Zeile 100:
   
  try:  try:
- os.mkdir(pPath) #​Erstellt ​Speicherverzeichniss ​falls noch nicht vorhanden+ os.mkdir(pPath) #​Erstellt ​Speicherverzeichnis ​falls noch nicht vorhanden
   
  except: pass  except: pass
Zeile 115: Zeile 115:
  EndLine=True  EndLine=True
   
- Zeit2=time() #​Beendet Zeitmessung.+ #Zeit2=time() #​Beendet Zeitmessung. Auskommentiert weil meist sinnlos, aber manchmal doch ganz nett zu wissen.
   
- print "​SymbolScanner-Time=",​ (Zeit2-Zeit1) #Gibt an, wie lange die ganze Suche gedauert hat+ #print "​SymbolScanner-Time=",​ (Zeit2-Zeit1) #Gibt an, wie lange die ganze Suche gedauert hat. Auskommentiert weil meist sinnlos, aber manchmal doch ganz nett zu wissen.
  
  
Zeile 130: Zeile 130:
  
 def Plotton(img,​h,​b):​ def Plotton(img,​h,​b):​
 + #​img=BildMatrix;​ h=Bildhoehe in Pixeln; b=BildBreite in Pixeln;
   
  pixelCounter=[0]*256 #Erstellt Liste mit 256 Slots, fuer jeden Farbwert einen  pixelCounter=[0]*256 #Erstellt Liste mit 256 Slots, fuer jeden Farbwert einen
Zeile 165: Zeile 166:
  
 def ZeilenFindo(h,​b,​yMax,​threshold,​img):​ def ZeilenFindo(h,​b,​yMax,​threshold,​img):​
 + #​h=Bildhoehe in Pixeln; b=BildBreite in Pixeln; yMax=OberGrenze fuer Suche; threshold=Grenzwert;​ img=BildMatrix;​
   
  jmp=2 ​ #Legt die Anzahl der Reihen fest, die uebersprungen werden (mehr=schneller=ungenauer)  jmp=2 ​ #Legt die Anzahl der Reihen fest, die uebersprungen werden (mehr=schneller=ungenauer)
Zeile 215: Zeile 217:
  
 def Skannomaton(h,​b,​xMax,​yMax,​threshold,​img):​ def Skannomaton(h,​b,​xMax,​yMax,​threshold,​img):​
- + #​h=Untergrenze fuer Suche; b=BildBreite in Pixeln (rechte Grenze fuer Suche); 
 + #​xMax=LinkeGrenze fuer Suche; yMax=OberGrenze fuer Suche; threshold=Grenzwert;​ img=BildMatrix;​
   
  y=yMax #Obergrenze  y=yMax #Obergrenze
Zeile 226: Zeile 229:
   
  while (cy>​yMax) and (cx<b): #Schleife laeuft bis der Algorithmus an der oberen oder rechten Kante vom Bereich ankommt.  while (cy>​yMax) and (cx<b): #Schleife laeuft bis der Algorithmus an der oberen oder rechten Kante vom Bereich ankommt.
- if img[cy,​cx]<​threshold:​ #Wenn der aktuell ​Pixel dunkel ist, werden die Koordinaten zurueckgegeben+ if img[cy,​cx]<​threshold:​ #Wenn der aktuelle ​Pixel dunkel ist, werden die Koordinaten zurueckgegeben
  return cx,cy  return cx,cy
  cx=cx+1 #Geht eins nach rechts  cx=cx+1 #Geht eins nach rechts
Zeile 238: Zeile 241:
   
  while (cy>​yMax) and (cx<​b):​ #​Schleife laeuft bis der Algorithmus an der oberen oder rechten Kante vom Bereich ankommt.  while (cy>​yMax) and (cx<​b):​ #​Schleife laeuft bis der Algorithmus an der oberen oder rechten Kante vom Bereich ankommt.
- if img[cy,​cx]<​threshold:​ #Wenn der aktuell ​Pixel dunkel ist, werden die Koordinaten zurueckgegeben+ if img[cy,​cx]<​threshold:​ #Wenn der aktuelle ​Pixel dunkel ist, werden die Koordinaten zurueckgegeben
  return cx,cy  return cx,cy
  cx=cx+1 #Geht eins nach rechts  cx=cx+1 #Geht eins nach rechts
Zeile 249: Zeile 252:
  return 0,0 #Das steht nur hier, weil das Programm sonst nicht mal starten will. Diese Zeile wird nie aufgerufen.  return 0,0 #Das steht nur hier, weil das Programm sonst nicht mal starten will. Diese Zeile wird nie aufgerufen.
   
 +
 +</​code>​
 +
 +== Koordinaten-Anpasser Oberkante==
 +__Name im Code: Korrektoid.__ Diese Methode wurde zu dem Zweck geschrieben,​ den "Halbe Zeichen"​-Fehler zu beheben. Sie nimmt den zuvor von //​Skannomaton//​ gefundenen Punkt und bringt ihn auf die Höhe des höchsten Punktes des Buchstaben. Die Funktionsweise ähnelt der von //​Findomat_UR//​ und //​Findomat_OL//​. Der Helligkeitswert des Pixels über dem Startpunkt wird getestet. Ist der Pixel dunkel, "​bewegt"​ sich Algorithmus nach oben, ist der Pixel hell, wird der Pixel auf der rechten Seit überprüft. Falls dieser Pixel dunkel ist, wird er zu neuen Startpunkt. Dies wird so lange wiederholt, bis beide Pixel hell sind, der Algorithmus also am lokalen Maximum des Zeichens angelangt ist. Der y-Wert des von //​Scannomaton//​ übergeben Punktes wird nun durch den des lokalen Maximums ersetzt.
 +
 +<code python>
 +
 +def Korrektoid(xS,​yS,​threshold,​img):​
 + #​xS=x-Koordinate Startpunkt; yS=y-Koordinate Startpunkt; treshold=Grenzwert;​ img=BildMatrix
 +
 + cx=xS
 + cy=yS
 + localMax=False
 + #Legt Startkoordinaten fest und schaltet Abbruchbedingung aus
 +
 + while localMax==False and (cy>​(yS-20)):​
 + #Solange das Maximum nicht gefunden wurde und das Programm sich nicht mehr  ​
 + #als 19 von der Starthoehe entfernt hat, wird nach dem Maximum gesucht.
 +
 + if img[(cy-1),​cx]<​threshold:​
 + cy=cy-1
 + #Wenn der Pixel ueber dem aktuellen dunkel ist, wird dieser der neue Ausgagngspixel
 +
 + else:
 + if img[cy,​(cx+1)]<​threshold:​
 + cx=cx+1
 + #Wenn der Pixel rechts von dem aktuellen dunkel ist, wird dieser der neue Ausgagngspixel
 +
 + else:
 + localMax=True
 + #Gibt es keine dunklen Pixel direkt ueber oder direkt rechts vom aktuelle, ist das Maximum gefunden
 +
 + return cy #Hoehe des Maximums wird returnt
 +
  
 </​code>​ </​code>​
Zeile 259: Zeile 297:
  
 def Findomat_UR(x,​y,​yH,​threshold,​img):​ def Findomat_UR(x,​y,​yH,​threshold,​img):​
 + #​x=x-Koordinate Startpunkt; y=y-Koordinate Startpunkt; yH=Von Korrektoid verbesserte y-Koordinate;​
 + #​treshold=Grenzwert;​ img=BildMatrix
   
  cx=x+1  cx=x+1
Zeile 300: Zeile 340:
  
 def swTester_UR(x,​y,​w,​zk,​threshold,​img):​ def swTester_UR(x,​y,​w,​zk,​threshold,​img):​
- #​x=Startbreite;​ y=Starthoehe;​ w=horizontal oder vertikale; zk=Zeilkoordinate;+ #​x=Startbreite;​ y=Starthoehe;​ w=horizontal oder vertikal; zk=Zielkoordinate;
  
  h,​b=img.shape #h ist die Hoehe des Bildes, b ist die Breite des Bildes  h,​b=img.shape #h ist die Hoehe des Bildes, b ist die Breite des Bildes
Zeile 311: Zeile 351:
  #Diese Schleife wird ausgefuehrt,​ wenn in x-Richtung getestet werden soll  #Diese Schleife wird ausgefuehrt,​ wenn in x-Richtung getestet werden soll
  while (img[cy,​cx]>​=threshold):​  while (img[cy,​cx]>​=threshold):​
- #​Diese ​Schelife ​bewegt sich so lange nach links, bis entweder ein + #​Diese ​Schleife ​bewegt sich so lange nach links, bis entweder ein 
  #dunkler Pixel gefunden wird (False) oder die Zielkoordinate erreicht wurde (True)  #dunkler Pixel gefunden wird (False) oder die Zielkoordinate erreicht wurde (True)
  if cx==zk:  if cx==zk:
Zeile 321: Zeile 361:
  #Diese Schleife wird ausgefuehrt,​ wenn in y-Richtung getestet werden soll  #Diese Schleife wird ausgefuehrt,​ wenn in y-Richtung getestet werden soll
  while (img[cy,​cx]>​=threshold):​  while (img[cy,​cx]>​=threshold):​
- #​Diese ​Schelife ​bewegt sich so lange nach links, bis entweder ein + #​Diese ​Schleife ​bewegt sich so lange nach oben, bis entweder ein 
  #dunkler Pixel gefunden wird (False) oder die Zielkoordinate erreicht wurde (True)  #dunkler Pixel gefunden wird (False) oder die Zielkoordinate erreicht wurde (True)
  if cy==zk:  if cy==zk:
Zeile 336: Zeile 376:
  
 def Korrektomat(x,​y,​threshold,​img):​ def Korrektomat(x,​y,​threshold,​img):​
 + #​x=x-Koordinate Startpunkt; y=y-Koordinate Startpunkt; treshold=Grenzwert;​ img=BildMatrix
   
  cx=x-1  cx=x-1
Zeile 356: Zeile 397:
  
 def Findomat_OL(x,​y,​threshold,​img):​ def Findomat_OL(x,​y,​threshold,​img):​
 + #​x=x-Koordinate Startpunkt; y=y-Koordinate Startpunkt; treshold=Grenzwert;​ img=BildMatrix
  
  cx=x-1  cx=x-1
Zeile 392: Zeile 434:
 == Schwarz/​Weiß-Tester Oben Links== == Schwarz/​Weiß-Tester Oben Links==
 __Name im Code: swTester_OL.__ Die Funktionsweise dieser Methode ist fast identisch mit der von //​swTester_UR//​. Der einzige Unterschied besteht darin, dass die der Algorithmus sich von oben nach unten Bzw. von links nach rechts über das Bild  bewegt. __Name im Code: swTester_OL.__ Die Funktionsweise dieser Methode ist fast identisch mit der von //​swTester_UR//​. Der einzige Unterschied besteht darin, dass die der Algorithmus sich von oben nach unten Bzw. von links nach rechts über das Bild  bewegt.
- 
-== Koordinaten-Anpasser Oberkante== 
-__Name im Code: Korrektoid.__ Diese Methode wurde zu dem Zweck geschrieben,​ den "Halbe Zeichen"​-Fehler zu beheben. Sie nimmt den zuvor von //​Skannomaton//​ gefundenen Punkt und bringt ihn auf die Höhe des höchsten Punktes des Buchstaben. Die Funktionsweise ähnelt der von //​Findomat_UR//​ und //​Findomat_OL//​. Der Helligkeitswert des Pixels über dem Startpunkt wird getestet. Ist der Pixel dunkel, "​bewegt"​ sich Algorithmus nach oben, ist der Pixel hell, wird der Pixel auf der rechten Seit überprüft. Falls dieser Pixel dunkel ist, wird er zu neuen Startpunkt. Dies wird so lange wiederholt, bis beide Pixel hell sind, der Algorithmus also am lokalen Maximum des Zeichens angelangt ist. Der y-Wert des von //​Scannomaton//​ übergeben Punktes wird nun durch den des lokalen Maximums ersetzt. 
  
 <code python> <code python>
  
-def Korrektoid(xS,yS,​threshold,​img):​+def swTester_OL(x,y,w,zk,​threshold,​img):​ 
 + #​x=Startbreite;​ y=Starthoehe;​ w=horizontal oder vertikal; zk=Zielkoordinate;​
  
- cx=xS + h,b=img.shape #h ist die Hoehe des Bildes, b ist die Breite des Bildes 
- cy=yS +  
- localMax=False + cy=y 
- #Legt Startkoordinaten fest und schaltet Abbruchbedingung aus + cx=x 
- + #Setzt Startparameter 
- while localMax==False and (cy>(yS-20)): +  
- #Solange das Maximum nicht gefunden wurde und das Programm ​sich nicht mehr  ​ +  
- #als 19 von der Starthoehe entfernt hat, wird nach dem Maximum gesucht.+ if w==1: 
 + #Diese Schleife wird ausgefuehrt,​ wenn in x-Richtung getestet werden soll 
 + while ​(img[cy,cx]>=thresholdand (cx<b): 
 + #Diese Schleife bewegt ​sich so lange nach rechts, bis entweder ein  
 + #dunkler Pixel gefunden ​wird (False) oder die Zielkoordinate erreicht wurde (True) 
 + if cx==zk: 
 + return True  
 + cx=cx+1 
 + return False
   
- if img[(cy-1),​cx]<​threshold+ else
- cy=cy-1 + #Diese Schleife wird ausgefuehrtwenn in y-Richtung getestet werden soll 
- #Wenn der Pixel ueber dem aktuellen dunkel istwird dieser der neue Ausgagngspixel + while (img[cy,cx]>​=threshold) and (cy<h)
-  + #Diese Schleife bewegt sich so lange nach unten, bis entweder ein  
- else: + #dunkler ​Pixel gefunden ​wird (False) oder die Zielkoordinate erreicht wurde (True) 
- if img[cy,(cx+1)]<threshold+ if cy==zk
- cx=cx+1 + return ​True  
- #Wenn der Pixel rechts von dem aktuellen dunkel ist, wird dieser der neue Ausgagngspixel + cy=cy+1 
-  + return ​False
- else+
- localMax=True +
- #Gibt es keine dunklen Pixel direkt ueber oder direkt rechts vom aktuelle, ist das Maximum gefunden +
-  +
- return ​cy #Hoehe des Maximums wird returnt +
- +
  
 </​code>​ </​code>​
Zeile 450: Zeile 492:
 == Artefakte == == Artefakte ==
  
-Flecken, Schatten, Druckfehler, ​Stempeln ​oder ähnliche Unreinheiten auf dem Papier sind teilweise dunkel genug um vom Programm als Symbol erkannt zu werden. Das kann dazu führen, dass Zeilen nicht richtig erkannt werden, in manchen Fällen hält das Programm dann zwei Zeilen für eine einzige. In solchen Fällen werden oft Buchstaben aus den beiden Zeilen nicht gefunden. Dieser Fall tritt aber nur bei relativ großen Artefakten ein, welche ziemlich selten sind, wenn man sich mit dem Foto etwas Mühe gibt.+Flecken, Schatten, Druckfehler, ​Stempel ​oder ähnliche Unreinheiten auf dem Papier sind teilweise dunkel genug um vom Programm als Symbol erkannt zu werden. Das kann dazu führen, dass Zeilen nicht richtig erkannt werden, in manchen Fällen hält das Programm dann zwei Zeilen für eine einzige. In solchen Fällen werden oft Buchstaben aus den beiden Zeilen nicht gefunden. Dieser Fall tritt aber nur bei relativ großen Artefakten ein, welche ziemlich selten sind, wenn man sich mit dem Foto etwas Mühe gibt.
 Kleinere Artefakte werden einfach als Symbole erkannt und an das neuronale Netzwerk übergeben, welches diese dann aussortieren soll. In diesem Teil des Programmes eine Lösung zu finden wäre zu aufwendig, vor allem da man mit einem neuronales Netzwerk ziemlich einfach erkennen kann, ob es sich um eine richtiges Symbol handelt oder nicht. Kleinere Artefakte werden einfach als Symbole erkannt und an das neuronale Netzwerk übergeben, welches diese dann aussortieren soll. In diesem Teil des Programmes eine Lösung zu finden wäre zu aufwendig, vor allem da man mit einem neuronales Netzwerk ziemlich einfach erkennen kann, ob es sich um eine richtiges Symbol handelt oder nicht.
 ==== Machine Learning ==== ==== Machine Learning ====
ss17/erkennung_gedruckter_geschrift_einen_kassenbon_lesen.1505980334.txt.gz · Zuletzt geändert: 2017/09/21 09:52 von Jan_Philipps