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>
fix_cell_phonetics() ersetzt fehlerhafte IPA-Klammern UND fuegt fehlende
Lautschrift fuer englische Woerter ein (z.B. badge, film, challenge, profit).
Wird auf alle Zellen mit col_type column_en/column_text angewandt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
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>
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>
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>
NameError behoben: skip_heal_gaps war nicht im Scope der
_word_batch_stream_generator Funktion.
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>
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>
Wenn column_result fehlt (z.B. OCR Overlay Pipeline), wird automatisch
eine einzelne ganzseitige Pseudo-Spalte erzeugt statt einen Fehler zu werfen.
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>
- detect_rows: Content-Strips nutzen jetzt box_ranges_inner (geschrumpft
um border_thickness, min 5px) statt der vollen Box-Range
- detect_words: _row_in_box Filter nutzt ebenfalls inner Range
- Dadurch wird die letzte Zeile oberhalb einer Box nicht mehr
faelschlicherweise der Box zugeordnet und ausgeschlossen
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 wurde nur bei is_vocab (column_en/column_de)
aufgerufen. Fuer Sub-Sessions mit column_text wurden keine Eintraege
erzeugt, daher blieb die Korrektur-Tabelle leer.
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>
_is_noise_tail_token() stuft rein nicht-alphabetische Tokens wie
€0.50, £1, €2.50 als OCR-Noise ein und entfernt sie. Zusaetzlich
zerstoert ' '.join(tokens) das proportionale Spacing.
Fuer Single-Column Sub-Sessions wird _clean_cell_text uebersprungen.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Zeigt low-confidence Woerter (conf<30) und Zellinhalte pro Zeile,
um fehlende Euro/Pfund-Betraege zu diagnostizieren.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>