Files
myscan/README.md
T
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

45 lines
3.6 KiB
Markdown

# myscan
Linux driver tools for the Hama myScan (00052343) scanner mouse, a Dacuda design
(USB 274f:c001: UVC MJPEG camera + HID mouse).
- `myscan/xu.py` — UVC extension-unit access: switch between mouse and scan mode, LEDs, exposure
- `myscan/frame.py` — fix the lying JPEG header and decode the per-frame sensor record (laser dx/dy)
- `myscan/calib.py` — per-device calibration from the mouse's EEPROM: colour gains, flat field, lens undistortion
- `myscan/stitching/` — page stitching, independent of the scanner hardware (no device imports), so it can
be used elsewhere: `from myscan.stitching import Corrector, PageGraph`. Its modules, lowest level first:
`geometry` (rigid transforms, poses), `filters` (grayscale, high-pass, feather weights), `correct`
(`Corrector`: lens undistortion + flat field), `odometry` (`LaserOdometry`, the myScan's laser motion
prior; another device can pass its own object with `predict()`), `register` (ECC, phase correlation, SIFT
matching, overlap check), `canvas` (weighted canvases, page composition, parallel rendering), `posegraph`
(robust pose-graph optimisation), `loops` (loop-closure candidates), and the two stitchers built from them:
`pagegraph` (`PageGraph`: assembles the page from all frames at once with loop closures between passes;
used by `scan.py` and `stitch.py`) and `incremental` (`Stitcher`: frame by frame, `stitch.py --live`)
- `tools/scan.py` — scan with the button: `python tools/scan.py` (press to start, press again to stop).
`--view [PORT]` serves a live view at `http://<host>:8000/`: the camera, the page as it is stitched
(re-solved every 1.5 s, current position outlined), Start/Stop buttons, PNG/JPEG download of the finished
page and a Screenshot button (camera + page + status as one PNG)
- `tools/app.py` — desktop app (Qt/PySide6; Linux, Windows, macOS): live camera and page view while scanning
(Start/Stop or the scan button, F5), then OCR of the finished page with RapidOCR (`myscan/ocr.py`;
multilingual PP-OCRv6 models bundled in the wheel, works offline). Recognised lines are outlined on the page by
confidence, and the text is selected right on the page like in a PDF viewer: drag (in reading order across
lines), double-click a word, triple-click a line, shift-click to extend, Ctrl+A; Ctrl+C or right-click copies.
Middle-drag or Space+drag pans, the wheel zooms. Copy all and Save text (.txt) take the whole page. `python tools/app.py [image]` also opens and reads existing images (Open, or
drag and drop), which is all it does on machines without the mouse
- `myscan/scanner.py` — the scan loop shared by `scan.py` and the app (finds the mouse's `/dev/videoN` itself)
- `myscan/live.py`, `myscan/webview.py` — the live preview and its browser viewer (standard library only)
- `tools/record.py` — record a scan session: `python tools/record.py -d 25 -o scan_text`
- `tools/stitch.py` — stitch a recording: `python tools/stitch.py scan_text` -> `scan_text/page.png`
- `tools/probe.py` — log raw frames and HID reports side by side
- `tools/scantest.py` — minimal scan-mode test: grab frames, decode records, restore mouse mode
See [FINDINGS.md](FINDINGS.md) for the protocol and calibration notes, and [EEPROM.md](EEPROM.md) for the
calibration blob.
Setup: `python -m venv .venv && .venv/bin/pip install -r requirements.txt`
**Calibration cache:** `calib/eeprom_3000.bin` in this repo is the EEPROM dump of one specific mouse.
`myscan/calib.py` uses that file whenever it exists and only reads the mouse when it is missing. With a
different mouse, delete it first (`rm calib/eeprom_3000.bin`), so the next scan reads and caches your own
unit's calibration (about 15 s).