Commit Graph

103 Commits

Author SHA1 Message Date
Benjamin Admin
dfce8415d7 fix: show per-word colors in grid table instead of whole-cell coloring
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 38s
CI / test-go-edu-search (push) Successful in 27s
CI / test-python-klausur (push) Failing after 2m1s
CI / test-python-agent-core (push) Successful in 16s
CI / test-nodejs-website (push) Successful in 19s
When a cell has colored words (red !, blue phonetics), render each
word as a separate span with its own color instead of coloring the
entire input text with the first non-black color found.

Switches to editable input on cell selection (click).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 08:55:43 +01:00
Benjamin Admin
729ebff63c feat: add border ghost filter + graphic detection tests + structure overlay
- Add _filter_border_ghost_words() to remove OCR artefacts from box borders
  (vertical + horizontal edge detection, column cleanup, re-indexing)
- Add 20 tests for border ghost filter (basic filtering + column cleanup)
- Add 24 tests for cv_graphic_detect (color detection, word overlap, boxes)
- Clean up cv_graphic_detect.py logging (per-candidate → DEBUG)
- Add structure overlay layer to StepReconstruction (boxes + graphics toggle)
- Show border_ghosts_removed badge in StepStructureDetection
- Update MkDocs with structure detection documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 18:28:53 +01:00
Benjamin Admin
6b9b280ba3 feat: integrate graphic element detection into structure step
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 28s
CI / test-go-edu-search (push) Successful in 28s
CI / test-python-klausur (push) Failing after 1m58s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 19s
Add cv_graphic_detect.py for detecting non-text visual elements (arrows,
circles, lines, exclamation marks, icons, illustrations). Draw detected
graphics on structure overlay image and display them in the frontend
StepStructureDetection component with shape counts and individual listings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 13:21:55 +01:00
Benjamin Admin
5b5213c2b9 feat: add Structure Detection step to OCR pipeline
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 27s
CI / test-go-edu-search (push) Successful in 28s
CI / test-python-klausur (push) Failing after 1m58s
CI / test-python-agent-core (push) Successful in 17s
CI / test-nodejs-website (push) Successful in 16s
New pipeline step between Crop and Columns that visualizes detected
document structure: boxes (line-based + shading), page zones, and
color regions. Shows original image on the left, annotated overlay
on the right.

Backend: POST /detect-structure endpoint + /image/structure-overlay
Frontend: StepStructureDetection component with zone/box/color details

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 12:31:09 +01:00
Benjamin Admin
4a8d43fd71 feat: display detected text colors in grid editor UI
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 32s
CI / test-go-edu-search (push) Successful in 26s
CI / test-python-klausur (push) Failing after 2m8s
CI / test-python-agent-core (push) Successful in 16s
CI / test-nodejs-website (push) Successful in 18s
- Add color/color_name/recovered fields to OcrWordBox type
- GridTable: show colored text + left-edge color indicator strip
- GridEditor: show color stats and recovered count in summary bar

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 01:03:09 +01:00
Benjamin Admin
c3f1547e32 feat: add Excel-like grid editor for OCR overlay (Kombi mode step 6)
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 27s
CI / test-go-edu-search (push) Successful in 28s
CI / test-python-klausur (push) Failing after 2m1s
CI / test-python-agent-core (push) Successful in 17s
CI / test-nodejs-website (push) Successful in 17s
Backend: new grid_editor_api.py with build-grid endpoint that detects
bordered boxes, splits page into zones, clusters columns/rows per zone
from Kombi word positions. New DB column grid_editor_result JSONB.

Frontend: GridEditor component with editable HTML tables per zone,
column bold toggle, header row toggle, undo/redo, keyboard navigation
(Tab/Enter/Arrow), image overlay verification, and save/load.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 23:41:03 +01:00
Benjamin Admin
4a15d46dfd refactor: rename PaddleOCR → PP-OCRv5 in frontend, remove Kombi-Vergleich tab
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 27s
CI / test-go-edu-search (push) Successful in 26s
CI / test-python-klausur (push) Failing after 1m53s
CI / test-python-agent-core (push) Successful in 16s
CI / test-nodejs-website (push) Successful in 16s
Since ocr_region_paddle() now runs RapidOCR locally (same PP-OCRv5 models),
the "PaddleOCR (Hetzner)" labels were misleading. Renamed to "PP-OCRv5 (lokal)".
Removed the Kombi-Vergleich tab since both sides would produce identical results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 09:11:26 +01:00
Benjamin Admin
a994ddee83 feat: add Kombi-Vergleich mode for side-by-side Paddle vs RapidOCR comparison
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 33s
CI / test-go-edu-search (push) Successful in 26s
CI / test-python-klausur (push) Failing after 1m55s
CI / test-python-agent-core (push) Successful in 17s
CI / test-nodejs-website (push) Successful in 21s
Add /rapid-kombi backend endpoint using local RapidOCR + Tesseract merge,
KombiCompareStep component for parallel execution and side-by-side overlay,
and wordResultOverride prop on OverlayReconstruction for direct data injection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 07:59:06 +01:00
Benjamin Admin
c2c082d4b4 docs+tests: update OCR Pipeline docs and add overlay position tests
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 27s
CI / test-go-edu-search (push) Successful in 28s
CI / test-python-klausur (push) Failing after 2m5s
CI / test-python-agent-core (push) Successful in 16s
CI / test-nodejs-website (push) Successful in 17s
MkDocs: document row-based merge algorithm, spatial overlap dedup,
and per-word yPct/hPct rendering in OCR Pipeline docs.

Tests: add 9 vitest tests for useSlideWordPositions covering
word-box path, fallback path, and yPct/hPct contract.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:03:00 +01:00
Benjamin Admin
d6f51e4418 fix: deduplicate overlapping OCR words and use per-word Y positions in overlay
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 33s
CI / test-python-klausur (push) Failing after 2m9s
CI / test-python-agent-core (push) Successful in 19s
CI / test-nodejs-website (push) Successful in 24s
Backend: Add spatial overlap check (>=50% horizontal IoU) to Kombi merge
so words at the same position are deduplicated even when OCR text differs.

Frontend: Add yPct/hPct to WordPosition so each word renders at its actual
vertical position instead of all words collapsing to the cell center Y.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 20:27:08 +01:00
Benjamin Admin
e9ccd1e35c feat: add Kombi-Modus (PaddleOCR + Tesseract) for OCR Overlay
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 35s
CI / test-go-edu-search (push) Successful in 33s
CI / test-python-klausur (push) Failing after 2m20s
CI / test-python-agent-core (push) Successful in 22s
CI / test-nodejs-website (push) Successful in 41s
Runs both OCR engines on the preprocessed image and merges results:
word boxes matched by IoU, coordinates averaged by confidence weight.
Unmatched Tesseract words (bullets, symbols) are added for better coverage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 20:05:50 +01:00
Benjamin Admin
d335a7bbf3 fix: use OCR word_box coordinates directly instead of fuzzy matching
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 2m6s
CI / test-python-agent-core (push) Successful in 19s
CI / test-nodejs-website (push) Successful in 25s
The slide positioning hook was re-matching cell.text tokens against
word_boxes via fuzzy text similarity, which broke positioning for
special characters (!, bullet points, IPA). Now uses word_box
coordinates directly — exact OCR positions without re-interpretation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:54:37 +01:00
Benjamin Admin
90c1efd9b0 feat: Paddle Direct — 1-click OCR without deskew/dewarp/crop
Some checks failed
CI / go-lint (push) Has been cancelled
CI / python-lint (push) Has been cancelled
CI / nodejs-lint (push) Has been cancelled
CI / test-go-school (push) Has been cancelled
CI / test-go-edu-search (push) Has been cancelled
CI / test-python-klausur (push) Has been cancelled
CI / test-python-agent-core (push) Has been cancelled
CI / test-nodejs-website (push) Has been cancelled
New 2-step mode (Upload → PaddleOCR+Overlay) alongside the existing
7-step pipeline. Backend endpoint runs PaddleOCR on the original image
and clusters words into rows/cells directly. Frontend adds a mode
toggle and PaddleDirectStep component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 16:41:55 +01:00
Benjamin Admin
06d63d18f9 fix: generic fuzzy text matching for overlay word-box positioning
Some checks failed
CI / test-go-edu-search (push) Has been cancelled
CI / go-lint (push) Has been cancelled
CI / python-lint (push) Has been cancelled
CI / nodejs-lint (push) Has been cancelled
CI / test-go-school (push) Has been cancelled
CI / test-python-klausur (push) Has been cancelled
CI / test-python-agent-core (push) Has been cancelled
CI / test-nodejs-website (push) Has been cancelled
Replace sequential 1:1 token-to-box mapping with fuzzy text matching.
Each token from cell.text finds its best matching word_box by text
similarity (normalized prefix match + substring bonus). Handles:
- Reordered boxes (different sort between text and boxes)
- IPA corrections changing token boundaries
- Token/box count mismatches
Unmatched tokens get interpolated positions from matched neighbors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 16:19:19 +01:00
Benjamin Admin
bb90d1ba94 fix: PaddleOCR engine forces words_first in frontend to match backend
Some checks failed
CI / go-lint (push) Has been cancelled
CI / python-lint (push) Has been cancelled
CI / nodejs-lint (push) Has been cancelled
CI / test-go-school (push) Has been cancelled
CI / test-go-edu-search (push) Has been cancelled
CI / test-python-klausur (push) Has been cancelled
CI / test-python-agent-core (push) Has been cancelled
CI / test-nodejs-website (push) Has been cancelled
When engine=paddle is selected, the backend overrides grid_method to
words_first and returns plain JSON (no SSE streaming). The frontend
was not aware of this override — it sent stream=true and tried to parse
SSE events from a JSON response, resulting in "Keine Daten".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 14:52:18 +01:00
Benjamin Admin
a6069631cc feat: PaddleOCR Remote-Engine (PP-OCRv5 Latin auf Hetzner x86_64)
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 31s
CI / test-go-edu-search (push) Successful in 29s
CI / test-python-klausur (push) Failing after 2m7s
CI / test-python-agent-core (push) Successful in 21s
CI / test-nodejs-website (push) Successful in 21s
PaddleOCR als neue engine=paddle Option in der OCR-Pipeline.
Microservice auf Hetzner (paddleocr-service/), async HTTP-Client
(paddleocr_remote.py), Frontend-Dropdown, automatisch words_first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:31:22 +01:00
Benjamin Admin
ced5bb3dd3 feat: Words-First Grid Builder (bottom-up alternative zu cell_grid_v2)
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 54s
CI / test-go-edu-search (push) Successful in 47s
CI / test-python-klausur (push) Failing after 2m31s
CI / test-python-agent-core (push) Successful in 23s
CI / test-nodejs-website (push) Successful in 32s
Neuer Algorithmus in cv_words_first.py: Clustert Tesseract word_boxes
direkt zu Spalten (X-Gap) und Zeilen (Y-Proximity), baut Zellen an
Schnittpunkten. Kein Spalten-/Zeilenerkennung noetig.

- cv_words_first.py: _cluster_columns, _cluster_rows, _build_cells, build_grid_from_words
- ocr_pipeline_api.py: grid_method Parameter (v2|words_first) im /words Endpoint
- StepWordRecognition.tsx: Dropdown Toggle fuer Grid-Methode
- OCR-Pipeline.md: Doku v4.3.0 mit Words-First Algorithmus
- 15 Unit-Tests fuer cv_words_first

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 06:46:05 +01:00
Benjamin Admin
35f2706098 fix: Slide-Modus nutzt cell.text Tokens statt word_boxes Text (keine Woerter verloren)
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 27s
CI / test-go-edu-search (push) Successful in 29s
CI / test-python-klausur (push) Failing after 2m8s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 22s
TEXT kommt aus cell.text (bereinigt, IPA-korrigiert).
POSITIONEN kommen aus word_boxes (exakte OCR-Koordinaten).
Tokens werden 1:1 in Leserichtung zugeordnet.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:01:57 +01:00
Benjamin Admin
0ee92e7210 feat: OCR word_boxes fuer pixelgenaue Overlay-Positionierung
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 37s
CI / test-go-edu-search (push) Successful in 32s
CI / test-python-klausur (push) Failing after 2m10s
CI / test-python-agent-core (push) Successful in 19s
CI / test-nodejs-website (push) Successful in 20s
Backend: _ocr_cell_crop speichert jetzt word_boxes mit exakten
Tesseract/RapidOCR Wort-Koordinaten (left, top, width, height)
im Cell-Ergebnis. Absolute Bildkoordinaten, bereits zurueckgemappt.

Frontend: Slide-Hook nutzt word_boxes direkt wenn vorhanden —
jedes Wort wird exakt an seiner OCR-Position platziert. Kein
Pixel-Scanning noetig. Fallback auf alten Slide wenn keine Boxes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:39:49 +01:00
Benjamin Admin
4949863bd7 revert: Zurueck zum Einzelwort-Slide mit fontRatio=1.0 Fix
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 31s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 2m5s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 19s
Gruppen-Sliding schob nicht weit genug nach rechts. Zurueck zum
Original-Einzelwort-Slide, aber mit den Fixes:
- fontRatio=1.0 (konsistente Schriftgroesse wie Fallback)
- Token-Breiten aus medianCh * 0.7 / refFontSize (statt totalInk)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:15:52 +01:00
Benjamin Admin
efbe15f895 fix: Slide-Modus auf Gruppen-basiertes Sliding umgestellt
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 28s
CI / test-python-klausur (push) Failing after 2m0s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 23s
Vorher: split(/\s+/) zerlegte alles in Einzelwoerter, verlor die
Spaltenstruktur (3+ Spaces zwischen Gruppen). Woerter stauten sich links.

Jetzt: split(/\s{3,}/) erhält Gruppen wie im Cluster-Modus. Jede Gruppe
wird als Einheit von links nach rechts geschoben bis Tinte gefunden.
Breite = max(gemessene Textbreite, tatsaechliche Tintenbreite).
fontRatio=1.0, kein Wort geht verloren.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:31:17 +01:00
Benjamin Admin
c3da131129 fix: Slide fontRatio=1.0 und Token-Breite aus gerenderter Fontgroesse
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 31s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 2m3s
CI / test-python-agent-core (push) Successful in 17s
CI / test-nodejs-website (push) Successful in 18s
fontRatio war 0.65 (35% kleiner als Fallback-Rendering). Jetzt 1.0
wie beim Fallback. Token-Breiten berechnet aus measureText skaliert
auf die tatsaechlich gerenderte Schriftgroesse (medianCh * 0.7).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:59:31 +01:00
Benjamin Admin
b81baa1d16 fix: Slide-Modus globale Schriftgroesse statt per-Token Scale
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 31s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 2m3s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 25s
Schriftgroesse wird jetzt GLOBAL aus der medianen Zellhoehe berechnet
(65% der Zellhoehe als Ziel-Font). Alle Tokens bekommen dieselbe
konsistente Groesse. Die Slide-Logik bestimmt nur noch die x-Position.

Vorher: Scale pro Zelle aus Ink-Span/Textbreite -> inkonsistente Groessen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:51:55 +01:00
Benjamin Admin
2010cab894 fix: Slide-Modus Scale-Berechnung auf Ink-Span statt Ink-Count
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 36s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m11s
CI / test-python-agent-core (push) Successful in 24s
CI / test-nodejs-website (push) Successful in 31s
totalInk zaehlte nur dunkle Pixel-Spalten (Striche), ignorierte
Luecken zwischen Buchstaben. Scale war dadurch viel zu klein,
Schrift unlesbar. Jetzt wird der Ink-Span (erstes bis letztes
dunkles Pixel) als Referenz fuer die Textbreite verwendet.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:41:38 +01:00
Benjamin Admin
bc13978bc1 feat: Slide-Modus als alternative Wort-Positionierung im Overlay
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 34s
CI / test-go-edu-search (push) Successful in 33s
CI / test-python-klausur (push) Failing after 2m9s
CI / test-python-agent-core (push) Successful in 23s
CI / test-nodejs-website (push) Successful in 24s
Neuer Hook useSlideWordPositions: Schiebt alle erkannten Woerter von links
nach rechts ueber die Pixel-Projektion bis jedes Wort auf seiner Tinte
einrastet. Kein Wort geht verloren, keine Cluster-Matching-Regeln noetig.

Toggle-Button (Slide/Cluster) in der Overlay-Toolbar zum Umschalten.
Bestehender Cluster-Algorithmus bleibt als Alternative erhalten.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:13:31 +01:00
Benjamin Admin
8a5f2aa188 fix: Cluster-Zuordnung per Breiten-Proportionalitaet statt Position
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 36s
CI / test-go-edu-search (push) Successful in 36s
CI / test-python-klausur (push) Failing after 2m20s
CI / test-python-agent-core (push) Successful in 21s
CI / test-nodejs-website (push) Successful in 29s
Zwei wesentliche Verbesserungen:

1. Multi-group: Gruppen werden per Best-Fit-Breite den Clustern
   zugeordnet statt naiv links-nach-rechts. Damit wird z.B.
   "Kokosnuss" dem DE-Spalten-Cluster zugeordnet statt dem
   breiteren Box-Cluster.

2. Single-group Fallback: verwendet den BREITESTEN Cluster statt
   first-to-last Span. Verhindert dass Streupixel von benachbarten
   Seitenbereichen den Text nach links ziehen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 15:39:54 +01:00
Benjamin Admin
d182d87f26 fix: OCR-Artefakte (|, >) vor Cluster-Matching zusammenfuehren
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 34s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m23s
CI / test-python-agent-core (push) Successful in 22s
CI / test-nodejs-website (push) Successful in 22s
Box-Rahmen werden vom OCR als einzelne Symbole wie "|" oder ">"
erkannt und als eigene Text-Gruppen behandelt. Das verfaelscht die
Cluster-Zuordnung weil diese Artefakte entweder keinen eigenen
Cluster erzeugen oder den falschen Cluster zugewiesen bekommen.

Fix: Gruppen mit max 2 Zeichen ohne Buchstaben/Ziffern werden mit
der benachbarten Gruppe zusammengefuehrt bevor die Cluster-Zuordnung
laeuft.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 15:03:37 +01:00
Benjamin Admin
87efc1b4ba fix: bei Cluster-Ueberschuss die breitesten N Cluster waehlen
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 2m5s
CI / test-python-agent-core (push) Successful in 22s
CI / test-nodejs-website (push) Successful in 20s
Wenn mehr Pixel-Cluster als Text-Gruppen existieren (z.B. wegen
Box-Rahmenlinien), werden jetzt die N breitesten Cluster ausgewaehlt
statt naiv clusters[i]→groups[i] zuzuordnen. Text-Cluster sind
breiter als Rahmenlinien-Cluster.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:34:58 +01:00
Benjamin Admin
dd7087cd6d fix: Pixel-Analyse nicht mehr ueberspringen wenn Cluster < Gruppen
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 31s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m1s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 20s
Vorher: wenn Text mehr Wort-Gruppen hatte als Pixel-Cluster gefunden
wurden (z.B. bei Box-Rahmen die Cluster zusammenmergen), wurde die
Zelle komplett uebersprungen → Fallback bei x=0%.

Jetzt: Fallback auf Single-Span Positionierung (first→last Cluster)
statt Skip. Damit wird der Text immer korrekt horizontal platziert.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:14:58 +01:00
Benjamin Admin
7282a220d6 fix: useMemo vor Early Returns verschieben (Rules of Hooks)
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 31s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m0s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 28s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 09:46:25 +01:00
Benjamin Admin
b5d5371f72 fix: einheitliche Schriftgroesse + Border-Cluster-Filter im Overlay
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 35s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m24s
CI / test-python-agent-core (push) Successful in 25s
CI / test-nodejs-website (push) Successful in 25s
1. Schriftgroesse basiert jetzt auf Median-Zeilenhoehe statt
   individueller Zellhoehe — keine Groessensprunge in Box-Bereichen
2. Sehr schmale Pixel-Cluster (< 0.5% Zellbreite) werden gefiltert,
   damit Box-Rahmen nicht als Textposition erkannt werden

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 09:34:41 +01:00
Benjamin Admin
8a60f4bf30 fix: Overlay-Zellen ohne _heal_row_gaps positionieren (skip_heal_gaps)
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 36s
CI / test-go-edu-search (push) Successful in 35s
CI / test-python-klausur (push) Failing after 2m12s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 21s
_heal_row_gaps verschiebt Zell-Positionen nach Entfernung von Artefakt-Zeilen,
was im Overlay zu sichtbarem Versatz fuehrt (z.B. 23px bei "badge").
Neuer skip_heal_gaps Parameter in build_cell_grid_v2 und words-Endpoint
behaelt die exakten Zeilen-Positionen bei.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 08:59:50 +01:00
Benjamin Admin
e3ee1de790 Revert "fix: Zeilen-Regularisierung im Overlay ueberspringen (generisch fuer gemischte Inhalte)"
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 29s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m2s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 24s
This reverts commit b91f799ccf.
2026-03-11 08:44:07 +01:00
Benjamin Admin
b91f799ccf fix: Zeilen-Regularisierung im Overlay ueberspringen (generisch fuer gemischte Inhalte)
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 49s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m21s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 26s
Seiten mit Info-Boxen (andere Zeilenhoehe) fuehren dazu, dass _regularize_row_grid
die Zeilenpositionen verzerrt. Neuer skip_regularize Parameter nutzt stattdessen
die gap-basierten Zeilen, die der tatsaechlichen Seitengeometrie folgen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 08:29:06 +01:00
Benjamin Admin
2df2a01a8b feat: Echtes Overlay — Text direkt ueber dem Originalbild
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 33s
CI / test-go-edu-search (push) Successful in 36s
CI / test-python-klausur (push) Failing after 2m11s
CI / test-python-agent-core (push) Successful in 25s
CI / test-nodejs-website (push) Successful in 26s
Statt Side-by-Side wird der erkannte Text jetzt direkt ueber das
Originalbild gelegt. Textfarbe (rot/blau/schwarz) und Deckkraft
per Slider einstellbar fuer einfache visuelle Fehlersuche.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:25:11 +01:00
Benjamin Admin
2cbdfc56f3 feat: OCR Overlay — ganzseitige Rekonstruktion ohne Spaltenerkennung
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 31s
CI / test-go-edu-search (push) Successful in 33s
CI / test-python-klausur (push) Failing after 2m6s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 28s
Neue Route /ai/ocr-overlay mit vereinfachter 7-Schritt-Pipeline
(Orientierung, Begradigung, Entzerrung, Zuschnitt, Zeilen, Woerter, Overlay).
Nutzt bestehende Step-Komponenten, ueberspringt Spalten/LLM-Review/Ground-Truth.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:08:05 +01:00
Benjamin Admin
840918df2a fix: Originalbild im Overlay nicht extra drehen (Orientierung bereits im Cropped-Bild)
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 34s
CI / test-go-edu-search (push) Successful in 33s
CI / test-python-klausur (push) Failing after 2m15s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 22s
Das cropped image ist bereits orientierungskorrigiert. Die zusaetzliche
180°-Rotation ueber imageRotation drehte das Bild falsch herum.
imageRotation wird weiter fuer Pixel-Matching genutzt, aber nicht mehr
fuer die Bildanzeige.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:25:20 +01:00
Benjamin Admin
eb3fc05cdc fix: Box-Zone Clamping nach Box-Mitte statt Cell-Center entscheiden
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 31s
CI / test-go-edu-search (push) Successful in 34s
CI / test-python-klausur (push) Failing after 2m8s
CI / test-python-agent-core (push) Successful in 19s
CI / test-nodejs-website (push) Successful in 21s
Euro/Badge-Zeilen hatten ihren Center innerhalb der Box-Zone, weshalb
das Clamping nicht griff. Jetzt wird anhand der Box-Mitte entschieden
ob eine Zelle nach oben (clamp height) oder unten (push y) gehoert.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:10:51 +01:00
Benjamin Admin
9dbb5fa708 fix: useMemo vor Early Returns verschieben (Rules of Hooks)
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 28s
CI / test-python-klausur (push) Failing after 2m10s
CI / test-python-agent-core (push) Successful in 22s
CI / test-nodejs-website (push) Successful in 25s
boxZonesPct useMemo war nach bedingten Returns platziert, was gegen
Reacts Rules of Hooks verstoesst und einen Client-Side Crash ausloest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 22:57:25 +01:00
Benjamin Admin
f468c30112 fix: Zellen an Box-Zone clampen im Overlay-Modus (keine Ueberlappung)
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 29s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 2m15s
CI / test-python-agent-core (push) Successful in 17s
CI / test-nodejs-website (push) Successful in 23s
Zellen oberhalb der Box werden in der Hoehe begrenzt, Zellen unterhalb
werden nach unten verschoben. Sub-Session-Zellen bleiben unveraendert.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 22:52:08 +01:00
Benjamin Admin
080fcb5e3c feat: 180°-Rotation fuer Pixel-Matching im Overlay-Modus
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 35s
CI / test-go-edu-search (push) Successful in 29s
CI / test-python-klausur (push) Failing after 2m15s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 23s
- usePixelWordPositions: neuer rotation-Parameter (0 | 180)
- Bei 180°: Bild auf Canvas rotiert, Zell-Koordinaten transformiert,
  Cluster-Positionen zurueck-gespiegelt
- StepReconstruction: 180°-Toggle-Button in Overlay-Toolbar
- Default 180° bei Parent-Sessions mit Boxen
- Linkes Originalbild wird ebenfalls CSS-rotiert

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 17:19:14 +01:00
Benjamin Admin
bcd97e7d78 feat: Overlay-Modus fuer ganzseitige Tabellenrekonstruktion mit Pixel-Positionierung
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 34s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m9s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 24s
- usePixelWordPositions Hook extrahiert (shared zwischen StepLlmReview und StepReconstruction)
- StepReconstruction: neuer Overlay-Modus mit 50/50 Layout (Original + Rekonstruktion)
- Sub-Session-Zellen werden in Parent-Koordinaten konvertiert und zusammengefuehrt
- Spalten-/Zeilenlinien und Box-Zone-Markierung aus column_result/row_result
- Schriftgroesse-Slider und Bold-Toggle fuer Overlay
- StepLlmReview: ~140 Zeilen Pixel-Analyse durch Hook ersetzt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 16:18:47 +01:00
Benjamin Admin
7f8615b8c1 fix: Schriftgroesse auf haeufigsten Wert (Mode) normalisieren
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 32s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 2m26s
CI / test-python-agent-core (push) Successful in 19s
CI / test-nodejs-website (push) Successful in 23s
Alle Wortgruppen bekommen die gleiche fontRatio (gerundet auf 0.02),
basierend auf der haeufigsten berechneten Groesse. Ueberschriften
und Fliesstext haben damit einheitliche Schriftgroesse.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:28:23 +01:00
Benjamin Admin
2055597ba4 fix: Pixel-Overlay fuer alle Zellen + Auto-Schriftgroesse + kein contentEditable
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 31s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m4s
CI / test-python-agent-core (push) Successful in 19s
CI / test-nodejs-website (push) Successful in 27s
- Auch Single-Group-Zellen (z.B. Ueberschriften) per Pixel positionieren
- Auto font-size per canvas measureText (Text fuellt Cluster-Breite aus)
- contentEditable entfernt (pointer-events-none), Tabelle zum Editieren
- overflow:visible statt hidden verhindert Klick-Shift-Bug

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:25:16 +01:00
Benjamin Admin
ad28f9420a feat: Pixel-basierte Wortpositionierung im Overlay
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 28s
CI / test-go-edu-search (push) Successful in 28s
CI / test-python-klausur (push) Failing after 2m6s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 20s
Analysiert Schwarzpixel-Verteilung auf dem Originalbild per Canvas.
Findet Wort-Cluster pro Zeile und positioniert erkannte Textgruppen
an den exakten Pixel-Positionen. Monospace-Font zurueck auf Sans-Serif.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:36:57 +01:00
Benjamin Admin
6314e60464 fix: Monospace-Schrift im Overlay fuer korrekte Leerzeichen-Ausrichtung
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 31s
CI / test-go-edu-search (push) Successful in 28s
CI / test-python-klausur (push) Failing after 2m7s
CI / test-python-agent-core (push) Successful in 22s
CI / test-nodejs-website (push) Successful in 22s
column_text Zellen enthalten proportionale Leerzeichen zur Ausrichtung.
Mit Monospace-Font stehen Waehrungswerte korrekt untereinander.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:50:53 +01:00
Benjamin Admin
d530738b12 fix: useMemo vor early returns verschieben (React Hooks Regel)
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 28s
CI / test-go-edu-search (push) Successful in 30s
CI / test-python-klausur (push) Failing after 2m4s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 21s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:35:59 +01:00
Benjamin Admin
ca7d44e543 fix: Overlay spaltenweise Ausrichtung per Median-Snap
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 33s
CI / test-go-edu-search (push) Successful in 33s
CI / test-python-klausur (push) Failing after 2m7s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 22s
Alle Zellen einer Spalte bekommen die gleiche x-Position (Median)
damit Werte vertikal korrekt untereinander stehen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:20:06 +01:00
Benjamin Admin
e44e319ccf feat: Text-Overlay Rekonstruktion in StepLlmReview
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 33s
CI / test-python-klausur (push) Failing after 2m13s
CI / test-python-agent-core (push) Successful in 22s
CI / test-nodejs-website (push) Successful in 24s
Neuer Overlay-Modus zeigt OCR-Text per bbox_pct ueber weissem
Hintergrund neben dem Originalbild. Steuerelemente fuer Schriftgroesse,
Einrueckung und Bold. Inline-Editing per contentEditable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:07:11 +01:00
Benjamin Admin
13553fc5e6 fix: column_text Typ fuer Sub-Sessions in Korrektur-Tabelle
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 29s
CI / test-go-edu-search (push) Successful in 28s
CI / test-python-klausur (push) Failing after 2m9s
CI / test-python-agent-core (push) Successful in 19s
CI / test-nodejs-website (push) Successful in 20s
_cells_to_vocab_entries kannte column_text nicht, daher wurden
keine Eintraege erzeugt. Jetzt mappt column_text -> 'text' Feld.

Frontend: column_text in FIELD_LABELS/COL_TYPE_TO_FIELD/COL_TYPE_COLOR.
Label: "Tabelle" statt "Vokabeltabelle" fuer Sub-Sessions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 09:48:40 +01:00