docs: add architecture reference
This commit is contained in:
parent
c1a1342db2
commit
d93c8d97b3
1 changed files with 134 additions and 0 deletions
134
docs/architecture.md
Normal file
134
docs/architecture.md
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
# 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 4-point quadrilateral and flags:
|
||||
|
||||
- `locked`
|
||||
- `side_handles_enabled`
|
||||
|
||||
It supports:
|
||||
|
||||
- top-left normalization and winding correction
|
||||
- rectangle detection (`is_perfect_rectangle`)
|
||||
- squarize while preserving tilt
|
||||
- reset to axis-aligned orientation
|
||||
|
||||
## 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/`)
|
||||
Loading…
Add table
Add a link
Reference in a new issue