File size: 3,259 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 80 81 82 83 84 85 86 87 88 89 90 | #!/usr/bin/env python
"""Generate samples with multiple random degradations stacked on one template.
Unlike scripts/generate_degradation_gallery.py (which isolates exactly one
effect per sample for comparison), this uses the realistic "varied batch"
probabilities from configs/generate.yaml unmodified -- every enabled effect
independently rolls its own probability per sample, so different samples end
up with different *combinations* of simultaneously-applied degradations, all
on the same template/box for a fair before/after comparison.
Each output image is the standard metrics visualization (full page, crop,
ink mask, coverage metrics, difficulty breakdown) plus a caption band listing
exactly which effects fired for that sample.
Usage:
python scripts/generate_multiple_degradation_gallery.py
"""
from __future__ import annotations
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from PIL import Image, ImageDraw, ImageFont
from src.config.loader import load_config
from src.generator import GeneratorContext
from src.visualization.visualizer import save_visualization
ROOT = Path(__file__).resolve().parents[1]
OUT_DIR = ROOT / "multiple_degradation"
N_SAMPLES = 10
TEMPLATE_ID = "bank_doc_05" # same template used in the single-effect gallery
def _load_font(size: int) -> "ImageFont.FreeTypeFont | ImageFont.ImageFont":
for candidate in (r"C:\Windows\Fonts\consola.ttf", r"C:\Windows\Fonts\arial.ttf"):
if Path(candidate).exists():
return ImageFont.truetype(candidate, size)
return ImageFont.load_default()
def _annotate_applied_effects(path: Path, metadata: dict) -> list[str]:
effects = metadata["augmentation"]["effects"]
applied = [name for name, rec in effects.items() if rec["applied"]]
difficulty = metadata["difficulty"]
caption = (
f"{metadata['document_id']} | applied degradations "
f"({len(applied)}/{len(effects)}): {', '.join(applied) if applied else 'none'}"
f" | difficulty = {difficulty['score']:.3f} ({difficulty['tier']})"
)
img = Image.open(path).convert("RGB")
band_h = 40
canvas = Image.new("RGB", (img.width, img.height + band_h), "white")
canvas.paste(img, (0, band_h))
draw = ImageDraw.Draw(canvas)
font = _load_font(16)
draw.rectangle([0, 0, canvas.width, band_h], fill=(15, 42, 67))
draw.text((14, 11), caption, fill="white", font=font)
canvas.save(path)
return applied
def main() -> None:
OUT_DIR.mkdir(parents=True, exist_ok=True)
overrides = [
f"document.template={TEMPLATE_ID}",
"generation.run_validation=false",
]
config = load_config(config_path=ROOT / "configs" / "generate.yaml", overrides=overrides)
ctx = GeneratorContext(config)
for i in range(1, N_SAMPLES + 1):
metadata, final_image, _ = ctx.run_sample(i)
out_path = OUT_DIR / f"sample_{i}.png"
save_visualization(out_path, final_image, metadata)
applied = _annotate_applied_effects(out_path, metadata)
print(f"[sample_{i}] {len(applied)} effects applied -> {', '.join(applied) or 'none'}")
print(f"\nWrote {N_SAMPLES} samples -> {OUT_DIR}")
if __name__ == "__main__":
main()
|