e-os-v6 / scripts /eval_os6.py
KillerBoss's picture
E-OS v0.6: Liquid Glass — Formen rein, Glas+Wasser raus (NPU 3.11ms)
da43581 verified
Raw History Blame Contribute Delete
3.56 kB
# E-OS v6 — eval: PSNR on fresh val scenes @ app-res + preview grids.
import os, sys, json, math
import numpy as np
import torch
sys.path.insert(0, "/home/z/my-project/scripts/os6")
from os6_models import FrameGenerator
from os6_draw import render_frame, rasterize_hint, build_state
from os6_spec import lay_home, lay_random, CARD, CIRCLE
from PIL import Image
CKPT = sys.argv[1] if len(sys.argv) > 1 else \
"/home/z/my-project/checkpoints6/gen_ckpt_final.pt"
OUT = "/home/z/my-project/download/e-os-v6/eval"
os.makedirs(OUT, exist_ok=True)
m = FrameGenerator()
ck = torch.load(CKPT, map_location="cpu", weights_only=False)
m.load_state_dict(ck["m"])
m.eval()
print("ckpt step %s best %s" % (ck.get("step"), ck.get("best")))
rng = np.random.default_rng(999)
def run(shapes, theme, day, shimmer, ripples, pressed=0):
hint = rasterize_hint(shapes, ripples, 256, 544)
st = build_state(theme, shimmer, day, pressed)
with torch.no_grad():
p = m(torch.from_numpy(hint).unsqueeze(0),
torch.from_numpy(st).unsqueeze(0))
return p[0].permute(1, 2, 0).numpy()
def gt(shapes, theme, day, shimmer, ripples, pressed=0):
return render_frame(shapes, theme, day, shimmer, ripples, pressed) / 255.0
# ---- 40 fresh val scenes ----
ps = []
samples = []
for k in range(40):
shapes = (lay_home if k % 3 == 0 else
lay_random if k % 3 == 1 else
(lay_home if k % 2 else lay_random))(rng)
shapes.sort(key=lambda s: s.get("z", 0))
theme = int(rng.integers(0, 4))
day = float(rng.uniform(0.05, 0.95))
shimmer = float(rng.uniform(0, 1))
rip = (float(rng.uniform(0.15, 0.85)), float(rng.uniform(0.15, 0.85)),
float(rng.uniform(0.05, 0.9))) if k % 4 != 3 else None
args = (shapes, theme, day, shimmer, [rip] if rip else [])
g = gt(*args)
p = np.clip(run(*args), 0, 1)
mse = ((g - p) ** 2).mean()
ps.append(10 * math.log10(1.0 / max(1e-8, mse)))
if k < 6:
samples.append((shapes, theme, rip, g, p))
ps = np.array(ps)
print("PSNR mean %.2f median %.2f (40 scenes @ 512x1088)" %
(ps.mean(), np.median(ps)))
# ---- preview grid: GT | NPU-Output (6 rows) ----
rows = []
for (shapes, theme, rip, g, p) in samples:
rows.append(np.concatenate([g, p], axis=1))
grid = (np.concatenate(rows, axis=0) * 255).astype(np.uint8)
Image.fromarray(grid).save(os.path.join(OUT, "eval_gt_vs_npu.png"))
# ---- GENERALIZATION PROOF: edited layout the net never saw ----
sh = lay_home(rng)
sh[0] = dict(sh[0], x0=100, x1=430, y0=90, y1=330) # card moved/resized
sh.append(dict(t=CIRCLE, x0=60, y0=430, x1=150, y1=520, z=9)) # extra circle
sh.append(dict(t=CARD, x0=210, y0=560, x1=470, y1=700, z=8)) # extra card
sh.sort(key=lambda s: s.get("z", 0))
theme = 1
rip = (0.4, 0.5, 0.35)
ge = gt(sh, theme, 0.5, 0.4, [rip])
pe = np.clip(run(sh, theme, 0.5, 0.4, [rip]), 0, 1)
mse = ((ge - pe) ** 2).mean()
psnr_edit = 10 * math.log10(1.0 / max(1e-8, mse))
hint_e = rasterize_hint(sh, [rip], 256, 544)
wire = np.stack([hint_e[0]] * 3, -1)
proof = (np.concatenate([ge, pe], axis=1) * 255).astype(np.uint8)
Image.fromarray(proof).save(os.path.join(OUT, "eval_generalization.png"))
print("EDITED-LAYOUT PSNR %.2f dB (proof of generalization)" % psnr_edit)
json.dump(dict(psnr_mean=float(ps.mean()), psnr_median=float(np.median(ps)),
psnr_edited_layout=float(psnr_edit), n=40, app_res=[512, 1088],
ckpt_step=ck.get("step")),
open(os.path.join(OUT, "eval_metrics.json"), "w"), indent=1)
print("EVAL DONE")