Users can now draw rectangles on the document image in the Structure
Detection step to mark areas (e.g. header graphics, alphabet strips)
that should be excluded from OCR results during grid building.
- Backend: PUT/DELETE endpoints for exclude regions stored in structure_result
- Backend: _build_grid_core() filters all words inside user-defined exclude regions
- Frontend: Interactive rectangle drawing with visual overlay and delete buttons
- Preserve exclude regions when re-running structure detection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Ground Truth button on last step of Pipeline/Kombi modes in ocr-overlay
- Prominent category picker in active session info bar (pulses when unset)
- GT badge shown when session has ground truth reference
- Backend: auto-detect pipeline from ocr_engine, store in GT snapshot
- Pipeline info shown in GT session list and regression reports
- Also pass pipeline param from ocr-pipeline StepGroundTruth
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract _build_grid_core() from build_grid() endpoint for reuse.
New ocr_pipeline_regression.py with endpoints to mark sessions as
ground truth, list them, and run regression comparisons after code
changes. Frontend button in StepGroundTruth.tsx to mark/update GT.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The frontend was checking for an existing structure_result and reusing
it, which meant the backend fix (passing word_boxes to graphic detection)
never had a chance to run on existing sessions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: merge gaps within 5% of image width — the spine area may have
thin ink strips splitting one physical gap into multiple detected gaps.
Only use gaps >= 2% width as split points.
Frontend: StepCrop now handles multi_page crop responses without
crashing on missing original_size/cropped_size fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
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>
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>
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>
_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>
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>
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>
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>
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>
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>
- 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>
- 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>
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>
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>
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>
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>
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>
_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>
Sub-Sessions ueberspringen Spaltenerkennung und nutzen stattdessen eine
Pseudo-Spalte ueber die volle Breite. Text wird mit proportionalem
Spacing aus Wort-Positionen rekonstruiert, um raeumliches Layout zu erhalten.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Spalten-, Zeilen-, Woerter-Overlay und alle nachfolgenden Steps
(LLM-Review, Rekonstruktion) lesen jetzt image/cropped mit Fallback
auf image/dewarped. Tests fuer page_crop.py hinzugefuegt (25 Tests).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
detect_and_fix_orientation() wird jetzt vor dem Deskew-Schritt in der
OCR-Pipeline ausgefuehrt, sodass 90/180/270°-gedrehte Scans automatisch
korrigiert werden. Frontend zeigt Orientierungskorrektur als Info-Banner.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The side-by-side panels used calc(100vh - 380px) pushing the Speichern/
Abschliessen buttons below the viewport. Reduced to calc(100vh - 580px)
and made the action bar sticky at the bottom.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bold detection:
- Replace absolute threshold with page-level relative comparison
- Measure stroke width for all cells, then mark cells >1.4× median as bold
- Adapts automatically to font, DPI and scan quality
Save buttons:
- Fix status stuck on 'error' preventing re-click
- Better error messages with response body
- Fallback score to 0 when null
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add umlaut confusion rules (i→ü, a→ä, o→ö, u→ü) to _spell_fix_token
for German text — fixes "iberqueren" → "überqueren" etc.
- Add _detect_bold() using OpenCV stroke-width analysis on cell crops
- Integrate bold detection in both narrow (cell-crop) and broad (word-lookup) paths
- Add is_bold field to GridCell TypeScript interface
- Render bold text in StepGroundTruth reconstruction view
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Prepend /klausur-api prefix to original image URL (nginx proxy)
- Remove colored column background stripes, use white background
- Change cell text color to black instead of per-column-type colors
- Calculate font size dynamically from cell bbox height via ResizeObserver
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the stub StepGroundTruth with a full side-by-side Original vs
Reconstruction view. Adds VLM-based image region detection (qwen2.5vl),
mflux image generation proxy, sync scroll/zoom, manual region drawing,
and score/notes persistence.
New backend endpoints: detect-images, generate-image, validate, get validation.
New standalone mflux-service (scripts/mflux-service.py) for Metal GPU generation.
Dockerfile.base: adds fonts-liberation (Apache-2.0).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Frontend: retry /words POST once after 2s delay if it gets 400/404,
which happens when navigating via wizard after container restart
(session cache not yet warm).
Backend: log when session needs DB reload and when dewarped_bgr is missing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cell-First OCR (v2): Each cell is cropped and OCR'd in isolation,
eliminating neighbour bleeding (e.g. "to", "ps" in marker columns).
Uses ThreadPoolExecutor for parallel Tesseract calls.
Document type detection: Classifies pages as vocab_table, full_text,
or generic_table using projection profiles (<2s, no OCR needed).
Frontend dynamically skips columns/rows steps for full-text pages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add DewarpDetection type with per-method results
- Expand method labels for all 4 detectors (A-D)
- Show green/amber banner: applied vs quality-gate-rejected
- Expandable "Details" panel showing all 4 methods with confidence bars
- Visual confidence bars instead of plain percentage
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace setBackgroundImage() with backgroundImage property (v6 breaking change)
- Replace setWidth/setHeight with Canvas constructor options
- Fix opacity handler to use direct property access
- Update CLAUDE.md: use git -C and docker compose -f instead of cd
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Rename Step 6 label to "Korrektur" (was "OCR-Zeichenkorrektur")
2. Move _fix_character_confusion from pipeline Step 1 into
llm_review_entries_streaming so corrections are visible in the UI:
char changes (| → I, 1 → I, 8 → B) are now emitted as a batch event
right after the meta event, appearing in the corrections list
3. StepReconstruction: all cells (including empty) are now rendered as
editable inputs — removed filter that hid empty cells from the editor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>