feat(ocr): mobile on-device TrOCR-handwritten — Spike-#77-Pivot mit Handwriting-Modell #421 #422

Closed
admin-mrrm wants to merge 2 commits from feat/421-ocr-handwritten-mobile into main
Owner

Closes #421

Was geändert wird

Spike-#77-Mechanik bleibt — nur das Modell tauscht. Xenova/trocr-small-printed (CER 0.51 auf Real-Daten, #416) → Xenova/trocr-small-handwritten. Konfig-Werte verifiziert identisch: 6 decoder layers, 384x384 input, decoder_start_token_id=2, eos=2.

Restoration

Files aus archive/spike-77-ocr-mobile:

  • apps/mobile/src/services/ocr-service.ts — Singleton mit ORT-RN + KV-cache Greedy-Decode
  • apps/mobile/src/services/ocr-service.spec.ts — 10 Specs (alle grün)
  • apps/mobile/src/services/ocr-model-assets.ts — Metro asset-handle wrapper
  • apps/mobile/app/ocr-spike.tsx — Debug-Screen (Route: /ocr-spike)
  • apps/mobile/assets/ocr-model/.gitignore für .onnx, README, Sample-JPG
  • apps/mobile/metro.config.js.onnx als asset-ext registriert
  • apps/mobile/app/_layout.tsx — Stack.Screen für /ocr-spike
  • deps: expo-asset@~12.0.13, jpeg-js@^0.4.4

ONNX-Weights

Int8-quantisierte Files aus Xenova/trocr-small-handwritten/onnx/:

  • encoder_model.onnx (~22 MB)
  • decoder_model.onnx (~38 MB)
  • decoder_with_past_model.onnx (~37 MB)

Bundle-Total: ~98 MB. Bleiben .gitignored — Repro-Workflow in apps/mobile/assets/ocr-model/README.md dokumentiert.

Test plan

  • pnpm --filter @mrrmlab/mobile typecheck clean
  • pnpm --filter @mrrmlab/mobile test — 71/71 grün (inkl. 10 ocr-service Specs)
  • EAS-Build erzeugt funktionsfähige Dev-Client-APK
  • /ocr-spike-Route liefert nicht-leeres OCR-Ergebnis auf Pixel mit Sample-JPG
  • OCR-Quality-Check: handschriftlicher Einkaufszettel-Crop → erwartet plausibler Text
  • CER-Eval auf den 77 Real-Daten-Crops aus #416 (optional, post-PR)

Was DIESER PR NICHT macht

  • Keine Integration mit image-preview.tsx / parseImage-Flow (kommt nach Device-Test-Validierung)
  • Keine Web-OCR-Änderung (bleibt EasyOCR)
  • Kein Bundle-Größen-Optimierungs-Pass (98 MB akzeptiert für jetzt)

Risk-Note

small-handwritten ist auf IAM-Datensatz finetuned. Real-Einkaufszettel-Performance unbekannt — wenn CER > 0.3, eskaliert zu base-handwritten (~280 MB Bundle). Decision-Point nach Device-Eval.

Closes #421 ## Was geändert wird **Spike-#77-Mechanik bleibt — nur das Modell tauscht.** `Xenova/trocr-small-printed` (CER 0.51 auf Real-Daten, #416) → `Xenova/trocr-small-handwritten`. Konfig-Werte verifiziert identisch: 6 decoder layers, 384x384 input, decoder_start_token_id=2, eos=2. ## Restoration Files aus `archive/spike-77-ocr-mobile`: - `apps/mobile/src/services/ocr-service.ts` — Singleton mit ORT-RN + KV-cache Greedy-Decode - `apps/mobile/src/services/ocr-service.spec.ts` — 10 Specs (alle grün) - `apps/mobile/src/services/ocr-model-assets.ts` — Metro asset-handle wrapper - `apps/mobile/app/ocr-spike.tsx` — Debug-Screen (Route: `/ocr-spike`) - `apps/mobile/assets/ocr-model/` — `.gitignore` für `.onnx`, README, Sample-JPG - `apps/mobile/metro.config.js` — `.onnx` als asset-ext registriert - `apps/mobile/app/_layout.tsx` — Stack.Screen für `/ocr-spike` - deps: `expo-asset@~12.0.13`, `jpeg-js@^0.4.4` ## ONNX-Weights Int8-quantisierte Files aus `Xenova/trocr-small-handwritten/onnx/`: - `encoder_model.onnx` (~22 MB) - `decoder_model.onnx` (~38 MB) - `decoder_with_past_model.onnx` (~37 MB) Bundle-Total: **~98 MB**. Bleiben `.gitignore`d — Repro-Workflow in `apps/mobile/assets/ocr-model/README.md` dokumentiert. ## Test plan - [x] `pnpm --filter @mrrmlab/mobile typecheck` clean - [x] `pnpm --filter @mrrmlab/mobile test` — 71/71 grün (inkl. 10 ocr-service Specs) - [ ] EAS-Build erzeugt funktionsfähige Dev-Client-APK - [ ] `/ocr-spike`-Route liefert nicht-leeres OCR-Ergebnis auf Pixel mit Sample-JPG - [ ] OCR-Quality-Check: handschriftlicher Einkaufszettel-Crop → erwartet plausibler Text - [ ] CER-Eval auf den 77 Real-Daten-Crops aus #416 (optional, post-PR) ## Was DIESER PR NICHT macht - Keine Integration mit `image-preview.tsx` / `parseImage`-Flow (kommt nach Device-Test-Validierung) - Keine Web-OCR-Änderung (bleibt EasyOCR) - Kein Bundle-Größen-Optimierungs-Pass (98 MB akzeptiert für jetzt) ## Risk-Note `small-handwritten` ist auf IAM-Datensatz finetuned. Real-Einkaufszettel-Performance unbekannt — wenn CER > 0.3, eskaliert zu `base-handwritten` (~280 MB Bundle). Decision-Point nach Device-Eval.
feat(ocr): mobile on-device TrOCR-handwritten — Spike-#77-Scaffolding restored mit Handwriting-Modell (#421)
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
399e35b455
Pivot nach Spike-#77-Exit (Business-No durch CER 0.51 auf real-Daten mit
`-small-printed`): Architektur-Mechanik aus Spike behalten, Modell tauschen.

Drop-in-Swap: `Xenova/trocr-small-handwritten` ist konfig-identisch zu
`-small-printed` — 6 decoder layers, 384x384 input, decoder_start_token_id=2,
eos=2, identische tokenizer.json-Struktur. Kein ONNX-Export, kein Code-Change
in der Decode-Schleife. Nur:

- MODEL_REPO-Konstante getauscht
- ONNX-Weights (int8) aus Xenova-Repo ins bundle gezogen (~98 MB)
- READMEs + Kommentare auf Handwriting-Kontext angepasst

Files aus `archive/spike-77-ocr-mobile` zurückgeholt: ocr-service.ts (mit
KV-cache Greedy-Decode), ocr-service.spec.ts (10 grüne Specs, alle pass),
ocr-model-assets.ts, ocr-spike.tsx (Debug-Screen), metro.config.js
.onnx-asset-Registrierung, expo-asset + jpeg-js deps.

Stakeholder-Trade-off (akzeptiert): handgeschriebene OCR mobile-only,
Web bleibt EasyOCR (Server hat keine GPU für TrOCR-handwritten).

Refs #421
chore(build): .easignore — OCR-Modelle aus .gitignore re-includen für EAS-Upload
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
00c830d34c
Die int8-TrOCR-Weights in apps/mobile/assets/ocr-model/ sind via .gitignore
vom Repo-Commit ausgeschlossen (~98 MB Binär-Bloat). EAS-Build nutzt aber
.gitignore zur Upload-Bestimmung — Folge: Build ohne Modelle, OCR-Spike
crasht beim asset-load.

.easignore überschreibt .gitignore für den EAS-Build-Upload und re-included
explizit *.onnx unter apps/mobile/assets/ocr-model/. Identisch zur
Spike-77-Lösung (aa028c6, vor archive).

Refs #421
Collaborator

PR on hold — siehe #423. ML-Kit-Spike läuft, EAS-Build queued (de0beabb). Wenn ML Kit das „Oregano"-Sample sauber liest, wird dieser PR geschlossen. Falls ML Kit ebenfalls failt, kommen wir hierauf zurück.

PR on hold — siehe #423. ML-Kit-Spike läuft, EAS-Build queued (`de0beabb`). Wenn ML Kit das „Oregano"-Sample sauber liest, wird dieser PR geschlossen. Falls ML Kit ebenfalls failt, kommen wir hierauf zurück.
Collaborator

Geschlossen — superseded by #424. ML Kit liefert auf demselben „Oregano"-Sample „Oreg amo" (CER ≈ 0.28) statt TrOCRs „consequences" (CER ≈ 1.0).

Geschlossen — superseded by #424. ML Kit liefert auf demselben „Oregano"-Sample „Oreg amo" (CER ≈ 0.28) statt TrOCRs „consequences" (CER ≈ 1.0).
pm-bot closed this pull request 2026-05-28 17:03:13 +02:00
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
Required
Details

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
admin-mrrm/mrrmlabapp!422
No description provided.