Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 30s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 2m28s
CI / test-python-agent-core (push) Successful in 17s
CI / test-nodejs-website (push) Successful in 18s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
254 lines
10 KiB
Markdown
254 lines
10 KiB
Markdown
# OCR Kombi Pipeline - Modulare 11-Schritt-Architektur
|
|
|
|
**Version:** 1.0.0
|
|
**Status:** Phase 1 implementiert (Grundgeruest + DB)
|
|
**URL:** https://macmini:3002/ai/ocr-kombi
|
|
|
|
## Uebersicht
|
|
|
|
Die OCR Kombi Pipeline ist der Nachfolger des OCR-Overlay-Monolithen (`/ai/ocr-overlay`).
|
|
Sie zerlegt den OCR-Prozess in **11 modulare Schritte** mit je einer eigenen Komponente
|
|
pro Frontend- und Backend-Datei. Ziel: schnelles Debugging, klare Verantwortlichkeiten,
|
|
Multi-Page-Dokument-Unterstuetzung.
|
|
|
|
**Primaerer Modus:** Kombi (PaddleOCR + Tesseract) — der einzige Modus, den der User nutzt.
|
|
|
|
### Warum ein Refactor?
|
|
|
|
| Problem (alt) | Loesung (neu) |
|
|
|----------------|---------------|
|
|
| `page.tsx` = 751-Zeilen-Monolith mit 3 Modi | `page.tsx` = ~140-Zeilen-Orchestrator, je 1 Datei pro Step |
|
|
| Upload, Orientierung und Page-Split in einem Step | 3 separate Steps mit eigener Logik |
|
|
| Keine Multi-Page-Dokument-Unterstuetzung | `document_group_id` + `page_number` auf DB-Ebene |
|
|
| OCR intransparent (eine Blackbox) | 3-Phasen-Fortschritt + Engine-Attribution pro Wort (geplant) |
|
|
| `grid_editor_api.py` = 1801 Zeilen | 4 Module + Orchestrator (geplant) |
|
|
|
|
---
|
|
|
|
## Pipeline-Schritte
|
|
|
|
| # | Step | Frontend | Backend | Beschreibung |
|
|
|---|------|----------|---------|--------------|
|
|
| 1 | Upload | `StepUpload.tsx` | `step_upload.py` | Bild/PDF hochladen, Titel, Kategorie. Multi-Page-PDF → N Sessions |
|
|
| 2 | Orientierung | `StepOrientation.tsx` | (shared) | Rotation 90/180/270 erkennen + korrigieren |
|
|
| 3 | Seitentrennung | `StepPageSplit.tsx` | (shared) | Doppelseiten erkennen + splitten |
|
|
| 4 | Begradigung | `StepDeskew.tsx` | (shared) | Hough Lines + Word Alignment |
|
|
| 5 | Entzerrung | `StepDewarp.tsx` | (shared) | Shear-Korrektur (Vertikalkanten-Drift) |
|
|
| 6 | Zuschneiden | `StepContentCrop.tsx` | (shared) | Scanner-Raender entfernen (nach Begradigung!) |
|
|
| 7 | OCR | `StepOcr.tsx` | (shared) | Tesseract + PaddleOCR + Merge |
|
|
| 8 | Strukturerkennung | `StepStructure.tsx` | (shared) | Boxen, Zonen, Farben, Grafiken |
|
|
| 9 | Grid-Aufbau | `StepGridBuild.tsx` | (shared) | Strukturiertes Grid aus OCR + Struktur |
|
|
| 10 | Grid-Review | `StepGridReview.tsx` | (shared) | Excel-Editor, IPA, Silben, Korrekturen |
|
|
| 11 | Ground Truth | `StepGroundTruth.tsx` | (shared) | Validierung + GT-Markierung |
|
|
|
|
!!! note "Crop nach Dewarp"
|
|
Seitentrennung (Step 3) passiert **vor** Begradigung — richtig, weil jede Haelfte
|
|
unabhaengig begradigt wird. Der Content-Crop (Step 6) bleibt **nach** Dewarp,
|
|
weil content-basierter Crop auf geradem Bild besser funktioniert.
|
|
|
|
---
|
|
|
|
## Multi-Page-Dokument-Gruppierung
|
|
|
|
### Problem
|
|
|
|
Ein Lehrer scannt 10 Vokabelseiten als eine PDF-Datei. Im Endnutzer-Frontend soll das
|
|
ein zusammenhaengendes Dokument sein. Alle Seiten muessen spaeter zu gemeinsamen
|
|
Lern-Units verarbeitet werden koennen.
|
|
|
|
### Loesung: `document_group_id` + `page_number`
|
|
|
|
Zwei neue Felder auf `ocr_pipeline_sessions` (Migration `009_add_document_group.sql`):
|
|
|
|
```sql
|
|
ALTER TABLE ocr_pipeline_sessions
|
|
ADD COLUMN IF NOT EXISTS document_group_id UUID,
|
|
ADD COLUMN IF NOT EXISTS page_number INT;
|
|
```
|
|
|
|
| Upload-Typ | document_group_id | page_number |
|
|
|------------|-------------------|-------------|
|
|
| Einzelbild | neues UUID | 1 |
|
|
| Multi-Page-PDF (10 Seiten) | gleiches UUID fuer alle 10 | 1..10 |
|
|
| Doppelseiten-Split von S. 3 | gleiches UUID | neue S. 3 + S. 4, Rest umkontiert |
|
|
|
|
### Benennung
|
|
|
|
Upload-Titel "Vokabeln Unit 3" erzeugt:
|
|
|
|
- "Vokabeln Unit 3 — S. 1"
|
|
- "Vokabeln Unit 3 — S. 2"
|
|
- ...
|
|
- "Vokabeln Unit 3 — S. 10"
|
|
|
|
### Session-Liste im Admin
|
|
|
|
Gruppierte Anzeige: Ein Dokument-Header ("Vokabeln Unit 3, 10 Seiten") mit aufklappbaren
|
|
Einzel-Sessions darunter. Jede Session hat eigenen Pipeline-Status.
|
|
|
|
---
|
|
|
|
## API-Endpoints
|
|
|
|
### Neue Endpoints (OCR Kombi)
|
|
|
|
| Methode | Pfad | Beschreibung |
|
|
|---------|------|--------------|
|
|
| POST | `/api/v1/ocr-kombi/upload` | Upload: Einzelbild oder Multi-Page-PDF |
|
|
| GET | `/api/v1/ocr-kombi/documents/{group_id}` | Alle Sessions einer Dokumentgruppe |
|
|
|
|
### Bestehende Endpoints (wiederverwendet)
|
|
|
|
Die Kombi-Pipeline nutzt alle bestehenden Endpoints aus `/api/v1/ocr-pipeline/`:
|
|
|
|
| Methode | Pfad | Step |
|
|
|---------|------|------|
|
|
| POST | `/sessions` | Upload (Legacy, Einzelbild) |
|
|
| POST | `/sessions/{id}/orientation` | Orientierung |
|
|
| POST | `/sessions/{id}/page-split` | Seitentrennung |
|
|
| POST | `/sessions/{id}/deskew` | Begradigung |
|
|
| POST | `/sessions/{id}/dewarp` | Entzerrung |
|
|
| POST | `/sessions/{id}/crop` | Zuschneiden |
|
|
| POST | `/sessions/{id}/paddle-kombi` | OCR (Kombi) |
|
|
| POST | `/sessions/{id}/detect-structure` | Strukturerkennung |
|
|
| POST | `/sessions/{id}/build-grid` | Grid-Aufbau |
|
|
| POST | `/sessions/{id}/save-grid` | Grid speichern |
|
|
| GET | `/sessions/{id}/grid-editor` | Grid laden |
|
|
| POST | `/sessions/{id}/mark-ground-truth` | GT markieren |
|
|
|
|
---
|
|
|
|
## Dateistruktur
|
|
|
|
### Frontend
|
|
|
|
```
|
|
admin-lehrer/app/(admin)/ai/ocr-kombi/
|
|
├── page.tsx # ~140 Zeilen, Orchestrator mit Suspense-Boundary
|
|
├── types.ts # KOMBI_V2_STEPS (11 Steps), DocumentGroup-Types, OCR-Transparenz-Types
|
|
└── useKombiPipeline.ts # Hook: Session-State, Step-Navigation, Dokument-Gruppierung
|
|
|
|
admin-lehrer/components/ocr-kombi/
|
|
├── KombiStepper.tsx # 11-Step-Indikator (kompakt, scrollbar)
|
|
├── SessionList.tsx # Gruppierte Session-Liste (Dokumentgruppen aufklappbar)
|
|
├── SessionHeader.tsx # Aktive Session: Name + Kategorie + GT-Badge
|
|
├── StepUpload.tsx # Drag-Drop + Titel + Kategorie-Auswahl
|
|
├── StepOrientation.tsx # Wrapper → shared StepOrientation
|
|
├── StepPageSplit.tsx # Doppelseiten-Erkennung + Auto-Advance
|
|
├── StepDeskew.tsx # Wrapper → shared StepDeskew
|
|
├── StepDewarp.tsx # Wrapper → shared StepDewarp
|
|
├── StepContentCrop.tsx # Wrapper → shared StepCrop
|
|
├── StepOcr.tsx # Wrapper → PaddleDirectStep (kombi endpoint)
|
|
├── StepStructure.tsx # Wrapper → shared StepStructureDetection
|
|
├── StepGridBuild.tsx # Auto-Trigger build-grid + Ergebnis-Anzeige
|
|
├── StepGridReview.tsx # Wrapper → shared StepGridReview (mit saveRef)
|
|
└── StepGroundTruth.tsx # GT-Markierung mit Auto-Save
|
|
```
|
|
|
|
### Backend
|
|
|
|
```
|
|
klausur-service/backend/ocr_kombi/
|
|
├── __init__.py
|
|
├── router.py # Composite Router (/api/v1/ocr-kombi)
|
|
└── step_upload.py # Multi-Page-PDF → N Sessions + document_group_id
|
|
```
|
|
|
|
### Shared (wiederverwendet)
|
|
|
|
Die Kombi-Pipeline nutzt alle bestehenden Backend-Module:
|
|
|
|
- `orientation_crop_api.py` — Orientierung, Page-Split, Crop
|
|
- `ocr_pipeline_api.py` — Deskew, Dewarp
|
|
- `ocr_pipeline_ocr_merge.py` — PaddleOCR + Tesseract Merge
|
|
- `grid_editor_api.py` — Grid-Aufbau + Editor
|
|
- `ocr_pipeline_session_store.py` — DB-Layer (erweitert um document_group_id)
|
|
- Alle `cv_*.py` — CV-Algorithmen
|
|
|
|
### Migration
|
|
|
|
```
|
|
migrations/009_add_document_group.sql # document_group_id UUID + page_number INT + Index
|
|
```
|
|
|
|
---
|
|
|
|
## Implementierungsphasen
|
|
|
|
| Phase | Status | Beschreibung |
|
|
|-------|--------|--------------|
|
|
| **1: Grundgeruest + DB** | Implementiert | DB-Migration, Types, Hook, Stepper, SessionList, page.tsx, Navigation, Backend-Router |
|
|
| **2: Vorverarbeitungs-Steps** | Geplant | Multi-Page-PDF-Upload, Orientierung ohne Upload, Seitentrennung mit document_group_id |
|
|
| **3: OCR-Transparenz** | Geplant | 3-Phasen-Fortschritt, Engine-Attribution pro Wort, Farbkodierung |
|
|
| **4: Grid-Pipeline aufteilen** | Geplant | grid_editor_api.py → 4 Module + Orchestrator |
|
|
| **5: Restliche Steps** | Geplant | Structure, GridBuild, GridReview, GroundTruth voll integriert |
|
|
| **6: Features migrieren** | Spaeter | LLM-Review-Streaming, Labeling-Mode, Bild-Generierung |
|
|
| **7: Aufraeumen** | Spaeter | /ai/ocr-overlay und /ai/ocr-pipeline loeschen |
|
|
|
|
---
|
|
|
|
## OCR-Transparenz (Phase 3, geplant)
|
|
|
|
### 3-Phasen-Fortschritt in Step 7
|
|
|
|
1. "Tesseract laeuft..." (Fortschrittsbalken)
|
|
2. "PaddleOCR laeuft..." (Fortschrittsbalken)
|
|
3. "Merge laeuft..." (Fortschrittsbalken)
|
|
|
|
### Engine-Attribution pro Wort
|
|
|
|
Vergleichsansicht mit Farbkodierung:
|
|
|
|
| Farbe | Bedeutung |
|
|
|-------|-----------|
|
|
| Gruen | Beide Engines einig |
|
|
| Blau | Nur PaddleOCR |
|
|
| Orange | Nur Tesseract |
|
|
| Gelb | Konflikt, PaddleOCR gewaehlt |
|
|
| Rot | Konflikt, Tesseract gewaehlt |
|
|
|
|
### Geplanter Endpoint
|
|
|
|
```
|
|
POST /sessions/{id}/ocr-kombi-transparent
|
|
→ { raw_tesseract, raw_paddle, merged, engine_source_per_word }
|
|
```
|
|
|
|
---
|
|
|
|
## Grid-Pipeline-Aufteilung (Phase 4, geplant)
|
|
|
|
`grid_editor_api.py` (1801 Zeilen) wird aufgeteilt in:
|
|
|
|
| Modul | Inhalt | ~Zeilen |
|
|
|-------|--------|---------|
|
|
| `grid_build_filters.py` | Margin, Footer, Header, Exclude, Grafik-Filter | ~200 |
|
|
| `grid_build_zones.py` | Box-Detect, Page-Zones, Vert-Dividers | ~250 |
|
|
| `grid_build_columns.py` | Spalten-Clustering + Union-Merge + Zone-Grids | ~300 |
|
|
| `grid_build_postprocess.py` | Row/Cell-Postprocessing, IPA, Farben, Dictionary | ~500 |
|
|
|
|
`grid_editor_api.py` wird zum schlanken Orchestrator.
|
|
|
|
---
|
|
|
|
## Verhaeltnis zu bestehenden Pipelines
|
|
|
|
| Pipeline | Route | Status | Beschreibung |
|
|
|----------|-------|--------|--------------|
|
|
| **OCR Kombi** | `/ai/ocr-kombi` | Aktiv (neu) | Modulare 11-Schritt-Pipeline |
|
|
| OCR Overlay | `/ai/ocr-overlay` | Legacy | 751-Zeilen-Monolith, 3 Modi |
|
|
| OCR Pipeline | `/ai/ocr-pipeline` | Legacy | Volle Pipeline mit Spalten |
|
|
| OCR Compare | `/ai/ocr-compare` | Eigenstaendig | Methoden-Vergleich |
|
|
|
|
Die alte OCR Overlay (`/ai/ocr-overlay`) bleibt waehrend des gesamten Umbaus parallel nutzbar
|
|
fuer A/B-Tests. Sobald die Kombi-Pipeline feature-complete ist, werden die alten Pipelines
|
|
in Phase 7 entfernt.
|
|
|
|
---
|
|
|
|
## Aenderungshistorie
|
|
|
|
| Datum | Version | Aenderung |
|
|
|-------|---------|-----------|
|
|
| 2026-03-26 | 1.0.0 | **Phase 1:** Grundgeruest mit 11-Step-Architektur, DB-Migration (document_group_id, page_number), Backend-Router mit Multi-Page-Upload, Frontend mit SessionList (gruppiert), KombiStepper, 13 Step-Komponenten, useKombiPipeline Hook, Navigation |
|