File size: 2,921 Bytes
1a12965
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/env python
"""Generate a labeled sample gallery of every augmentation effect in isolation.

For each of the 25 configurable augmentation families, forces that one effect
on (probability=1.0) and disables every other effect, so the visual result is
attributable to that effect alone. Placement is frozen (no rotation/scale/
misplacement jitter, fixed template) so samples across effects are directly
comparable. Writes 5 sample images per effect to degradation/<effect>/, each
a multi-panel figure (full page, signature crop, ink mask, coverage metrics,
difficulty breakdown) via the existing visualizer.

Usage:
    python scripts/generate_degradation_gallery.py
"""

from __future__ import annotations

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from src.config.loader import load_config
from src.generator import GeneratorContext
from src.visualization.visualizer import save_visualization

SIGNATURE_EFFECTS = [
    "rotation", "stroke_dilation",
    "ink_fading", "ink_bleed", "motion_blur", "gaussian_blur",
]
DOCUMENT_EFFECTS = [
    "perspective", "contrast", "gamma", "coffee_stain", "stain",
    "shadow", "crumple", "discoloration", "page_tilt", "dust", "scanner_streaks",
    "scanner_noise", "salt_pepper", "jpeg_compression",
]
ALL_EFFECTS = SIGNATURE_EFFECTS + DOCUMENT_EFFECTS

OUT_ROOT = Path(__file__).resolve().parents[1] / "degradation"
SAMPLES_PER_EFFECT = 5
TEMPLATE_ID = "bank_doc_05"  # decent-sized signature box (255x35px)
FORCED_STRENGTH = 0.75


def build_overrides(target_effect: str) -> list[str]:
    overrides = [
        f"document.template={TEMPLATE_ID}",
        "placement.rotation_deg.min=0", "placement.rotation_deg.max=0",
        "placement.scale_factor.min=0.85", "placement.scale_factor.max=0.85",
        "placement.x_offset=0", "placement.y_offset=0",
        "placement.misplacement_probability=0.0",
        "generation.run_validation=false",
    ]
    for name in ALL_EFFECTS:
        is_target = name == target_effect
        overrides.append(f"augmentation.{name}.enabled={'true' if is_target else 'false'}")
        overrides.append(f"augmentation.{name}.probability={'1.0' if is_target else '0.0'}")
    overrides.append(f"augmentation.{target_effect}.strength={FORCED_STRENGTH}")
    return overrides


def main() -> None:
    OUT_ROOT.mkdir(parents=True, exist_ok=True)
    for effect in ALL_EFFECTS:
        out_dir = OUT_ROOT / effect
        out_dir.mkdir(parents=True, exist_ok=True)

        config = load_config(overrides=build_overrides(effect))
        ctx = GeneratorContext(config)

        for i in range(1, SAMPLES_PER_EFFECT + 1):
            metadata, final_image, _ = ctx.run_sample(i)
            save_visualization(out_dir / f"sample_{i}.png", final_image, metadata)

        print(f"[{effect}] wrote {SAMPLES_PER_EFFECT} samples -> {out_dir}")


if __name__ == "__main__":
    main()