OdoKeep ist jetzt im App Store. Kostenlos laden.

Alle Artikel

Belegerkennung

Offline-Beleg-OCR mit Expo: Die Arbeit beginnt nach der Texterkennung

Tankbelege auf dem Telefon mit Expo, Vision und ML Kit auswerten: Kandidaten, Rechenprüfungen, eindeutige Einheiten und überprüfbare Entwürfe.

Aktualisiert am

In diesem Artikel

Auf einem Tankbeleg kann 1,899 der Einzelpreis sein, 95 die Kraftstoffsorte und 04 die Zapfsäule. Die OCR kann alle drei Werte korrekt lesen und trotzdem einen falschen Tankvorgang liefern.

Ich habe OdoKeep, meinem Fahrzeugtagebuch mit React Native und Expo, eine Belegfunktion hinzugefügt. Die Erkennung läuft auf dem Telefon: Apples Vision unter iOS und mitgelieferte Google-ML-Kit-Modelle unter Android. Diese Funktion lädt weder Foto noch erkannten Text hoch.

Das native Modul übernimmt Aufnahme, Bildvorbereitung, Texterkennung und temporäres Foto. Die Interpretation liegt in TypeScript unter lib/receipt-scan. So lässt sich der Parser unabhängig von Kamera und Telefonmodell testen.

Nachweise am Text behalten

Das native Ergebnis enthält Zeilen, Quellrechtecke, verfügbare Konfidenzinformationen und gegebenenfalls alternative Transkriptionen. Mit den Positionen kann der Parser ein Feld seiner Herkunft auf dem Foto zuordnen.

Der Ablauf sieht ungefähr so aus:

Foto
  -> native OCR-Zeilen und Rechtecke
  -> Zahlentokens mit Einheiten und Positionen
  -> bewertete Feldkandidaten
  -> arithmetische Prüfung
  -> überprüfter Entwurf
  -> bestehendes Tank- oder Ladeformular

Zwischen Erkennung und ursprünglichem Formular wird nichts gespeichert. Der Scan füllt einen Vorschlag aus, den die Person auf demselben Weg wie eine manuelle Eingabe korrigiert und speichert.

Lesarten bewerten, bevor eine Zahl gewählt wird

Belege verwenden Dezimalkommas, Dezimalpunkte, Gruppierungsleerzeichen, Schweizer Apostrophe und unterschiedliche Ziffernsysteme. Beim Thermodruck können Trennzeichen verschwinden oder Ziffern wie Buchstaben aussehen.

Der Tokenizer behält mehrere plausible Lesarten. Er muss 1,899 nicht auflösen, bevor Beschriftung, Einheit und Nachbarn bekannt sind. Eine mögliche Reparatur hat geringeres Gewicht als eine gewöhnliche Lesart; ihre Quellposition bleibt erhalten.

Die Bewertung beginnt mit gedruckten Nachweisen. Eine explizite Mengeneinheit spricht für die Menge. EUR/L spricht für den Einzelpreis. Eine Gesamtbetrag-Beschriftung spricht für den Referenzbetrag.

Daten, Prozentsätze, Kilometerstände und administrative Angaben werden aus den Betragsfeldern ausgeschlossen. Eine unbeschriftete Zahl wird nicht zur fehlenden Menge, nur weil damit die Rechnung aufgeht. Pro Feld bleiben höchstens zwanzig Kandidaten, damit die Kombinationen begrenzt sind.

Multiplikation bestätigt nur einen Teil

Die Rechnung wirkt einfach:

quantity * unitPrice = printedTotal

Ein passendes Produkt stützt eine Lesart. Es beweist weder die richtige Bilderkennung noch, dass die drei Felder die gemeinte Transaktion beschreiben.

Der Parser vergleicht das Produkt mit einer Toleranz von einer halben kleinsten Währungseinheit zuzüglich Gleitkommaspielraum. Bei zwei Nachkommastellen sind das zunächst ein halber Cent. Ein Prozentsatz der Rechnung wäre ungeeignet, weil größere Belege dann größere OCR-Fehler erlaubten.

Dieser Fall steckt in den Tests:

31.93 L x 1.899 EUR/L
TOTAL 60.84 EUR

Das Produkt beträgt ungefähr 60,635. Eine großzügige prozentuale Toleranz könnte 60,84 akzeptieren. Der währungsbezogene Vergleich lehnt die Übereinstimmung ab.

Ein weiterer Test enthält eine gut lesbare Menge, einen Preis, eine passende Zwischensumme und einen niedrigeren Zahlbetrag:

40 L x 1.80 EUR/L
Subtotal 72 EUR
Discount 4 EUR
Total 68 EUR

Der Parser behält 68 als gedruckten Referenzgesamtbetrag. Er macht nicht 72 zum Endbetrag, nur weil die Multiplikation passt. Menge und Einzelpreis können trotz Rabatt nützlich sein.

OdoKeep berechnet die gespeicherten Kosten aus Menge mal Einzelpreis abzüglich eines optionalen, geprüften Rabatts. Der gedruckte Gesamtbetrag wird nicht als gespeicherter Preis übernommen. Er darf auch keine fehlende Menge oder keinen fehlenden Einzelpreis durch Division erzeugen.

Wurde nur der Gesamtbetrag erkannt, müssen die Eingabewerte ergänzt werden. Fehlt der Preis, bleibt er leer. Ein Teilergebnis darf unvollständig bleiben.

Bei gescheiterter arithmetischer Prüfung kann die App eine kontrastreichere Erkennung anfordern. Beide Durchläufe werden zuerst nach arithmetischer Bestätigung, dann nach erkannten Betragsfeldern verglichen. Bei Gleichstand bleibt der erste. Datum, Uhrzeit, Station und andere Nichtbetragsfelder können Lücken aus dem anderen Durchlauf füllen, da beide dasselbe Foto betreffen.

Auch die bessere Lesart wird überprüft. Zusätzliche Nachweise ändern die Bewertung, nicht die Möglichkeit zur Korrektur.

Einheiten und Währungen ausdrücklich wählen

Liter, US-Gallonen, imperiale Gallonen, Kilogramm, Kubikmeter und Kilowattstunden sind im Tank- und Ladebereich gültig. Austauschbar sind sie nicht.

Ein bloßes gal legt den Gallonentyp nicht fest. Der Import fragt nach. Bei kompatiblen Volumeneinheiten wird die Menge mit dem Faktor multipliziert und der Preis durch denselben Faktor geteilt:

convertedQuantity = printedQuantity * factor
convertedUnitPrice = printedUnitPrice / factor

Vor dem Runden bleibt das Produkt gleich. Die umgerechneten Werte haben höchstens drei Nachkommastellen; deshalb können die im Formular berechneten Kosten leicht vom gedruckten Referenzbetrag abweichen. Die ursprüngliche Einheit vermeidet diese Umrechnungsrundung.

Widersprüchliche physikalische Dimensionen verlangen mehr Vorsicht. Liter und ein ausdrücklich pro Kilowattstunde angegebener Preis lassen sich nicht zu Tankkosten verbinden. Menge und Einheit bleiben erhalten, der Preis bleibt leer.

Bei einer anderen gedruckten Währung kann die Person diese beibehalten. Wählt sie die konfigurierte Währung, bleibt die Menge und der Einzelpreis wird gelöscht. Es wird kein Wechselkurs unterstellt. Eine spätere Anzeige fremdwährungsbasierter Kosten übernimmt die datumsabhängige Umrechnungsschicht der App.

Der regionale Kontext kommt von der Geräteregion, unabhängig von der Oberflächensprache. Eine englische Oberfläche in Portugal macht Belege nicht amerikanisch. Explizite Währungscodes und Einheiten wiegen stärker als regionale Standardwerte.

Erkennung und Lebensdauer des Fotos

Unter iOS verwendet Vision genaue Erkennung bei deaktivierter Sprachkorrektur. Zahlen und Produktkürzel profitieren nicht von allen Annahmen, die Fließtext verbessern. Sprachhinweise werden vor ihrer Übergabe gegen die konfigurierte Vision-Anfrage geprüft.

Android enthält die Modelle für lateinische, chinesische, Devanagari-, japanische und koreanische Schrift aus der ML-Kit-Dokumentation. Das vergrößert die App und macht diese Erkennung offline verfügbar. Der Dokumentenscanner hat eigene Google-Play-services-Anforderungen und kann einen ersten Download brauchen; Bildauswahl und mitgelieferte OCR bieten einen Ausweichweg. Das bedeutet keine Unterstützung jedes Schriftsystems.

Die Orientierung wird in die Pixel eingerechnet. OCR-Rechtecke müssen zum angezeigten Foto passen. Beide nativen Implementierungen können bei dürftiger Erkennung Drehungen versuchen, aber einige zusätzliche Fragmente rechtfertigen nicht automatisch eine Drehung.

Temporäre Kopien gehören zu einer Scan-Sitzung. Eine abgebrochene Sitzung darf nach dem Aufräumen kein verspätetes Foto schreiben, und eine Prüfung darf nicht das Bild einer anderen löschen. Der Entwurf gehört zum anfordernden Formular und lässt sich einmal übernehmen. Eine spätere Rückkehr darf Korrekturen nicht mit dem alten Scan überschreiben.

Interpretation getrennt testen

Die Tests enthalten zwei echte Belegtranskriptionen und synthetische Fälle für regionale Formate, mehrdeutige Einheiten, Rabatte, ungültige Daten, alternative Lesarten und Teilübergaben. Sie prüfen die Verarbeitung des OCR-Texts, keine Erkennungsquote auf einem Bildkorpus. Schlechtes Licht, verblasster Druck und Schriftabdeckung benötigen weiterhin Gerätetests.

Diese Trennung erleichtert die Suche. Bei falschen Zeichen untersuche ich Aufnahme und Erkennung. Bei richtigen Zeichen und falschem Datensatz prüfe ich Parsernachweise und Formularübergabe. Ein vollständig aussehendes JSON würde diesen Unterschied verdecken.

Belegscans gehören zu OdoKeep. Wer Tank- oder Ladevorgänge erfasst, kann den Ablauf in der iOS-App ausprobieren: fotografieren, erkannte Werte prüfen und im gewohnten Formular abschließen.