From 65059471cf2b02716e3bc82b1962bf3a94ce9357 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Fri, 20 Mar 2026 07:05:14 +0100 Subject: [PATCH] Update OCR Pipeline docs: Grid Editor v4.7.0 with zone merging, heading detection, IPA fixes Co-Authored-By: Claude Opus 4.6 --- .../services/klausur-service/OCR-Pipeline.md | 181 +++++++++++++++++- 1 file changed, 179 insertions(+), 2 deletions(-) diff --git a/docs-src/services/klausur-service/OCR-Pipeline.md b/docs-src/services/klausur-service/OCR-Pipeline.md index 0daf297..e84473b 100644 --- a/docs-src/services/klausur-service/OCR-Pipeline.md +++ b/docs-src/services/klausur-service/OCR-Pipeline.md @@ -1,7 +1,7 @@ # OCR Pipeline - Schrittweise Seitenrekonstruktion -**Version:** 4.3.0 -**Status:** Produktiv (Schritte 1–10 implementiert) +**Version:** 4.7.0 +**Status:** Produktiv (Schritte 1–10 + Grid Editor implementiert) **URL:** https://macmini:3002/ai/ocr-pipeline ## Uebersicht @@ -148,13 +148,18 @@ klausur-service/backend/ │ └── cv_vocab_pipeline.py # Computer Vision + NLP Algorithmen ├── ocr_pipeline_api.py # FastAPI Router (Schritte 2-10) ├── orientation_crop_api.py # FastAPI Router (Schritte 1 + 4) +├── grid_editor_api.py # Grid Editor: build-grid, save-grid, grid-editor +├── cv_ocr_engines.py # OCR-Engines, IPA-Korrektur, Britfone-Woerterbuch ├── cv_box_detect.py # Box-Erkennung + Zonen-Aufteilung ├── cv_graphic_detect.py # Grafik-/Bilderkennung (Region-basiert) ├── cv_color_detect.py # Farbtext-Erkennung (HSV-Analyse) ├── cv_words_first.py # Words-First Grid Builder (bottom-up) +├── cv_vocab_types.py # Datentypen: PageZone, ColumnGeometry, etc. ├── page_crop.py # Content-basierter Crop-Algorithmus ├── ocr_pipeline_session_store.py # PostgreSQL Persistence ├── layout_reconstruction_service.py # Fabric.js JSON + PDF/DOCX Export +├── tests/ +│ └── test_grid_editor_api.py # 27 Tests fuer Grid Editor + IPA └── migrations/ ├── 002_ocr_pipeline_sessions.sql # Basis-Schema ├── 003_add_row_result.sql # Row-Result Spalte @@ -311,6 +316,14 @@ Alle Endpoints unter `/api/v1/ocr-pipeline/`. | `POST` | `/sessions/{id}/reconstruction/validate` | Validierung speichern (Step 10) | | `GET` | `/sessions/{id}/reconstruction/validation` | Validierungsdaten abrufen | +### Grid Editor (Excel-aehnlich) + +| Methode | Pfad | Beschreibung | +|---------|------|--------------| +| `POST` | `/sessions/{id}/build-grid` | Strukturiertes Grid aus Kombi-Wortdaten erstellen | +| `POST` | `/sessions/{id}/save-grid` | Bearbeitetes Grid speichern | +| `GET` | `/sessions/{id}/grid-editor` | Grid-Editor-Daten abrufen | + --- ## Schritt 4: Zuschneiden/Crop (Detail) @@ -1057,6 +1070,169 @@ Body: {"cells": [{"cell_id": "r5_c2", "text": "corrected text"}]} --- +## Grid Editor (Detail) + +Der Grid Editor baut aus den Kombi-Wortdaten (PaddleOCR + Tesseract) ein strukturiertes, +Excel-aehnliches Grid mit Zonen, Spalten, Zeilen und Zellen. Er ersetzt die manuelle +Rekonstruktion fuer Vokabelseiten mit komplexen Layouts (Bilder, Ueberschriften, IPA-Lautschrift). + +**Dateien:** + +| Datei | Beschreibung | +|-------|--------------| +| `grid_editor_api.py` | `_build_grid_core()` Pipeline, alle Steps | +| `cv_ocr_engines.py` | IPA-Korrektur, Britfone-Woerterbuch, Garbled-IPA-Erkennung | +| `cv_vocab_types.py` | `PageZone` (mit `image_overlays`), `ColumnGeometry` | +| `tests/test_grid_editor_api.py` | 27 Tests | + +### `_build_grid_core()` Pipeline + +Die Grid-Erstellung laeuft in mehreren Steps: + +``` +Kombi-Wortdaten + │ + ├─ Zone Merging: Content-Zonen durch Bilder zusammenfuegen + │ → _merge_content_zones_across_boxes() + │ + ├─ Step 1: Zonen-Grid-Berechnung + │ → Spalten (Column Union), Zeilen, Zellen pro Zone + │ + ├─ Step 2: Header-Zeilen erkennen + mergen + │ + ├─ Step 3: Ghost-Filter + │ → _filter_border_ghosts(): Einzel-Char-Artefakte an Box-Raendern + │ + ├─ Step 4: Farb-Annotation + │ → detect_word_colors(): HSV-Farbanalyse aller word_boxes + │ + ├─ Step 4c: Oversized Word Box Removal + │ → word_boxes > 3x Median entfernen (Grafik-Artefakte) + │ + ├─ Step 5: Overlay-Wort-Filter + │ → Woerter innerhalb image_overlays entfernen + │ + ├─ Step 5a: Heading Detection by Color + Height + │ → _detect_heading_rows_by_color(): Farbige Ueberschriften erkennen + │ + ├─ Step 5b: Fix Unmatched Parentheses + │ + ├─ Step 5c: IPA Phonetic Correction + │ → fix_cell_phonetics(): Garbled OCR-IPA durch Britfone ersetzen + │ + └─ Step 5d: IPA Continuation Detection + → fix_ipa_continuation_cell(): Reine Klammer-Zellen als IPA-Fortsetzung +``` + +### Zone Merging Across Images + +`_merge_content_zones_across_boxes()` erkennt das Muster `[content, box, content]` und +fuegt die Content-Zonen zu einer einzigen Zone zusammen. Die Box-Zonen werden als +`image_overlays` auf der gemergten Zone gespeichert. + +``` +Vorher: Zone 1 (content) → Zone 2 (box/Bild) → Zone 3 (content) +Nachher: Zone 1 (content, mit image_overlays=[Zone 2]) +``` + +**PageZone.image_overlays:** + +```json +[{"y": 120, "height": 85, "x": 50, "width": 400, "box": {...}}] +``` + +Box-Zonen die NICHT zwischen Content-Zonen liegen (z.B. "VOCABULARY" Header-Box) +bleiben als eigenstaendige Zone erhalten. + +### Heading Detection by Color + Height + +`_detect_heading_rows_by_color()` erkennt farbige Zwischenueberschriften +(z.B. "Unit 4: Bonnie Scotland") nach der Farb-Annotation: + +1. **Farbkriterium:** ALLE word_boxes der Zeile haben `color_name != 'black'` (typisch: blau) +2. **Hoehenkriterium:** Mittlere Worthoehe > 1.2× Median aller Woerter in der Zone + +Erkannte Headings werden zu einer Spanning-Cell zusammengefuegt (`col_type: 'heading'`). + +### Ghost-Filter + +`_filter_border_ghosts()` entfernt einzelne Zeichen (a-z, A-Z, 0-9) die nahe an +Box-Raendern erkannt werden — typische OCR-Artefakte von Rahmenlinien. + +**Ausnahme:** Borderless Boxes (`border_thickness = 0`) ueberspringen den Ghost-Filter, +da dort keine Rahmen-Artefakte entstehen. + +### IPA Phonetic Correction (Step 5c) + +PaddleOCR erkennt IPA-Symbole als ASCII-Zeichen: + +| IPA-Symbol | OCR liest | +|------------|-----------| +| `ʒ` | `3` | +| `ʃ` | `f` | +| `ə` | `9` | +| `ˈ` | `'` | +| `ɪ` | `i` oder `1` | + +**`fix_cell_phonetics()`** ersetzt garbled OCR-IPA durch korrekte Lautschrift aus dem +Britfone-Woerterbuch (British English). Nur Zellen mit `col_type == 'column_en'` werden +verarbeitet. + +**`_text_has_garbled_ipa()`** erkennt garbled IPA anhand von: + +- Typischen OCR-IPA-Zeichen: `' 3 9 @ : ;` +- Bracket-Notation ohne echte IPA-Symbole: `[n, nn]`, `[1uedtX,1]` + +### IPA Continuation Detection (Step 5d) + +Vokabelseiten haben manchmal Zeilen, die nur Lautschrift enthalten (Fortsetzung +des Headwords der vorherigen Zeile). Diese werden von PaddleOCR als garbled Text erkannt. + +**`fix_ipa_continuation_cell()`:** + +1. Prueft ob die Zelle **komplett in Klammern** steht (`[...]`) — Zellen wie + "employee [im'ploi:]" werden NICHT ueberschrieben +2. Sucht das Headword in der Zeile darueber +3. Stripped Grammatik-Annotationen: `[sth.]`, `(adj.)` etc. +4. Schlaegt IPA im Britfone-Woerterbuch nach +5. Beruecksichtigt alle Wortteile (z.B. "close sth. down" → `[klˈəʊz dˈaʊn]`) + +### `en_col_type` Erkennung + +Die Erkennung der Englisch-Headword-Spalte nutzt **Bracket-IPA-Pattern-Count** +statt "laengster Durchschnittstext": + +1. Fuer jede `column_*`-Spalte: Zaehle Zellen mit `[` im Text +2. Spalte mit den meisten Klammer-Mustern = `en_col_type` +3. **Fallback:** Laengster Durchschnittstext (wenn keine Klammern vorhanden) + +Dies verhindert, dass Beispielsatz-Spalten (laenger aber ohne IPA) faelschlicherweise +als Headword-Spalte erkannt werden. + +### Oversized Word Box Removal (Step 4c) + +Entfernt `word_boxes` deren Flaeche > 3× der Median-Flaeche aller Woerter in der Zone. +Diese sind typischerweise Grafik-Artefakte (z.B. ein einzelnes "N" das eine ganze +Illustration abdeckt). + +### Tests + +```bash +cd klausur-service/backend && pytest tests/test_grid_editor_api.py -v # 27 Tests +``` + +| Klasse | Tests | Beschreibung | +|--------|-------|--------------| +| `TestZoneMerging` | 4 | Content-Zone-Merging ueber Box-Zonen | +| `TestHeadingDetection` | 3 | Farb- + Hoehenbasierte Heading-Erkennung | +| `TestGhostFilter` | 4 | Border-Ghost-Filterung inkl. Borderless | +| `TestOversizedWordBoxes` | 2 | Grafik-Artefakt-Entfernung | +| `TestGarbledIpaDetection` | 8 | Bracket-IPA, Continuation, en_col_type | +| `TestColumnUnion` | 3 | Spalten-Vereinigung ueber Zonen | +| `TestHeaderMerging` | 3 | Header-Zeilen zusammenfuegen | + +--- + ## Wichtige Konstanten | Konstante | Wert | Datei | Beschreibung | @@ -1360,6 +1536,7 @@ cd klausur-service/backend && pytest tests/test_paddle_kombi.py -v # 36 Tests | Datum | Version | Aenderung | |-------|---------|----------| +| 2026-03-20 | 4.7.0 | Grid Editor: Zone Merging ueber Bilder (`image_overlays`), Heading Detection (Farbe + Hoehe), Ghost-Filter (borderless-aware), Oversized Word Box Removal, IPA Phonetic Correction (Britfone), IPA Continuation Detection, `en_col_type` via Bracket-Count. 27 Tests. | | 2026-03-16 | 4.6.0 | Strukturerkennung (Schritt 8): Region-basierte Grafikerkennung (`cv_graphic_detect.py`) mit Zwei-Pass-Verfahren (Farbregionen + schwarze Illustrationen), Wort-Ueberlappungs-Filter, Box/Zonen/Farb-Analyse. Schritt laeuft nach Worterkennung. | | 2026-03-12 | 4.5.0 | Kombi-Modus (PaddleOCR + Tesseract): Beide Engines laufen parallel, Koordinaten werden IoU-basiert gematcht und confidence-gewichtet gemittelt. Ungematchte Tesseract-Woerter (Bullets, Symbole) werden hinzugefuegt. 3er-Toggle in OCR Overlay. | | 2026-03-12 | 4.4.0 | PaddleOCR Remote-Engine (`engine=paddle`): PP-OCRv5 Latin auf Hetzner x86_64. Neuer Microservice (`paddleocr-service/`), HTTP-Client (`paddleocr_remote.py`), Frontend-Dropdown-Option. Nutzt words_first Grid-Methode. |