fork download
  1. # compare_config.py
  2. from __future__ import annotations
  3. from dataclasses import dataclass, field
  4. from enum import Enum
  5. from typing import Tuple
  6.  
  7.  
  8. class Mode(Enum):
  9. VIDEO = "video"
  10. IMAGE = "image"
  11.  
  12.  
  13. @dataclass(slots=True, frozen=True)
  14. class CompareConfig:
  15. """
  16. Konfiguration für Video- und Bildvergleich.
  17.  
  18. Designziele:
  19. - Performance-skalierbar (für 10k+ Videos / 1M+ Bilder)
  20. - Tuning über Profile möglich (Speed/Balance/Accuracy/LowResource)
  21. - Transparent/erklärbar: Schwellenwerte + aktivierte Stufen
  22. """
  23.  
  24. mode: Mode = Mode.VIDEO # "video" | "image"
  25.  
  26. # Sampling / Frames (Video)
  27. frame_interval_sec: float = 1.0
  28. max_frames: int = 120 # harte Obergrenze (Performance)
  29. resize_width: int = 320 # für Hash/Histogramm (schnell)
  30.  
  31. # Bildvergleich (Image)
  32. enable_multiscale: bool = True
  33. multiscale_widths: Tuple[int, ...] = (256, 384)
  34.  
  35. # Stufen aktivieren
  36. enable_midlevel: bool = True
  37. enable_highlevel: bool = False # optional (torch / embeddings)
  38. enable_object_semantics: bool = False # nutzt Analyse-Ergebnisse (labels)
  39. enable_offset_alignment: bool = True # nur Video sinnvoll
  40.  
  41. # Schwellenwerte
  42. phash_gate_max_dist: int = 14 # 0..64 (kleiner=strenger)
  43. midlevel_hist_max_dist: float = 0.28 # 0..1 (kleiner=strenger)
  44. highlevel_cos_min_sim: float = 0.86 # 0..1 (größer=strenger)
  45. object_jaccard_min_sim: float = 0.45 # 0..1
  46.  
  47. # Offset-Suche (Video)
  48. max_offset_sec: float = 8.0
  49. offset_step_sec: float = 0.5
  50.  
  51. def __post_init__(self):
  52. # Da frozen=True, müssen wir object.__setattr__ verwenden, falls nötig
  53. # Validierung der Wertebereiche
  54. if not isinstance(self.mode, Mode):
  55. raise ValueError(f"Ungültiger Modus: {self.mode}")
  56.  
  57. if not (0 <= self.phash_gate_max_dist <= 64):
  58. raise ValueError("phash_gate_max_dist muss zwischen 0 und 64 liegen")
  59.  
  60. if not (0 <= self.midlevel_hist_max_dist <= 1):
  61. raise ValueError("midlevel_hist_max_dist muss zwischen 0 und 1 liegen")
  62.  
  63. if not (0 <= self.highlevel_cos_min_sim <= 1):
  64. raise ValueError("highlevel_cos_min_sim muss zwischen 0 und 1 liegen")
  65.  
  66. if not (0 <= self.object_jaccard_min_sim <= 1):
  67. raise ValueError("object_jaccard_min_sim muss zwischen 0 und 1 liegen")
  68.  
  69. if self.max_frames <= 0:
  70. raise ValueError("max_frames muss größer als 0 sein")
  71.  
  72. if self.resize_width <= 0:
  73. raise ValueError("resize_width muss größer als 0 sein")
  74.  
  75. if self.frame_interval_sec <= 0:
  76. raise ValueError("frame_interval_sec muss größer als 0 sein")
  77.  
  78. if self.max_offset_sec < 0:
  79. raise ValueError("max_offset_sec darf nicht negativ sein")
  80.  
  81. if self.offset_step_sec <= 0:
  82. raise ValueError("offset_step_sec muss größer als 0 sein")
  83.  
  84. if not self.multiscale_widths:
  85. raise ValueError("multiscale_widths darf nicht leer sein")
  86.  
  87. if any(w <= 0 for w in self.multiscale_widths):
  88. raise ValueError("Alle Werte in multiscale_widths müssen größer als 0 sein")
  89.  
Success #stdin #stdout 0.26s 19400KB
stdin
Standard input is empty
stdout
Standard output is empty