14. Jan 2021

Texterkennung mit Machine Learning in Python

Wie löse ich ein individuelles OCR-Problem mit Machine Learning? Welche grundlegenden Konzepte und Überlegungen haben wir dazu behandelt?
Accso Avatar auf grauem Font

Author

Julian Cornea

Vorschau jpg

Ein Überblick in OCR Anwendungsfälle und wie man ein Programm zur Texterkennung entwickeln kann

Bei Accso haben wir uns in letzter Zeit damit beschäftigt was man machen muss, um automatisch Text in Bildern zu erkennen, und wie man so eine Anwendung bereitstellen kann. Speziell geht es um Texterkennung in Dokumenten mit Tesseract OCR. Unsere Erfahrung damit vermitteln wir euch in diesem Artikel.

Was ist OCR?

Unter Optical Character Recognition (OCR) versteht man, dass bei einem visuellen Input (Bild, Video) Text automatisch erkannt wird. Diese Idee hat viele Anwendungsbereiche, darunter:

  • Selbstfahrende Autos (Erkennung von Straßenschildern etc.)
  • Digitalisierung schriftlicher Dokumente (Einscannen + automatische Konvertierung in PDF Dateien mit markierbarem und suchbarem Text)
  • Kennzeichenerkennung auf Fotos von Blitzern
  • Computerassistenten für Menschen mit Sehbehinderungen und Analphabeten

Wenn man OCR Probleme ganz simpel formulieren will, dann kommt es immer auf folgende zwei Fragen an:

  1. Welcher Teil eines Bildes enthält den für mich relevanten Text?
    • Das macht den Großteil des Aufwands aus. Hierfür sind sowohl ML-basierte, als auch andere Algorithmen verbreitet.
  2. Was ist dieser relevante Text?
    • Das kann man meistens relativ einfach und genau bestimmen, wenn die vorherige Aufgabe gut gelöst wurde. Für diesen Teil wird mittlerweile ausschließlich ML verwendet.

Warum OCR?

Einige von euch fragen sich jetzt bestimmt warum wir uns damit beschäftigen, obwohl es kein „neues“ Thema ist und etablierte Anbieter bereits existieren. Kurze Antwort: Es gibt (noch) nicht die perfekte Lösung.

Im Jahr 2019 haben wir bereits eine Marktrecherche durchgeführt. Will man für seinen konkreten Anwendungsfall eine OCR-Lösung, so findet man auf dem Markt in der Regel einerseits sehr templatespezifische Lösungen, welche mit den kleinsten Änderungen Schwierigkeit haben, oder weniger genaue und sehr allgemeine Lösungen, bei denen man letztendlich trotzdem ergänzen muss welcher Teil eines Bildes relevant ist und in welcher Form der Output generiert/verschickt werden soll. Hat man also spezifische Anforderungen an die Segmentierung (Welcher Teil des Bildes ist relevant?), oder will man mehr API als „Als CSV exportieren“ o.ä., so muss man auch bei den fertigen Produkten mit, manchmal erheblichem, Zusatzaufwand rechnen.

Um solche Anwendungsfälle abdecken zu können möchten wir vorbereitet sein, Kunden bei der Lösung von OCR-Problemen unterstützen zu können.

Unser Prototyp: Texterkennung bei der Reisekostenabrechnug

In unserem Fokus liegt die Automatisierung der, bisher manuellen, Datenerfassung von ausgedruckten, unterschriebenen Dokumenten zur Reisekostenerstattung. Hier wäre es natürlich ideal, wenn man das Dokument nicht nur schriftlich, sondern auch digital senden könnte. Dann wäre es relativ einfach die relevanten Felder auszulesen und deren Werte an die Datenbank weiterzuleiten. Da dies leider keine Möglichkeit ist, haben wir eine Anwendung entwickelt, welche bei den ausgedruckten Dokumenten den Inhalt der relevanten Felder erkennt. Hier sieht man wie so ein Dokument aussehen könnte.

Reisekostenzettel-Scan
Reisekosten 1 jpg

Allgemein kann man sich eine OCR-Pipeline folgendermaßen vorstellen:

  1. Man hat eine Inputdatei
  2. Man verarbeitet die Inputdatei (z.B. Konvertierung zu schwarz/weiß)
  3. Alle Textfelder (nicht der Inhalt dieser Felder) werden identifiziert
  4. Jedes Feld wird an einen OCR-Algorithmus weitergeleitet, welcher den Inhalt schätzt
  5. Man filtert irrelevante Felder weg

Für den Prototypen wurde die Pipeline folgendermaßen erweitert:

  1. Man hat eine Inputdatei
  2. Große Textbereiche werden identifiziert (diese können mehrere Textfelder enthalten)
Reisekosten 2 png
  • 3. Man filtert irrelevante Textbereiche weg (hier interessieren uns nur die persönlichen Daten und der Gesamtbetrag)
  • 4. Auf den relevanten Textbereichen werden alle Textfelder identifiziert
  • 5. Durch die Nutzung mehrerer mathematischer Formeln können viele irrelevante Textfelder hier schon weggefiltert werden (z.B. bei starken Überlappungen).
Reisekosten 3 jpg
  • 6. Jedes Textfeld wird an einen OCR-Algorithmus weitergeleitet, welcher den Inhalt schätzt
    • Je nach Textquelle kann es Sinn machen manuell codierte Anpassungen zu nutzen. Zum Beispiel um „|“ zu „I“ zu ändern. Oder im Betragsfeld ein „€“ anzuhängen, falls es fehlen sollte.
  • 7. Mithilfe der Inhalte filtert man die restlichen irrelevanten Felder weg

Die Schritte 2 und 4 enthalten zusätzlich eine relevante Vorverarbeitung des Inputs. Auf die Details jedes Schrittes gehen wir hier nicht ein, da sie den Rahmen dieses Artikels sprengen würden. Erwähnenswert ist jedoch, dass für Schritt 4 der Neumann-Algorithmus und für Schritt 6 Tesseract OCR von Google genutzt wird.

Will man die zwei zentralen Fragen (Was sind die relevanten Felder? Was ist der Text?) beantworten, so hat man eine große Auswahl an Möglichkeiten dies zu tun. Generell gilt jedoch: Je genauer man den Input kennt, desto einfacher ist es die Aufgabe zu lösen. Je mehr Möglichkeiten man dem User bietet, Daten zu liefern, desto unterschiedlicher können die Verhältnisse in der Inputdatei sein. Dadurch wird es umso schwerer den relevanten Text verlässlich zu erkennen. Dies kann folgende Ursachen haben:

  • Foto vs. Scanner: Bei einem Scan kann man von sehr ähnlichen, falls nicht identischen, Lichtverhältnissen und Rotationswinkeln ausgehen. Nimmt man ein Foto mit seinem Handy auf, so kann es bei jeder neuen Aufnahme leichte Änderungen in der Beleuchtung, der Rotation und der Auflösung geben, welche zu enormen Schwierigkeiten bei der Texterkennung führen können. Hier ist der Precision-Recall-Tradeoff von zentraler Bedeutung!
  • Unterstützung verschiedener Geräte: Will man, dass User verschiedene Modelle von Handys, oder verschiedene Modelle von Scannern verschiedener Hersteller nutzen können, dann muss man akzeptieren, dass die Qualität der Inputdatei stark schwanken kann. Auflösung, Farbverhältnisse und weitere Faktoren können jedes mal anders sein.
  • Unterstützung von Scans mit niedriger Auflösung: Bei vielen Scannern wird, wenn man eine niedrige Auflösung auswählt, das Eingabedokument nicht „Pixel für Pixel“ gescannt. Stattdessen werden, um die Dateigröße klein zu halten, einzelne Pixel mehrmals wiederverwendet, wenn ein anderes Pixel ähnlich genug ist. Da es zu unnatürlichen Verläufen der Farbwerte führt, erschwert es das Finden von Konturen und somit das Ermitteln einzelner Textfelder, auch wenn es dem menschlichen Auge kaum auffällt. Eine ausführliche Erklärung davon findet man auf der Seite vom Chaos Computer Club. Dort ist ein ca. 50 Minuten langer Vortrag zu finden, in dem erklärt wird, wieso Scanner falsche Zahlen einlesen und warum der Scan von Obama’s Geburtsurkunde wie eine billige Fälschung aussieht.

Will man also viele Geräte unterstützen, dann wäre es sinnvoll die Verarbeitung in seiner OCR-Anwendung z.B. ein mal für Scans und ein mal für iPhones (bei Bedarf sogar spezifisch der neuesten Generation) zu optimieren.

Um unsere Arbeit bei der Entwicklung des Prototyps zu erleichtern, gehen wir davon aus, dass man die ausgedruckte Reisekostenabrechnung mit einem Accso-Scanner mit 600 dpi als JPEG-Datei einscannt. Im folgenden sieht man zwei Beispieldokumente, deren relevante Textfelder und was unser Programm für den Inhalt erkannt hat:

Reisekosten 4 jpg
Reisekosten 5 1 1536x1199 jpg
Tabelle jpg

Um die Anwendung über eine API ansprechbar zu machen kann man z.B. Flask (ein Microframework) und Gunicorn (ein WSGI Server) nutzen. Das erlaubt die flexible Gestaltung der Input/Output-Schichten. In unserem Fall können User ein oder mehrere Scans hochladen.

Selectfile jpg

Der vorhergesagte Text und die Bilder mit Rechtecken um die jeweils genutzten Textfelder werden zurückgegeben.

Vorhergesagte Texte jpg

Das ganze dauert auf unserem bescheidenen ML-Rechner nur 10 Sekunden pro Bild. Zusätzlich kann man die Ergebnisse gleichzeitig an die Datenbank schicken, in der die Daten am Ende der manuellen Erfassung gelangen. Das ganze läuft als Linux-Docker-Container, was uns das Ausrollen von Änderungen deutlich leichter gestaltet.

Fazit

Die Entwicklung einer Individualsoftware für OCR-Anwendungsfälle bietet sich an wenn man detaillierte API Anforderungen hat, wenn sich die relevanten Bereiche eines Bildes nicht einfach identifizieren lassen, oder wenn sich der Aufbau des Inputs regelmäßig ändern kann. Will man mehrere kompatible Gerätearten (z.B. Smartphones und Scanner) für den Input, so macht es wahrscheinlich Sinn die Texterkennung für jeden dieser Fälle speziell zu optimieren. Schafft man es die relevanten Bereiche eines Bildes zu identifizieren, so lässt sich der Text dank der Open Source Engine von Google, namens Tesseract OCR, verlässlich erkennen.

Reisekostenheader jpg

Fazit

Die Entwicklung einer Individualsoftware für OCR-Anwendungsfälle bietet sich an wenn man detaillierte API Anforderungen hat, wenn sich die relevanten Bereiche eines Bildes nicht einfach identifizieren lassen, oder wenn sich der Aufbau des Inputs regelmäßig ändern kann. Will man mehrere kompatible Gerätearten (z.B. Smartphones und Scanner) für den Input, so macht es wahrscheinlich Sinn die Texterkennung für jeden dieser Fälle speziell zu optimieren. Schafft man es die relevanten Bereiche eines Bildes zu identifizieren, so lässt sich der Text dank der Open Source Engine von Google, namens Tesseract OCR, verlässlich erkennen.

Dr. Xenija Neufeld

Managing Consultant
lorem ipsum
Xenija Neufeld Zitat