Commit Graph
5 Commits
Author SHA1 Message Date
erikandClaude Opus 5.5 2ef567580a Decide text orientation per page instead of per line
RapidOCR's angle classifier judges each cut-out line on its own and now
and then turns a perfectly upright line upside down, which then reads as
garbage ("Jo a ds ne t i d s t d no" for a line ending in "or" on the
latest scan). It is off now. All lines on a page face the same way, so a
page that reads poorly (upright text scores 0.97-1.0 per character,
upside-down text 0.55-0.8) is read again rotated 180 degrees and the
better reading kept; that also covers pages turned 90 degrees. The app
shows an upside-down page turned the right way up.

Upright pages read about 25% faster without the per-line classifier.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:44:40 +00:00
erikandClaude Opus 5.5 a1942faa41 Order OCR lines in the page's own frame, so slanted scans read right
Lines were grouped into rows and sorted by their centres' image y and
their left x. On a page scanned at an angle (5.4 degrees on the latest
scan) a short line's centre sits lower than that of a long line beside
it, so lines got swapped or merged into one row and paragraphs read as
nonsense. Rows now use positions along and across the text direction,
the length-weighted median direction of the lines (ocr.text_direction,
ocr.page_coords); a rotated page gives the same text.

Paragraph joining also follows a list item's hanging indent (continuation
lines lined up after "(a)", "1.", a bullet ...) and lets a heading whose
number was read as a separate item run on to its next line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:44:40 +00:00
erikandClaude Opus 5.5 6631073be5 Copy OCR text as paragraphs
A Paragraphs toggle (Ctrl+J, on by default) makes copied and saved text
put each paragraph on one line: line breaks inside a paragraph become
spaces and words hyphenated across lines are rejoined (the hyphen stays
before a capital, as in "Nord-Amerika"). A line ends its paragraph if the
next one is indented, has a different text size, or starts with a word
that would have fitted at the end of this one, which works for justified
and ragged-right text alike; rows of several items (tables) are left
alone. The right-click menu offers the other form.

ocr.paragraph_joins gives the joins as edits on layout()'s text, and
reflow applies those inside any range, so selections keep working on the
page's character positions.

Ctrl+C now copies in the chosen form (QAction.triggered passed
checked=False through as paragraphs=False), and tabs show in the status
bar's selection preview.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:44:40 +00:00
erikandClaude Opus 5.5 67333528ca Select and copy text directly on the page
The text pane is gone: recognised text is selected on the page image like
in a PDF viewer (drag in reading order, double-click a word, triple-click a
line, shift-click to extend, Ctrl+A), copied with Ctrl+C or the context
menu, and previewed in the status bar; on X11/Wayland it also goes to the
primary selection. Middle-drag or Space+drag pans.

OCR asks RapidOCR for per-character boxes and keeps each line's character
boundaries (Line.edges), with Line.locate/quad/word for hit testing and
drawing; lines whose boxes don't match the text fall back to even spacing.

Errors are logged to the terminal with their traceback, and Ctrl+C in the
terminal closes the app (restoring mouse mode), dismissing any open dialog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:25:11 +00:00
erikandClaude Opus 5.5 909baec1e7 Desktop app with live scanning and OCR
tools/app.py (myscan/app.py, Qt/PySide6) shows the camera and the page as it
is stitched, Start/Stop or the scan button (F5), then reads the finished page
with RapidOCR (myscan/ocr.py; bundled multilingual models, offline). Lines are
outlined on the page by confidence and linked to an editable text pane that
can be copied or saved. Existing images can be opened or dropped, so the app
is useful without the mouse.

The scan loop moves from tools/scan.py to myscan/scanner.py, shared by both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:05:22 +00:00