"""Application configuration and tunable defaults. Plain dataclasses. The detection thresholds matter most here — this tool is now an image-folder inspector for tuning the detectors, so keep them easy to tweak. """ from __future__ import annotations from dataclasses import dataclass, field @dataclass(frozen=True) class DetectionConfig: """Parameters for the detector. Thresholds tuned for the classic-CV detector.""" proc_max_dim: int = 720 # downscale longer side to this before detection (speed) min_area_frac: float = 0.0008 # ignore regions smaller than this fraction of the image # --- solid bars (black or white, achromatic, rectangular) --- black_intensity: int = 40 # V below this = dark-bar candidate white_intensity: int = 225 # V above this = light-bar candidate bar_saturation_max: int = 45 # S below this = achromatic (excludes colored fills) bar_min_extent: float = 0.80 # contour area / bbox area — how rectangular a bar must be # --- mosaic / pixelation --- mosaic_block_sizes: tuple[int, ...] = (8, 12, 16, 24) # candidate tile sizes (px, proc space) mosaic_residual_max: float = 6.0 # max reconstruction error to count as "blocky" mosaic_contrast_min: float = 14.0 # min local contrast (excludes flat gradients) mosaic_grad_min: float = 8.0 # min edge energy in BOTH x and y (excludes straight edges) mosaic_min_side: int = 24 # reject thin regions (px) — kills edge false-positives # --- blur --- blur_window: int = 31 # sliding window for local sharpness (odd) blur_sharpness_ratio: float = 0.35 # below this fraction of median sharpness => blurry blur_contrast_min: float = 8.0 # min local contrast (excludes flat regions) # --- YOLO detector (used only when detector == "yolo"/"combined") --- 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 = "classic" # "classic" | "yolo" | "combined" model_path: str | None = None # weights path, used by the YOLO detector default_threshold: float = 0.20 # initial overlay confidence threshold # --- restoration ("расцензурить") --- restorer: str = "inpaint" # "inpaint" | "deepmosaics" 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