# Fahrzeugschein-OCR: lokaler Vergleich Eine lokale Testoberfläche für zwei unabhängige Wege auf **demselben Bild**: | A: klassische OCR | B: Vision-Dokumentmodell | | --- | --- | | PP-OCRv5 mobile, Latin: Textzeilen und Zeilenboxen | PaddleOCR-VL 1.6 mit **Layout-Erkennung**: Dokumentregionen, Text und Tabellen | | Flexible, regelbasierte Feldvorschläge | Feldvorschläge aus gelesenen Layoutblöcken und Tabellen | Die Oberfläche zeigt Rohtext, Feldvorschläge, Bildbelege und Laufzeiten nebeneinander. Die Ecken des Dokuments lassen sich per Maus oder Touch setzen; alternativ wird das ganze Bild verwendet. Besondere Feldcodes: C.1.1 (Name), C.1.2 (Vorname), C.1.3 (Anschrift), B (Erstzulassung), 2.1 (HSN) und 2.2 (TSN). **Jeden Vorschlag am Bild prüfen.** Unleserliche oder unbelegte Werte bleiben offen. Es werden keine künstlichen Konfidenzwerte angezeigt. Dieses Repository enthält **keine Dokumentbilder, OCR-Ergebnisse, personenbezogenen Testdaten, Modellgewichte, privaten Hostnamen oder Zugangsdaten**. Die Tests nutzen erfundene Textzeilen und generierte Bilder. Ein Generator kann lokal synthetische Trainingsbeispiele erzeugen; dieses Repository startet selbst kein Training. Es gibt keine Datenübertragung an externe OCR- oder KI-APIs. Die offiziellen Modellgewichte werden beim Einrichten heruntergeladen; die Inferenz nutzt anschließend explizite lokale Modellverzeichnisse. Der optionale SSH-Modus überträgt das Bild ausschließlich an eine selbst verwaltete Maschine. Das Projekt ist für interne Tests gedacht und enthält keine öffentliche Lizenz. ## Voraussetzungen - Python 3.11 oder 3.12, Git und ausreichend freier Speicherplatz für PaddlePaddle, Abhängigkeiten und Modellgewichte. - macOS mit Apple Silicon oder Linux x86_64. Für die Vision-Pipeline kann eine eigene NVIDIA-GPU genutzt werden. Auf Apple Silicon läuft der hier genutzte PaddlePaddle-Pfad auf der CPU; Vision kann deutlich länger dauern. - Ein aktueller Browser. Der Webserver wird nur an `127.0.0.1` gebunden. Für entfernte Nutzung einen SSH-Tunnel verwenden, keinen öffentlichen Port öffnen. - Installiere **entweder** `paddlepaddle` für CPU **oder** `paddlepaddle-gpu` passend zu Treiber/CUDA, niemals beide in derselben Umgebung. Die [offizielle PaddleOCR-VL-Anleitung](https://www.paddleocr.ai/main/en/version3.x/pipeline_usage/PaddleOCR-VL.html) beschreibt die vollständige Pipeline und die Hardwarepfade. Für Apple Silicon gibt es eine [eigene Anleitung](https://www.paddleocr.ai/main/en/version3.x/pipeline_usage/PaddleOCR-VL-Apple-Silicon.html). Das Repo ist mit PaddleOCR 3.7.0 festgelegt; PaddlePaddle 3.2.1 oder neuer wird getrennt installiert. In den Beispielen steht `python3.12`; mit installiertem Python 3.11 kann stattdessen `python3.11` verwendet werden. ## macOS, Apple Silicon Im geklonten Repository: ```sh python3.12 -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip python -m pip install paddlepaddle==3.2.1 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/ python -m pip install -e '.[vision,test]' python -m ocr_compare.setup_models --classic --vision --device cpu OCR_VISION_MODE=local OCR_VISION_DEVICE=cpu python -m uvicorn ocr_compare.server:app --host 127.0.0.1 --port 8092 ``` Dann `http://127.0.0.1:8092/` öffnen. Die Modelleinrichtung nutzt ausschließlich ein im Skript erzeugtes Testbild. Die Gewichte liegen im ignorierten Verzeichnis `.cache/`. Je nach Mac und Bildgröße kann die Vision-Stufe ihr Zeitlimit erreichen; A bleibt dann trotzdem sichtbar. ## Linux x86_64, CPU ```sh python3.12 -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip python -m pip install paddlepaddle==3.2.1 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/ python -m pip install -e '.[vision,test]' python -m ocr_compare.setup_models --classic --vision --device cpu OCR_VISION_MODE=local OCR_VISION_DEVICE=cpu python -m uvicorn ocr_compare.server:app --host 127.0.0.1 --port 8092 ``` ## Linux x86_64 mit eigener NVIDIA-GPU Dieses Beispiel gilt für eine passende CUDA-12.6-Umgebung. Für andere CUDA-Versionen den [offiziellen Installationsweg](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/en/develop/install/pip/linux-pip_en.html) wählen. ```sh python3.12 -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip python -m pip install paddlepaddle-gpu==3.2.1 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/ python -m pip install -e '.[vision,test]' python -m ocr_compare.setup_models --classic --vision --device gpu:0 OCR_VISION_MODE=local OCR_VISION_DEVICE=gpu:0 python -m uvicorn ocr_compare.server:app --host 127.0.0.1 --port 8092 ``` Prüfe vorher `nvidia-smi` und den passenden Treiber. Beide Verfahren laufen lokal, wobei A die CPU und B die konfigurierte GPU nutzt. ### Vision auf einer eigenen Linux-Maschine per SSH Dieser Modus ist optional, wenn der Browser und A auf einem anderen Rechner laufen. Auf dem GPU-Rechner denselben Commit klonen, die obige GPU-Umgebung einrichten und dort `python -m ocr_compare.setup_models --vision --device gpu:0` ausführen. Auf dem lokalen Rechner A samt CPU-PaddlePaddle und `python -m ocr_compare.setup_models --classic` einrichten; die Vision-Zusatzpakete sind dort nicht nötig (`python -m pip install -e '.[test]'`). Vorhandenen SSH-Zugang mit bereits bekanntem Hostschlüssel verwenden. Auf dem lokalen Rechner die eigenen Werte als Umgebungsvariablen setzen (Beispielnamen sind Platzhalter): ```sh export OCR_VISION_MODE=ssh export OCR_VISION_SSH_TARGET='user@gpu-host' export OCR_VISION_REMOTE_DIR='/path/to/clone' export OCR_VISION_REMOTE_PYTHON='./.venv/bin/python' export OCR_VISION_REMOTE_DEVICE='gpu:0' python -m uvicorn ocr_compare.server:app --host 127.0.0.1 --port 8092 ``` Optional: `OCR_VISION_SSH_IDENTITY` für einen **bereits vorhandenen** privaten Schlüssel, `OCR_VISION_REMOTE_MODEL_HOME` für einen abweichenden Cachepfad, `OCR_VISION_REMOTE_UNSHARE=1` für Linux-Netzwerk-Isolation, sofern der Zielhost User Namespaces erlaubt. Der entfernte Befehl benötigt GNU `timeout`. Bilddateien werden dort in einem temporären, nach dem Lauf gelöschten Verzeichnis verarbeitet. Lege echte Dokumente und SSH-Schlüssel nie im Clone ab. ## Windows Mit WSL2/Ubuntu die Linux-Schritte **innerhalb von WSL2** ausführen. Native Windows-Installation ist für diesen Stand nicht getestet; die [PaddleOCR-Dokumentation](https://www.paddleocr.ai/main/en/version3.x/installation.html) ist dafür die Referenz. ## Bedienung und Grenzen 1. JPEG oder PNG hochladen (maximal 16 MiB und 24 Megapixel). 2. Bei Bedarf vier äußere Ecken setzen und die Leserichtung wählen. 3. Beide Ergebnisse vergleichen. Ein Fehler bei B unterdrückt A nicht. 4. Rohtext und die markierten Bildbereiche prüfen. Automatische Vorschläge lassen sich verwerfen; erkannte Textzeilen können manuell einem Feld zugeordnet werden. Die klassische OCR liefert präzisere Zeilenboxen, kann aber Text verlesen. Die Vision-Pipeline erkennt Layout und Tabellen, ihre Belege können ganze Regionen statt einzelner Wörter markieren. Die Zuordnung ist bewusst konservativ und kein amtliches Auslesen. Dieses Repository enthält keine belastbare Erkennungsquote für reale Fahrzeugscheine. Die App verarbeitet Uploads im Speicher und in kurzlebigen temporären Dateien. Sie schreibt weder Dokumente noch OCR-Ausgaben in ein dauerhaftes Verzeichnis. Browser und eigener Server sehen die Bilddaten; bei SSH-Betrieb auch der eigene SSH-Zielhost. Vor dem Einsatz mit echten Dokumenten sollten Modelle bereits eingerichtet sein. Ein fehlender Cache wird als Fehler angezeigt, statt beim Upload Modellgewichte nachzuladen. ## Synthetische Daten und Training Der Generator erzeugt **sichtbar ungültige, erfundene** Fahrzeugformulare mit variierter Feldreihenfolge, Schrift, Dichte und Bildstörung. Er liest keine Quelldokumente. Ausgabe und Modellartefakte liegen unter dem von Git ignorierten `data/`-Verzeichnis. Niemals echte Dokumente, daraus ausgeschnittene Texte oder OCR-Ausgaben in diesen Trainingssatz mischen. ```sh python -m ocr_compare.synthetic --out data/synthetic-v1 --count 100 --seed 20261007 python -m ocr_compare.benchmark_synthetic --dataset data/synthetic-v1 ``` Vor dem Benchmark die **klassischen** Modelle mit `python -m ocr_compare.setup_models --classic` lokal einrichten. Der Benchmark verarbeitet standardmäßig nur den nach ganzen Dokumenten getrennten Validierungsteil; `--split train` und `--split all` sind für die Fehlersuche gedacht. Er gibt ausschließlich Summen aus: an Wertboxen überlappende OCR-Zeilen, dort vollständig gelesene Werte und korrekt, falsch oder gar nicht zugeordnete Zielfelder. Für eine neue Stichprobe ein neues Ausgabeverzeichnis und einen anderen Seed nehmen. Der Generator überschreibt nichts. Der Satz enthält `rec_train.txt`/`rec_val.txt` mit Bildpfad und Text für die PaddleOCR-Texterkennung sowie `det_train.txt`/`det_val.txt` mit Seitenpfad und Zeilenpolygonen für die Texterkennung auf der Seite. `ground_truth.jsonl` enthält die exakten synthetischen Sollwerte für C.1.1, C.1.2, C.1.3, B, 2.1 und 2.2. Eine Validierung der Labels und des Auswertungscodes ist in den lokalen Tests enthalten; **ein Modelltraining und dessen Export sind hier noch nicht getestet**. Für einen Trainingsexperiment zuerst den Fehler nach Stufe messen: Fehlende Textboxen sprechen für den [Detektor](https://www.paddleocr.ai/main/en/version3.x/module_usage/text_detection.html), falsch gelesene vorhandene Boxen für den [Recognizer](https://www.paddleocr.ai/main/en/version3.x/module_usage/text_recognition.html). Korrekt gelesene Werte mit falschem Feldcode sind ein Zuordnungs- oder Layoutproblem. PaddleOCR-VL ist eine Pipeline aus Layoutanalyse und VLM. Die [offizielle SFT-Anleitung](https://www.paddleocr.ai/main/en/version3.x/pipeline_usage/PaddleOCR-VL.html#5-model-fine-tuning) unterstützt zurzeit nur das VLM; die [ERNIEKit-Beispielkonfiguration](https://github.com/PaddlePaddle/ERNIE/blob/release/v1.4/docs/paddleocr_vl_sft.md) wurde auf einer 80-GB-GPU demonstriert. Das ist keine belastbare Zusage für Training auf einer kleineren lokalen GPU. Synthetische Validierung allein beweist keine Verbesserung bei echten Dokumenten: Diese ausschließlich als unveränderten, lokalen **Test-Holdout** verwenden, nie zum Training. ## Prüfen und Fehler eingrenzen ```sh python -m unittest discover -s tests -v curl -fsS http://127.0.0.1:8092/api/health ``` Wenn A oder B `Modelle fehlen` zeigt: Modelleinrichtung in **derselben** Umgebung und auf dem betroffenen Host ausführen. Für einen anderen privaten Modellcache vor Einrichtung und Serverstart `OCR_MODEL_HOME=/path/to/cache` setzen. Bei SSH zusätzlich `OCR_VISION_REMOTE_MODEL_HOME`, falls der entfernte Cache nicht unter `.cache/` im Clone liegt. Bei `Vision-Konfiguration` Ziel, Clonepfad, Pythonpfad und SSH-Erreichbarkeit prüfen. Bei Zeitlimit zunächst ein gut ausgerichtetes, kleineres Bild versuchen; CPU-Vision kann hierfür ungeeignet sein. `config.example.env` dokumentiert alle optionalen Variablen. Sie wird nicht automatisch geladen. Lokale Konfigurationen und Modellgewichte gehören nicht ins Git-Repository. ## Vor einem Repository-Push Die `.gitignore` lässt nur Quellcode, Tests und diese Anleitung zu. Auch damit gilt: keine echten Dokumente, Ergebnisse, Schlüssel, privaten Konfigurationen oder Modellgewichte committen. Nach dem Staging die **tatsächlich vorgemerkten Git-Blobs** prüfen: ```sh git status --short python scripts/release_audit.py git diff --cached --stat ``` Der Audit nennt bei einem Fund nur Regel und Dateipfad, niemals den gefundenen Inhalt. Er ersetzt keine Codeprüfung. Das Repository für Kollegen privat halten und Zugriffsrechte im eigenen Gitea-Team setzen.