"""Application configuration and tunable defaults. Plain dataclasses. Detection is YOLO-only and restoration is DeepMosaics-only, so the knobs here are the YOLO inference params, the overlay style, and the DeepMosaics weights. """ from __future__ import annotations from dataclasses import dataclass, field DETECTORS = ("yolo",) RESTORERS = ("deepmosaics", "deepmosaics_video") @dataclass(frozen=True) class DetectionConfig: """Parameters for the YOLO detector.""" yolo_conf: float = 0.2 # confidence threshold (LADA recommends ~0.2) yolo_imgsz: int = 640 # inference image size yolo_device: str | None = None # None => auto ("cuda" if available, else "cpu") @dataclass(frozen=True) class OverlayConfig: """How detections are drawn over the image.""" # RGB per CensorType value colors: dict[str, tuple[int, int, int]] = field( default_factory=lambda: { "mosaic": (231, 76, 60), # red "blur": (241, 196, 15), # yellow "black_bar": (26, 188, 156), # teal "unknown": (155, 89, 182), # purple } ) line_width: int = 2 fill_alpha: int = 48 # 0..255 translucency of the region fill show_labels: bool = True @dataclass class AppConfig: detection: DetectionConfig = field(default_factory=DetectionConfig) overlay: OverlayConfig = field(default_factory=OverlayConfig) detector: str = "yolo" # only "yolo" model_path: str | None = None # weights path, used by the YOLO detector default_threshold: float = 0.20 # initial overlay confidence threshold # --- restoration ("расцензурить") --- restorer: str = "deepmosaics" # "deepmosaics" | "deepmosaics_video" dm_dir: str | None = None # DeepMosaics repo dir (contains deepmosaic.py) dm_model: str | None = None # DeepMosaics clean weights (clean_*.pth) dm_python: str | None = None # python exe for DeepMosaics (None = current) dm_gpu: str = "0" # CUDA device id, "-1" for CPU def normalize_config(cfg: AppConfig) -> None: """Coerce legacy/removed settings to supported values (mutates ``cfg``). Old projects / settings.json may carry the removed ``classic``/``combined`` detectors or the ``inpaint`` restorer — map those onto the survivors so loading them doesn't blow up at build time. """ if cfg.detector not in DETECTORS: cfg.detector = "yolo" if cfg.restorer not in RESTORERS: cfg.restorer = "deepmosaics"