PixelModel-v6 / build_eval_set.py
TobiasLogic's picture
Publish PixelModel v6: MMDiT + REPA, 150k steps, FID 23.62 at cfg 3.0
6c311ad verified
Raw
History Blame Contribute Delete
3.16 kB
from __future__ import annotations
import argparse
import io
import json
import os
import random
import zipfile
from concurrent.futures import ThreadPoolExecutor
import numpy as np
import requests
from PIL import Image
ANN_URL = "http://images.cocodataset.org/annotations/annotations_trainval2014.zip"
def csr(img, size):
img = img.convert("RGB")
w, h = img.size
s = min(w, h)
l, t = (w - s) // 2, (h - s) // 2
return np.asarray(img.crop((l, t, l + s, t + s)).resize((size, size), Image.BICUBIC), dtype=np.uint8)
def fetch_one(item, size):
url, cap = item
for _ in range(3):
try:
r = requests.get(url, timeout=15)
if r.status_code == 200:
return csr(Image.open(io.BytesIO(r.content)), size), cap
except Exception:
pass
return None
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--work", default="/root/v6cache")
ap.add_argument("--n", type=int, default=5000)
ap.add_argument("--size", type=int, default=256)
ap.add_argument("--seed", type=int, default=0)
ap.add_argument("--workers", type=int, default=48)
args = ap.parse_args()
os.makedirs(args.work, exist_ok=True)
out_path = os.path.join(args.work, "eval_256.npz")
if os.path.exists(out_path):
print(f"[eval-set] already exists at {out_path}", flush=True)
return
ann_path = os.path.join(args.work, "captions_val2014.json")
if not os.path.exists(ann_path):
print("[eval-set] downloading annotations", flush=True)
z = os.path.join(args.work, "ann.zip")
with requests.get(ANN_URL, stream=True, timeout=120) as r:
with open(z, "wb") as f:
for chunk in r.iter_content(1 << 20):
f.write(chunk)
with zipfile.ZipFile(z) as zf:
with zf.open("annotations/captions_val2014.json") as src, open(ann_path, "wb") as dst:
dst.write(src.read())
os.remove(z)
ann = json.load(open(ann_path))
url_by_id = {im["id"]: im["coco_url"] for im in ann["images"]}
cap_by_id = {}
for a in ann["annotations"]:
cap_by_id.setdefault(a["image_id"], a["caption"])
items = [(url_by_id[i], cap_by_id[i]) for i in cap_by_id if i in url_by_id]
random.Random(args.seed).shuffle(items)
print(f"[eval-set] {len(items)} val2014 pairs available, target {args.n}", flush=True)
imgs, caps = [], []
pool = ThreadPoolExecutor(max_workers=args.workers)
idx, batch = 0, 64
while len(imgs) < args.n and idx < len(items):
chunk = items[idx:idx + batch]
idx += batch
results = [r for r in pool.map(lambda it: fetch_one(it, args.size), chunk) if r is not None]
for a, c in results:
imgs.append(a); caps.append(c)
if idx % (batch * 20) == 0:
print(f"[eval-set] {len(imgs)}/{args.n}", flush=True)
imgs = np.stack(imgs[:args.n])
caps = np.array(caps[:args.n], dtype=object)
np.savez(out_path, images=imgs, captions=caps)
print(f"[eval-set] DONE {imgs.shape} -> {out_path}", flush=True)
if __name__ == "__main__":
main()