Commit Graph
4 Commits
Author SHA1 Message Date
erikandClaude Opus 5.5 c8b9f610bf Split stitching into a hardware-independent myscan.stitching package
stitch.py and pagegraph.py mixed laser odometry, image registration,
frame correction, canvas handling, pose-graph maths and the two stitchers.
They are now modules of myscan/stitching, which imports nothing from the
device code:

  geometry    rigid transforms, pose vectors, warp_add
  filters     grayscale, high-pass, feather weights
  correct     Corrector: undistortion + flat field (and weighted variant)
  odometry    LaserOdometry: the laser model and the phase-correlation
              override, shared by both stitchers
  register    ECC, phase correlation, SIFT matching, overlap agreement
  canvas      growable Canvas, layout, parallel render, normalize/compose
  posegraph   robust Gauss-Newton, largest connected component
  loops       keyframes and loop-closure candidates
  pagegraph   PageGraph, now orchestration only
  incremental Stitcher, on the shared Canvas

The stitchers take a Corrector and an odometry object (anything with
predict()) instead of building them, so another device can supply its
own motion prior. live.py drops its own canvas and normalisation for the
shared ones; PageGraph's mosaic check uses the parallel renderer.

Output on scan_text is unchanged (global stitcher identical, incremental
within 1 grey level). stitch.py --live now applies lens correction too
(--no-undistort restores the old output).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:55:22 +00:00
erikandClaude Opus 5.5 f47df93c97 Live browser view while scanning, with downloads and screenshots
scan.py --view serves a page (myscan/webview.py, standard library only) with
MJPEG streams of the latest camera frame and the page as it is stitched,
Start/Stop buttons, PNG/JPEG download of the finished page and a screenshot
of the current view.

myscan/live.py keeps a downscaled preview: new frames are pasted at their
current best pose, and a background thread re-solves the pose graph every
1.5 s (throttled to at most ~50% duty) and redraws the preview off the
registration thread. PageGraph.solve can now run on a prefix of the frames
while add() continues, keeping loop closures and features between solves,
so the final solve after the stop press is much shorter. Frame PNGs are
saved on their own thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 13:51:59 +00:00
erikandClaude Opus 5.5 026aa6c894 Global page assembly with loop closures and lens undistortion
The frame-by-frame stitcher accumulated drift, so later passes landed rotated
and offset, doubling text. myscan/pagegraph.py instead solves all frame poses
together: ECC odometry between consecutive frames (bridging single corrupt
frames), SIFT+RANSAC loop closures between overlapping passes, and a robust
Gauss-Newton pose graph. Loop matches must agree over the whole overlap, which
rejects matches on repeated text. Off-page frames and frames that disagree
with the mosaic are left out of the render.

calib.Undistort applies the EEPROM lens model (OpenCV k1..k3, p1, p2 plus
the tilt homography, as decoded in EEPROM.md); up to 8.8 px at the corners.

scan.py registers frames on a worker thread so capture no longer drops
frames, then assembles the page after the stop press (~11 s for a full
page). stitch.py uses the new assembly by default; --live keeps the old one.

EEPROM.md documents the full calibration blob layout, checksum and signature.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 13:06:45 +00:00
erikandClaude Opus 5.5 e70d56d957 Live button-driven scanning with EEPROM calibration
- ScanSession: scan-mode context manager with bright-pixel auto-exposure and
  sensor colour gains; tools/scan.py scans on the scan button with live stitching
- Read-only EEPROM access and calib.py parser (laser geometry, intrinsics,
  colour gains, black/white flat-field samples); flat-field correction in Stitcher
- OV7740 sensor access via the MCU proxy; colour gains from EEPROM fix green cast
- Stitcher: colour support, high-passed registration (robust on blank paper)
- RE notes on the Mac app's colour, exposure, stitching and button handling

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:13:59 +00:00