DIY WSI
The larger of the two video-to-WSI systems: live camera acquisition, a Qt desktop app, real-time stitching with pose-graph positioning, and an analysis stack that is written but not wired to the application.
Purpose
Build whole slide images from a microscope camera feed rather than a scanner, covering the acquisition end that Video to WSI deliberately leaves out. See Video-Based WSI Mosaicing for the method.
Data used
Microscope camera feeds — Leica Flexacam and generic webcams via OpenCV, plus GenICam devices. The repository carries a calibration profile for the Leica Flexacam i5: 1.55 µm native sensor pitch at 12 MP, 0.5× C-mount adapter assumed. Nothing patient-identifiable is tracked.
Methods
FastAPI backend with pinned dependencies, React frontend, and a Qt desktop application. 278 tracked files, 55 test modules, thirteen route modules.
The backend is unusually well decomposed for a project of this kind — separate modules for acquisition (opencv_camera, genicam_camera, capture_session), motion and optical flow, pose and position graphs, coverage tracking and gap navigation, checkpointing, disk-tile compositing and pyramid writing, DICOM export, audit and regression.
Two features worth naming because they address failure modes a naive implementation ignores:
- Coverage enforcement. A
coverage_trackerandgap_navigatormaintain 70% default overlap and detect uncovered regions in any scan direction. Hand scanning otherwise leaves holes that only become visible after stitching. - Bounded-memory tiled export.
disk_tile_compositorandpyramid_writerbuild pyramidal BigTIFF from disk tiles rather than assembling the whole mosaic in RAM — the constraint that decides whether large scans are possible at all.
The registration decision, which is the interesting part
The codebase contains estimateAffinePartial2D (similarity, 4 DOF) and findHomography (8 DOF) in several modules, plus a validation layer with scale, rotation, reprojection-error and shear tolerances in strict and relaxed modes.
But the shipped default is translation-only. config.py sets force_translation_only: True — “disable feature-based rotation/scale” — and phase_correlation_priority: True — “try phase correlation FIRST to prevent rotation”. Both are genuinely consumed in realtime_stitcher.py, and a test asserts that ORB matches carrying rotation or scale are rejected when the flag is set.
So the richer transform machinery is present but gated off by default, and the reason recorded in the config is drift prevention. Video to WSI reaches the same endpoint by a different route — estimating an affine and then collapsing it to a median translation. Two independent implementations, no shared code, same conclusion. That convergence is the most useful finding across the pair and it is written up on Video-Based WSI Mosaicing.
Current state / open questions
Very active — last commit 2026-07-26, the day of this review, a repo-wide ruff and eslint sweep. Working tree carries only an untracked _to_delete/.
The README’s documented defaults disagree with the code
Reading source rather than documentation paid for itself again. The README documents validation tolerances; config.py disagrees for the default mode:
| Relaxed mode (the default) | README | config.py |
|---|---|---|
| Max scale deviation | ±15% | 0.30 (30%) |
| Max rotation | ±8.6° | 0.087 rad (~5°) |
| Max reprojection error | 15 px | 25 px |
All three are wrong, and in different directions — the README understates the scale and error tolerance and overstates the rotation tolerance. The strict mode figures (±3%, ±2°, 5 px) do match the code. One path in realtime_stitcher.py then doubles the relaxed scale tolerance again at runtime. Anyone tuning acceptance rates from the README would be working from three wrong numbers for the mode that is on by default.
The analysis stack is not reachable from the application
The README advertises “Advanced Analysis” — tissue detection, cell detection, spatial and texture analysis, artifact detection, “12+ quantitative quality scores”. The code exists and is substantial. But advanced_pipeline.py and pathology_analyzer.py are imported only by test_advanced_pipeline.py — no route, no main.py, nothing else. These are a library with a demo driver, not features of the running system. Presented in the README as capabilities of the app, which they are not yet.
The calibration gap, which matters most
config.py contains object_pixel_size_um(profile, magnification, capture_width), which computes specimen µm/px correctly as sensor_pitch / (magnification × adapter). The repository’s own test asserts the Leica Flexacam i5 at 20× gives 0.155 µm/px.
That function is called only from tests. Meanwhile pathology_analyzer.calculate_cell_metrics defaults pixel_size_um = 0.5 and computes cell_density as cells per mm² from it.
So the correct calibration is implemented, and the consumer of calibration defaults to a placeholder roughly 3.2× too large — about a 10× error in any per-mm² density, since area goes as the square. Nothing is currently shipping wrong numbers to users, because the analysis is not wired into the API; the two facts together mean this is a gap to close before wiring, not a live defect. Video to WSI has the identical 0.5 µm/px default, independently.
Open questions
- Wire
object_pixel_size_um()into the analysis path, or makepixel_size_uma required argument with no default. A silent placeholder in a quantitative metric is the failure mode worth designing out. - Reconcile the README’s relaxed-mode tolerances with
config.py, and decide which is intended. - No LICENSE file, though the README carries an MIT badge. Same situation as Pathology Atlas Pipeline, where a README claimed MIT with no LICENSE present. Worth fixing across all three at once.
[unverified]as to intent. - Is the analysis stack meant to be wired in, or is it exploratory code kept for reference? Nothing records the intent.
[unverified] - A 332 KB
CHANGELOG.mdand anISSUES.mdsit at top level alongsidedocs/. Thedocs/reorganisation is half done.
Related: Video to WSI — the sibling with no shared code that converged on the same registration model. Video-Based WSI Mosaicing — the method page. Pathology Atlas Pipeline — the third imaging tool in the estate, and the other one missing its declared licence. WSI Quality Control — the artifact detection here overlaps with what HistoQC already does.
Derived from: repository working tree read 2026-07-26 — README.md, backend/config.py, backend/pathology_analyzer.py, backend/advanced_pipeline.py, backend/calibration.py, backend/robust_matching.py, backend/realtime_stitcher.py, backend/requirements.txt, backend/tests/test_two_pass_trajectory.py, plus git ls-files and git log at commit cd4de18.