# compare_config.py
from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
from typing import Tuple
class Mode(Enum):
VIDEO = "video"
IMAGE = "image"
@dataclass(slots=True, frozen=True)
class CompareConfig:
"""
Konfiguration für Video- und Bildvergleich.
Designziele:
- Performance-skalierbar (für 10k+ Videos / 1M+ Bilder)
- Tuning über Profile möglich (Speed/Balance/Accuracy/LowResource)
- Transparent/erklärbar: Schwellenwerte + aktivierte Stufen
"""
mode: Mode = Mode.VIDEO # "video" | "image"
# Sampling / Frames (Video)
frame_interval_sec: float = 1.0
max_frames: int = 120 # harte Obergrenze (Performance)
resize_width: int = 320 # für Hash/Histogramm (schnell)
# Bildvergleich (Image)
enable_multiscale: bool = True
multiscale_widths: Tuple[int, ...] = (256, 384)
# Stufen aktivieren
enable_midlevel: bool = True
enable_highlevel: bool = False # optional (torch / embeddings)
enable_object_semantics: bool = False # nutzt Analyse-Ergebnisse (labels)
enable_offset_alignment: bool = True # nur Video sinnvoll
# Schwellenwerte
phash_gate_max_dist: int = 14 # 0..64 (kleiner=strenger)
midlevel_hist_max_dist: float = 0.28 # 0..1 (kleiner=strenger)
highlevel_cos_min_sim: float = 0.86 # 0..1 (größer=strenger)
object_jaccard_min_sim: float = 0.45 # 0..1
# Offset-Suche (Video)
max_offset_sec: float = 8.0
offset_step_sec: float = 0.5
def __post_init__(self):
# Da frozen=True, müssen wir object.__setattr__ verwenden, falls nötig
# Validierung der Wertebereiche
if not isinstance(self.mode, Mode):
raise ValueError(f"Ungültiger Modus: {self.mode}")
if not (0 <= self.phash_gate_max_dist <= 64):
raise ValueError("phash_gate_max_dist muss zwischen 0 und 64 liegen")
if not (0 <= self.midlevel_hist_max_dist <= 1):
raise ValueError("midlevel_hist_max_dist muss zwischen 0 und 1 liegen")
if not (0 <= self.highlevel_cos_min_sim <= 1):
raise ValueError("highlevel_cos_min_sim muss zwischen 0 und 1 liegen")
if not (0 <= self.object_jaccard_min_sim <= 1):
raise ValueError("object_jaccard_min_sim muss zwischen 0 und 1 liegen")
if self.max_frames <= 0:
raise ValueError("max_frames muss größer als 0 sein")
if self.resize_width <= 0:
raise ValueError("resize_width muss größer als 0 sein")
if self.frame_interval_sec <= 0:
raise ValueError("frame_interval_sec muss größer als 0 sein")
if self.max_offset_sec < 0:
raise ValueError("max_offset_sec darf nicht negativ sein")
if self.offset_step_sec <= 0:
raise ValueError("offset_step_sec muss größer als 0 sein")
if not self.multiscale_widths:
raise ValueError("multiscale_widths darf nicht leer sein")
if any(w <= 0 for w in self.multiscale_widths):
raise ValueError("Alle Werte in multiscale_widths müssen größer als 0 sein")