ScanSlicer/docs/architecture.md
dan 426a18f342 chore: prune boilerplate and refresh stale docs
- Remove 257 redundant per-definition comment stubs across the package
- Drop dead nonlocal declarations in autoslicer_detection.py
- Document the swapped flag and swap_left_right in architecture docs
- Remove unsupported 'legacy override' claims from autotune/runtime docs
2026-09-11 23:07:30 +02:00

136 lines
4.1 KiB
Markdown

# Architecture
## Overview
ScanSlicer is a Qt desktop app split into UI mixins, controller mixins, canvas subsystems, and image-processing/autotune engines.
Top-level startup path:
1. `scanslicer.entry:main`
2. Backend/environment resolution and validation
3. `scanslicer.main:run_app`
4. `QtScanSlicer` window composition
## Module Map
- `scanslicer/entry.py`
- CLI parsing
- Wayland/X11 backend selection
- Qt platform environment configuration
- `scanslicer/main.py`
- `QtScanSlicer` main window lifecycle
- Theme handling and app icon resolution
- App bootstrap (`run_app`)
- `scanslicer/controller*.py`
- UI action handlers split by responsibility
- `scanslicer/ui_builders*.py`
- Widget construction for control panel, preview panel, and shared UI helpers
- `scanslicer/canvas*.py`
- Interactive image canvas for box display/editing
- `scanslicer/autoslicer.py`
- Detection/export engine wrapper
- `scanslicer/autoslicer_detection.py`
- Detection pipelines and contour-to-box extraction
- `scanslicer/autoslicer_feedback.py`
- Auto-tune profiles, candidate scoring, and feedback persistence
- `scanslicer/params.py`
- Parameter model, defaults, and user presets
- `scanslicer/slices.py`
- Box geometry model and polygon IoU helper
## UI Composition
`QtScanSlicer` inherits:
- `ScanSlicerUiBuilderMixin` (UI construction)
- `ScanSlicerControllerMixin` (behavior)
Controller mixin composition:
- `ScanSlicerStatusMixin` (status/logging/busy state)
- `ScanSlicerCanvasActionsMixin` (box operations and preview toggles)
- `ScanSlicerDetectionMixin` (worker orchestration)
- `ScanSlicerImageIOMixin` (directory/image loading and save/export)
- `ScanSlicerParamsMixin` (parameter/default/preset/autotune interactions)
## Detection Execution Flow
1. User action triggers `update_preview()`.
2. Detection starts in `DetectionTask` (`QRunnable`) on `QThreadPool` (single worker).
3. Worker runs `Autoslicer.autodetect_slices(...)`.
4. On completion:
- Cache normal preview image
- Cache filter preview image
- Update canvas image
- Merge/update boxes
5. Toolbar status and box state are refreshed.
Key properties:
- One detection worker at a time.
- Busy state disables controls during processing.
- Task IDs prevent stale callbacks from old tasks mutating UI.
## Auto-Tune Execution Flow
1. User clicks `Auto-tune`.
2. `AutotuneTask` runs in the same single-thread pool.
3. `autotune_for_current_image()`:
- Builds candidate parameter sets
- Ranks by current-image + prior feedback similarity
- Coarse pass on downscaled image (`fast_mode=True`)
- Fine pass on top finalists
- Applies best candidate to parameter model
4. UI controls sync from model and detection re-runs.
## Canvas System
- `QtSlicingCanvas` = interaction + rendering + state mixins
- Stores:
- image and zoom/pan state
- list of `PhotoSlice` objects
- active slice index
- drag modes (corner, side, rotation, box drag, panning)
- Emits `active_slice_changed` signal to keep toolbar state synchronized.
## Geometry Model
`PhotoSlice` stores a 4-point quadrilateral and flags:
- `locked`
- `side_handles_enabled`
- `swapped` (persistent left/right mirror state, honored by normalization)
It supports:
- top-left normalization and winding correction
- rectangle detection (`is_perfect_rectangle`)
- squarize while preserving tilt
- reset to axis-aligned orientation
- explicit left/right swap (`swap_left_right`)
## Persistence Model
Paths are runtime-dependent (host vs container), with environment overrides:
- Defaults JSON
- Presets JSON
- Auto-tune feedback JSON
- Session status log
Persistence writes are performed through explicit actions (save defaults/preset, save slices with feedback, status updates).
## Export Pipeline
For each locked box:
1. Compute output width/height from opposing edge lengths.
2. Build perspective transform from box quad to rectangle.
3. Warp source image with `cv2.warpPerspective`.
4. Save with format-specific encoding params.
## Packaging Surfaces
- Python package/CLI (`pyproject.toml`, script `scanslicer`)
- Docker runtime (`Dockerfile`, `docker-compose.yml`)
- AppImage (`packaging/appimage/`)