|
|
from __future__ import annotations |
|
|
from dataclasses import dataclass |
|
|
from enum import Enum |
|
|
from typing import List, Optional |
|
|
|
|
|
class Implementation(Enum): |
|
|
VECT = "Vectorised" |
|
|
|
|
|
class MatchSpace(Enum): |
|
|
LAB = "Lab (perceptual)" |
|
|
RGB = "RGB (euclidean)" |
|
|
|
|
|
@dataclass |
|
|
class Config: |
|
|
"""Runtime configuration for the Lab 5 mosaic generator pipeline.""" |
|
|
|
|
|
|
|
|
grid: int = 32 |
|
|
out_w: int = 768 |
|
|
out_h: int = 768 |
|
|
tile_size: int = 32 |
|
|
|
|
|
|
|
|
hf_dataset: str = "Kratos-AI/KAI_car-images" |
|
|
hf_split: str = "train" |
|
|
hf_limit: int = 200 |
|
|
hf_cache_dir: Optional[str] = None |
|
|
|
|
|
|
|
|
impl: Implementation = Implementation.VECT |
|
|
match_space: MatchSpace = MatchSpace.LAB |
|
|
|
|
|
|
|
|
use_uniform_q: bool = False |
|
|
q_levels: int = 8 |
|
|
use_kmeans_q: bool = False |
|
|
k_colors: int = 8 |
|
|
|
|
|
|
|
|
tile_norm_brightness: bool = False |
|
|
allow_rotations: bool = False |
|
|
|
|
|
|
|
|
tiles_cache_dir: Optional[str] = None |
|
|
|
|
|
|
|
|
do_bench: bool = False |
|
|
bench_grids: Optional[List[int]] = None |
|
|
|
|
|
def __post_init__(self) -> None: |
|
|
self._validate() |
|
|
|
|
|
def validate(self) -> None: |
|
|
"""Public wrapper that re-validates the current configuration.""" |
|
|
self._validate() |
|
|
|
|
|
def _validate(self) -> None: |
|
|
"""Validate numeric parameters so incorrect grids fail fast.""" |
|
|
if self.grid <= 0: |
|
|
raise ValueError("grid must be a positive integer") |
|
|
if self.tile_size <= 0: |
|
|
raise ValueError("tile_size must be a positive integer") |
|
|
if self.out_w <= 0 or self.out_h <= 0: |
|
|
raise ValueError("out_w and out_h must be positive integers") |
|
|
if self.out_w % self.grid != 0 or self.out_h % self.grid != 0: |
|
|
raise ValueError("out_w and out_h must be divisible by grid to maintain whole tiles") |
|
|
if self.hf_limit <= 0: |
|
|
raise ValueError("hf_limit must be positive") |
|
|
|