OCR ist Texterkennung aus einem Bild. Ein erkanntes Wort ist noch keine bestätigte Ablesung. Fotos können Seriennummern, Datumsangaben und mehrere Zahlen enthalten. Zählerstand Log erzeugt deshalb Kandidaten und verlangt eine Nutzerbestätigung. Fahrzeugakte verwendet zusätzlich einen Dokumentenscanner für PDF-Belege, ohne daraus automatisch eine Rechnungsanalyse zu machen. Wir modellieren den gemeinsamen Ablauf über einen Port und testen zuerst mit kontrollierter Erkennung.
01Die Erkennungsgrenze definieren
OcrPort liefert erkannte Textzeilen. Der Lernadapter liefert feste Zeilen statt einer Kameraaufnahme. Dadurch können wir den fachlichen Ablauf auf jedem Computer ausführen. Er beweist keine echte OCR-Qualität.
abstract interface class OcrPort {
Future<List<String>> recognize(String image);
}
class LearningOcr implements OcrPort {
@override
Future<List<String>> recognize(String image) async => [
'Meter 12345',
'Reading 64820.5 kWh',
];
}
class CaptureService {
CaptureService(this.ocr);
final OcrPort ocr;
final saved = <String>[];
Future<List<String>> propose(String image) async {
final lines = await ocr.recognize(image);
final pattern = RegExp(r'\b\d{1,6}(?:[.,]\d{1,3})?\b');
return [
for (final line in lines)
for (final match in pattern.allMatches(line)) match.group(0)!,
];
}
void confirm(String candidate, {required bool accepted}) {
if (!accepted) return;
if (!RegExp(r'^\d{1,6}(?:[.,]\d{1,3})?$').hasMatch(candidate))
throw ArgumentError('Invalid value');
saved.add(candidate.replaceAll(',', '.'));
}
}
Future<void> main() async {
final service = CaptureService(LearningOcr());
final candidates = await service.propose('synthetic-photo');
if (service.saved.isNotEmpty) throw StateError('Saved before confirmation');
service.confirm(candidates.last, accepted: false);
if (service.saved.isNotEmpty) throw StateError('Saved after rejection');
service.confirm(candidates.last, accepted: true);
print(service.saved);
}
Starten / prüfen
dart run capture.dart02Kandidaten erzeugen
Die kleine Regex sucht Zahlen mit optionalem Dezimalteil. Sie ist ausdrücklich kein Ersatz für die echte Kandidatenextraktion. Dort werden unter anderem Zeilen, Positionen und getrennte Zifferngruppen berücksichtigt. Das Lernbeispiel darf mehrere Vorschläge zurückgeben.
03Die Bestätigung als eigene Aktion halten
propose schreibt keine Ablesung. confirm verlangt einen Kandidaten und eine ausdrückliche Entscheidung. Eine echte Oberfläche zeigt Foto und Wert nebeneinander, erlaubt eine Korrektur und prüft erst danach die Fachregel.
04Ressourcen und Abbruch behandeln
Der echte ML-Kit-Adapter schließt TextRecognizer in finally. Ein Abbruch darf keinen Entwurf heimlich bestätigen. Der Service muss Fehler von Kamera, fehlendem Plugin und ungültigem Ergebnis unterscheiden. Die Oberfläche behält einen sinnvollen Wiederholungsweg.
05Scanner und OCR auseinanderhalten
Der Dokumentenscanner in Fahrzeugakte erstellt eine PDF mit bearbeitbaren Scan-Seiten. Die App kopiert das Ergebnis kontrolliert zum Eintrag. Zähler-OCR erzeugt dagegen einen Wertvorschlag. Beide benötigen Geräteadapter, aber ihre fachlichen Ergebnisse sind unterschiedlich.
Vor Bestätigung ist saved leer. Ablehnung bleibt leer. Bestätigung fügt genau den ausgewählten Wert hinzu.
06Den echten Geräteablauf prüfen
Teste auf Android ein klares und ein unscharfes Foto, fehlende Berechtigung, Abbruch und mehrere Zahlen. Prüfe, dass vor Bestätigung keine Ablesung existiert. Browsertests ersetzen diesen Nachweis nicht. Bei Google-ML-Kit-Scannerfunktionen gelten die im Produkt dokumentierten Geräte- und Play-Services-Anforderungen.
- Foto / Scan
- Geräte-Port
- OCR-Kandidaten
- Nutzerprüfung
- Fachregel / Speichern
Deine Übung
Ergänze einen OcrPort, der einen Fehler wirft. Prüfe, dass saved unverändert bleibt.
Lösung mit Erklärung anzeigen
Die Exception muss vor confirm auftreten. Fange sie an der Anwendungsgrenze ab und biete erneute Erfassung oder manuelle Eingabe an. Speichere keinen erfundenen 0-Wert. Ein zusätzlicher Test prüft einen abgelehnten Kandidaten und einen ausdrücklich korrigierten Wert.
Projektbezug und Quellen
Das Beispiel ist zum Lernen vereinfacht. Die verlinkte Codeversion zeigt die Anwendung im Projekt und die dortigen Prüfungen.