Was ist der beste Weg, um die Ecken einer Rechnung / Quittung / eines Blattes Papier auf einem Foto zu erkennen? Dies ist für die nachfolgende perspektivische Korrektur vor der OCR zu verwenden.
Mein aktueller Ansatz war:
RGB> Grau> Canny Edge Detection mit Schwellenwert> Dilatieren (1)> Kleine Objekte entfernen (6)> Grenzobjekte löschen> Größeres Blog basierend auf konvexem Bereich auswählen. > [Eckenerkennung - Nicht implementiert]
Ich kann nicht anders, als zu glauben, dass es einen robusteren „intelligenten“ / statistischen Ansatz geben muss, um diese Art der Segmentierung zu handhaben. Ich habe nicht viele Trainingsbeispiele, aber ich könnte wahrscheinlich 100 Bilder zusammen bekommen.
Breiteren Kontext:
Ich verwende Matlab als Prototyp und plane, das System in OpenCV und Tesserect-OCR zu implementieren. Dies ist das erste einer Reihe von Bildverarbeitungsproblemen, die ich für diese spezielle Anwendung lösen muss. Daher möchte ich meine eigene Lösung entwickeln und mich erneut mit Bildverarbeitungsalgorithmen vertraut machen.
Hier sind einige Beispielbilder, die der Algorithmus verarbeiten soll: Wenn Sie die Herausforderung annehmen möchten, finden Sie die großen Bilder unter http://madteckhead.com/tmp
(Quelle: madteckhead.com )
(Quelle: madteckhead.com )
(Quelle: madteckhead.com )
(Quelle: madteckhead.com )
Im besten Fall ergibt dies:
(Quelle: madteckhead.com )
(Quelle: madteckhead.com )
(Quelle: madteckhead.com )
In anderen Fällen schlägt es jedoch leicht fehl:
(Quelle: madteckhead.com )
(Quelle: madteckhead.com )
(Quelle: madteckhead.com )
Vielen Dank im Voraus für all die tollen Ideen! Ich liebe so!
EDIT: Hough Transform Fortschritt
F: Welcher Algorithmus würde die Hough-Linien gruppieren, um Ecken zu finden? Nach den Ratschlägen der Antworten konnte ich die Hough-Transformation verwenden, Linien auswählen und filtern. Mein aktueller Ansatz ist ziemlich grob. Ich bin davon ausgegangen, dass die Rechnung immer weniger als 15 Grad vom Bild entfernt ist. Wenn dies der Fall ist, erhalte ich vernünftige Ergebnisse für Zeilen (siehe unten). Ich bin mir jedoch nicht ganz sicher, welcher Algorithmus geeignet ist, um die Linien zu gruppieren (oder abzustimmen), um sie für die Ecken zu extrapolieren. Die Hough-Linien sind nicht durchgehend. Und in den verrauschten Bildern können parallele Linien vorhanden sein, sodass eine gewisse Form oder Entfernung von den Linienursprungsmetriken erforderlich ist. Irgendwelche Ideen?
(Quelle: madteckhead.com )
quelle
Antworten:
Ich bin Martins Freund, der Anfang dieses Jahres daran gearbeitet hat. Dies war mein erstes Codierungsprojekt und endete ein bisschen in Eile, daher muss der Code etwas fehlerhaft ... dekodiert werden ... Ich werde ein paar Tipps von dem geben, was ich bereits gesehen habe, und dann sortiere meinen Code an meinem freien Tag morgen.
Erster Tipp,
OpenCV
undpython
sind fantastisch, gehen Sie so schnell wie möglich zu ihnen. : D.Anstatt kleine Objekte und / oder Geräusche zu entfernen, senken Sie die schlauen Fesseln, damit mehr Kanten akzeptiert werden, und finden Sie dann die größte geschlossene Kontur (bei OpenCV-Verwendung
findcontour()
mit einigen einfachen Parametern, glaube ichCV_RETR_LIST
). Es könnte immer noch schwierig sein, wenn es auf einem weißen Blatt Papier ist, aber es lieferte definitiv die besten Ergebnisse.Houghline2()
Versuchen Sie für die Transformation mit demCV_HOUGH_STANDARD
im Gegensatz zu demCV_HOUGH_PROBABILISTIC
, es gibt Rho- und Theta- Werte, die die Linie in Polarkoordinaten definieren, und dann können Sie die Linien innerhalb einer bestimmten Toleranz zu diesen gruppieren.Meine Gruppierung diente als Nachschlagetabelle. Für jede Zeile, die von der Hough-Transformation ausgegeben wurde, ergab sich ein Rho-Theta-Paar. Wenn diese Werte innerhalb von beispielsweise 5% eines Wertepaars in der Tabelle lagen, wurden sie verworfen. Wenn sie außerhalb dieser 5% lagen, wurde der Tabelle ein neuer Eintrag hinzugefügt.
Sie können dann viel einfacher parallele Linien oder Abstände zwischen Linien analysieren.
Hoffe das hilft.
quelle
Eine Studentengruppe an meiner Universität hat kürzlich eine iPhone-App (und eine Python-OpenCV-App) vorgeführt, die genau dafür geschrieben wurde. Soweit ich mich erinnere, waren die Schritte ungefähr so:
Dies schien ziemlich gut zu funktionieren und sie konnten ein Foto von einem Stück Papier oder Buch aufnehmen, die Eckenerkennung durchführen und dann das Dokument im Bild in fast Echtzeit auf eine flache Ebene abbilden (es gab eine einzige OpenCV-Funktion, die ausgeführt werden musste die Zuordnung). Es gab keine OCR, als ich sah, dass es funktionierte.
quelle
Folgendes habe ich mir nach einigem Experimentieren ausgedacht:
Nicht perfekt, funktioniert aber zumindest für alle Proben:
quelle
for line in lines[0]: cv2.line(edges, (line[0], line[1]), (line[2], line[3]), (255,0,0), 2, 8) # finding contours contours, _ = cv2.findContours(edges.copy(), cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_TC89_KCOS) contours = filter(lambda cont: cv2.arcLength(cont, False) > 100, contours) contours = filter(lambda cont: cv2.contourArea(cont) > 10000, contours)
Anstatt mit der Kantenerkennung zu beginnen, können Sie die Eckenerkennung verwenden.
Marvin Framework bietet zu diesem Zweck eine Implementierung des Moravec-Algorithmus. Sie könnten die Ecken der Papiere als Ausgangspunkt finden. Unterhalb der Ausgabe des Moravec-Algorithmus:
quelle
Sie können auch MSER ( Maximal stabile Extremalregionen) über dem Sobel-Operatorergebnis verwenden, um die stabilen Regionen des Bildes zu finden. Für jede von MSER zurückgegebene Region können Sie eine konvexe Hülle und eine Poly-Approximation anwenden, um Folgendes zu erhalten:
Diese Art der Erkennung ist jedoch nützlich für die Live-Erkennung von mehr als einem einzelnen Bild, das nicht immer das beste Ergebnis liefert.
quelle
Verwenden Sie nach der Kantenerkennung die Hough-Transformation. Fügen Sie diese Punkte dann mit ihren Beschriftungen in eine SVM (Supporting Vector Machine) ein. Wenn die Beispiele glatte Linien aufweisen, hat SVM keine Schwierigkeiten, die erforderlichen Teile des Beispiels und andere Teile zu teilen. Mein Rat zu SVM, setzen Sie einen Parameter wie Konnektivität und Länge. Das heißt, wenn Punkte verbunden und lang sind, sind sie wahrscheinlich eine Empfangszeile. Dann können Sie alle anderen Punkte entfernen.
quelle
Hier haben Sie @ Vanuans Code mit C ++:
quelle
std::vector<cv::Vec4i> lines;
wird in meinem Projekt global deklariert.In Laborraum konvertieren
Verwenden Sie kmeans Segment 2 Cluster
quelle