Spaces:
Build error
Build error
| """ | |
| Bootstrap training data when CIFAKE download is slow/unavailable. | |
| REAL = CIFAR-10 photos (same source as CIFAKE real class) | |
| FAKE = stylized variants (placeholder until full CIFAKE download completes) | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import pickle | |
| import tarfile | |
| import urllib.request | |
| from io import BytesIO | |
| from pathlib import Path | |
| import numpy as np | |
| from PIL import Image, ImageFilter, ImageOps | |
| CIFAR_URL = "https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz" | |
| def _unpickle_file(path: Path) -> dict: | |
| with path.open("rb") as handle: | |
| return pickle.load(handle, encoding="bytes") | |
| def download_cifar10(cache_dir: Path) -> Path: | |
| cache_dir.mkdir(parents=True, exist_ok=True) | |
| tar_path = cache_dir / "cifar-10-python.tar.gz" | |
| extract_dir = cache_dir / "cifar-10-batches-py" | |
| if not extract_dir.exists(): | |
| if not tar_path.exists(): | |
| print("Downloading CIFAR-10 (~170 MB)…") | |
| urllib.request.urlretrieve(CIFAR_URL, tar_path) | |
| print("Extracting CIFAR-10…") | |
| with tarfile.open(tar_path, "r:gz") as tar: | |
| tar.extractall(cache_dir) | |
| return extract_dir | |
| def load_cifar_images(extract_dir: Path, limit: int) -> list[Image.Image]: | |
| images: list[Image.Image] = [] | |
| for batch_idx in range(1, 6): | |
| batch_path = extract_dir / f"data_batch_{batch_idx}" | |
| batch = _unpickle_file(batch_path) | |
| data = batch[b"data"] | |
| for row in data: | |
| arr = np.array(row, dtype=np.uint8).reshape(3, 32, 32).transpose(1, 2, 0) | |
| images.append(Image.fromarray(arr, mode="RGB")) | |
| if len(images) >= limit: | |
| return images | |
| return images | |
| def make_fake_variant(img: Image.Image, seed: int) -> Image.Image: | |
| rng = np.random.default_rng(seed) | |
| out = img.convert("RGB").resize((128, 128), Image.Resampling.BILINEAR) | |
| out = out.filter(ImageFilter.GaussianBlur(radius=0.6 + float(rng.random()))) | |
| out = ImageOps.posterize(out, bits=5) | |
| arr = np.asarray(out, dtype=np.float32) | |
| arr += rng.normal(0, 6, arr.shape) | |
| arr = np.clip(arr, 0, 255).astype(np.uint8) | |
| return Image.fromarray(arr, mode="RGB") | |
| def build_bootstrap(output_dir: Path, per_class: int) -> tuple[int, int]: | |
| cache = output_dir.parent / "_cache" | |
| extract_dir = download_cifar10(cache) | |
| real_dir = output_dir / "REAL" | |
| fake_dir = output_dir / "FAKE" | |
| real_dir.mkdir(parents=True, exist_ok=True) | |
| fake_dir.mkdir(parents=True, exist_ok=True) | |
| print(f"Building bootstrap set ({per_class} per class)…") | |
| cifar = load_cifar_images(extract_dir, per_class) | |
| for i, img in enumerate(cifar): | |
| img.resize((128, 128), Image.Resampling.LANCZOS).save(real_dir / f"real_{i:05d}.jpg", quality=92) | |
| make_fake_variant(img, seed=i).save(fake_dir / f"fake_{i:05d}.jpg", quality=92) | |
| print(f"Bootstrap ready REAL={len(cifar)} FAKE={len(cifar)}") | |
| return len(cifar), len(cifar) | |
| def main() -> None: | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--output", default="ml/data/cifake_sample") | |
| parser.add_argument("--per-class", type=int, default=2500) | |
| args = parser.parse_args() | |
| build_bootstrap(Path(args.output), args.per_class) | |
| if __name__ == "__main__": | |
| main() | |