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

4.1 KiB

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
  1. 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
  1. 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/)