Gap-basierte Erkennung findet bei kleinen Box-Bildern zu wenige Gaps
und mergt Zeilen (7 raw gaps -> 4 validated -> nur 3 rows statt 6).
Sub-Sessions nutzen jetzt direkt _build_rows_from_word_grouping(),
das Woerter nach Y-Position clustert — robuster fuer komplexe Box-Layouts.
Zusaetzlich: alle zones=None Crashes gefixt (replace_all .get("zones") or []).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
column_result.get("zones", []) gibt None zurueck wenn der Key mit
Wert None existiert. Geaendert zu .get("zones") or [].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bisher wurden _word_dicts, _inv und _content_bounds fuer Sub-Sessions
nicht gecacht, sodass detect_rows auf detect_column_geometry() zurueckfiel.
Das konnte bei kleinen Box-Bildern mit <5 Woertern fehlschlagen.
Jetzt laeuft Tesseract + Binarisierung direkt im Pseudo-Spalten-Block,
und die Intermediates werden gecacht. Zusaetzlich ausfuehrliche Kommentare
zur Zeilenerkennung (detect_row_geometry, _regularize_row_grid).
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>
Alle Bild-Endpoints (cropped, columns-overlay, rows-overlay,
words-overlay) suchten nur nach cropped/dewarped. Sub-Sessions haben
nur ein original-Bild. Neue Hilfsfunktion _get_base_image_png() mit
Fallback-Kette: cropped > dewarped > original.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Spalten-/Zeilen-/Woerter-Erkennung suchen nach cropped_bgr oder
dewarped_bgr. Bei Sub-Sessions existiert nur original_bgr (der
Box-Ausschnitt). Jetzt wird original_bgr automatisch als cropped_bgr
gesetzt, sowohl im Cache-Aufbau als auch bei der Erstellung.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Box-Sub-Sessions haben bereits ein zugeschnittenes Bild. Orientierung,
Begradigung, Entzerrung und Crop werden uebersprungen (skipped).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rote semi-transparente Box-Markierung in allen Overlays (Spalten, Zeilen, Woerter)
- Zeilenerkennung: Combined-Image-Ansatz schliesst Box-Bereiche aus
- Woerter-Erkennung: Zeilen innerhalb von Box-Zonen werden gefiltert
- Sub-Sessions: parent_session_id/box_index in DB-Schema
- POST /sessions/{id}/create-box-sessions erstellt Sub-Sessions aus Box-Regionen
- Session-Info zeigt Sub-Sessions bzw. Parent-Verknuepfung
- Sessions-Liste blendet Sub-Sessions per Default aus
- Rekonstruktion: Fabric-JSON merged Sub-Session-Zellen an Box-Positionen
- Save-Reconstruction routet box{N}_* Updates an Sub-Sessions
- GET /sessions/{id}/vocab-entries/merged fuer zusammengefuehrte Eintraege
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Content-Streifen oberhalb/unterhalb von Boxen werden zu einem Bild zusammengefügt,
Spaltenerkennung läuft einmal auf dem kombinierten Bild. Entfernt Step 5c
(suspicion-based gap alignment), da der neue Ansatz das Problem an der Wurzel löst.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vorher wurden alle internen Gaps geprueft, was echte Spaltentrennungen
(EN→DE) faelschlicherweise entfernte. Jetzt werden nur Gaps geprueft,
die eine unverhaeltnismaessig breite rechte Spalte erzeugen wuerden
(>2x Median-Spaltenbreite). Schwelle auf 15% gesenkt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Variable wurde vor ihrer Definition in Step 7 referenziert.
Eigene margin_thresh Variable fuer Step 5c eingefuehrt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Interiore Gaps werden jetzt geprueft: rechts des Gaps muessen
mindestens 25% der Woerter eine gemeinsame linke Kante teilen.
Verhindert falsche Spaltentrennungen innerhalb breiter Spalten
(z.B. Example-Spalte mit kurzen und langen Eintraegen).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Weitere NameError-Probleme vom Modul-Refactoring: beide Symbole
werden in cv_cell_grid.py benutzt, sind aber in cv_ocr_engines.py
definiert und waren nicht importiert.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Funktion war nur in cv_review.py definiert, wurde aber auch in
cv_ocr_engines.py und cv_layout.py benutzt — NameError zur Laufzeit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
NameError in build_cell_grid_v2 weil _MIN_WORD_CONF nur in
_ocr_cell_crop und build_cell_grid lokal definiert war.
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>
Wenn bereits 2+ breite Content-Spalten existieren, ist das Layout
wahrscheinlich korrekt in EN/DE getrennt. Split wird nur ausgefuehrt
wenn eine einzelne breite Spalte EN+DE kombiniert enthaelt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gaps die den Spaltenrand beruehren (Margins) werden jetzt ausgeschlossen,
nur interne Gaps werden als Split-Kandidaten betrachtet. Behebt das
Problem dass trailing whitespace faelschlich als groesster Gap gewaehlt
wurde. Early-return in _run_ocr_pipeline_for_page gibt jetzt korrekt
([], rotation) statt [] zurueck.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Spalten mit <=2 Woertern und <15% Breite werden jetzt als column_marker
statt als content-Spalte klassifiziert. Bei 2 breiten Content-Spalten
wird die rechte als column_example statt column_de gelabelt, da die
linke Spalte EN+DE kombiniert enthaelt.
OSD-Zoom von 1.0 auf 2.0 erhoeht fuer zuverlaessigere Orientierungserkennung.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rotation wird jetzt in upload_pdf_get_info() erkannt, damit Thumbnails
bei der Seitenauswahl bereits richtig herum angezeigt werden.
Debug-Logging fuer _split_broad_columns hinzugefuegt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
_split_broad_columns() erkennt EN/DE-Gemisch in breiten Spalten via
Word-Coverage-Analyse und trennt sie am groessten Luecken-Gap.
Thumbnails und Page-Images werden serverseitig per fitz rotiert,
Frontend laedt Thumbnails nach OCR-Processing neu.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tesseract OSD erkennt 0/90/180/270° Rotation und korrigiert
automatisch vor dem Deskew. Loest das Problem mit Buchscannern,
bei denen jede 2. Seite auf dem Kopf steht.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shared Funktion positional_column_regions() in cv_vocab_pipeline.py,
wird jetzt von beiden Pfaden (Vocab-Worksheet + OCR Pipeline Admin)
genutzt. classify_column_types() bleibt als Legacy erhalten.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Zeigt die ersten 8 Zeichen der Session-ID neben dem Untertitel an,
damit die Session einfach identifiziert und kommuniziert werden kann.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprachbasiertes Scoring (classify_column_types) verursachte vertauschte
Spalten auf Seite 3 bei Beispielsaetzen mit vielen englischen Funktionswoertern.
Neue _positional_column_regions() ordnet Spalten rein geometrisch (links→rechts)
zu. OCR Pipeline Admin bleibt unveraendert.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Woerter aus Sub-Header-Bereichen ueberlappten korrekte Spaltenluecken
und liessen die Word-Validation faelschlich Gaps verwerfen. Jetzt werden
nur Woerter aus dem gewaehlten Segment fuer die Validation verwendet.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Statt full-width Zeilen zu maskieren wird die Seite jetzt an grossen
horizontalen Luecken (Sub-Header, Kapitelgrenzen) in Segmente unterteilt.
Das groesste Segment wird fuer die vertikale Projektion verwendet.
Dadurch stoeren Illustrationen und Ueberschriften nicht mehr.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wenn pixel-basierte Projektion zu wenige Spaltenluecken findet (z.B.
durch Illustrationen/Grafiken die Luecken fuellen), wird jetzt eine
wort-basierte Gap-Detection als Zwischenschritt vor dem Clustering
ausgefuehrt. Tesseract-Wort-BBs sind immun gegen dekorative Grafiken.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Farbige Sub-Header (z.B. "Unit 4: Bonnie Scotland") mit voller Breite
fuellten die Spaltenluecken im vertikalen Projektionsprofil auf und
fuehrten zu 11 statt 5 erkannten Spalten. Zeilen mit >40% Tintendichte
werden jetzt vor der Projektion maskiert.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After iterative projection (pass 1) and word-alignment (pass 2), a third
pass uses Tesseract word positions + linear regression per text line to
measure and correct residual rotation. This catches cases where passes 1-2
leave significant slope (e.g. 1.7° residual on heavily skewed scans).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Increase iterative deskew coarse_range from ±2° to ±5° to handle
heavily skewed scans
- New deskew_two_pass(): runs iterative projection first, then
word-alignment on the corrected image to detect/fix residual skew
(applied when residual ≥ 0.3°)
- OCR pipeline API auto_deskew now uses deskew_two_pass by default
- Vocab worksheet _run_ocr_pipeline_for_page uses deskew_two_pass
- Deskew result now includes angle_residual and two_pass_debug
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- LLM Compare Seiten, Configs und alle Referenzen geloescht
- Kommunikation-Kategorie in Sidebar mit Video & Chat, Voice Service, Alerts
- Compliance SDK Kategorie aus Sidebar entfernt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Original pages rendered at full resolution (pdf-page-image endpoint, zoom=2.0)
instead of downscaled thumbnails
- Insert-row triangles on left margin between every row (hover to reveal)
- Dynamic extra columns: "+" button in header adds custom columns
(e.g. Aussprache, Wortart), removable via hover-x on column header
- Extra columns stored per-page (pageExtraColumns state) so different
source pages can have different column structures
- Grid template adjusts dynamically based on number of columns
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove max-w-7xl constraint on content area so panels stretch to edges
- Fall back to direct API thumbnail URLs when blob URLs are empty
- Original pages now reliably show even if preloaded thumbnails failed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Swap from 3/5-2/5 grid to 1/3-2/3 flexbox (original left, table right)
- Table uses 3 equal 1fr columns for EN/DE/example instead of cramped 13-col grid
- Full viewport height minus header (calc(100vh - 240px)) for more visible rows
- Show only processed pages in original preview (filtered by selectedPages)
- Remove per-row insert buttons to reduce vertical noise
- Compact row spacing (py-1.5) to fit ~15+ rows without scrolling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
process-single-page now runs the full CV pipeline (deskew → dewarp → columns →
rows → cell-first OCR v2 → LLM review) for much better extraction quality.
Falls back to LLM vision if pipeline imports are unavailable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>