SlapStackStudio / make_builtins.py
Aluode's picture
Upload 21 files
e85709c verified
Raw
History Blame Contribute Delete
2.6 kB
#!/usr/bin/env python3
"""
Build the studio's built-in layers: the Bet-6 tractor and star, plus a boat,
drawn on NEUTRAL MID-GRAY (127,127,127). sigmoid(0) = 0.5, so a mid-gray
background needs NO atoms — the fit spends its whole budget on the object
and the layer comes out spatially compact by construction. This is the
object-layer recipe the Space UI also recommends for uploaded images.
"""
import json
import math
import numpy as np
from PIL import Image, ImageDraw
from oracle import fit_image, render_atoms
GRAY = (127, 127, 127)
def draw_tractor(px=96):
# fills ~90% of the frame: template extent IS the object extent
im = Image.new("RGB", (px, px), GRAY)
d = ImageDraw.Draw(im)
d.rectangle([10, 34, 74, 72], fill=(200, 40, 30))
d.rectangle([42, 8, 74, 34], fill=(180, 30, 25))
d.ellipse([4, 58, 42, 92], fill=(20, 20, 20))
d.ellipse([57, 66, 82, 90], fill=(25, 25, 25))
return im
def draw_star(px=96):
im = Image.new("RGB", (px, px), GRAY)
d = ImageDraw.Draw(im)
c, r1, r2 = px / 2, px * 0.47, px * 0.19
pts = []
for i in range(10):
r = r1 if i % 2 == 0 else r2
a = math.pi / 2 + i * math.pi / 5
pts.append((c + r * math.cos(a), c - r * math.sin(a)))
d.polygon(pts, fill=(240, 200, 60))
d.ellipse([c - 9, c - 9, c + 9, c + 9], fill=(200, 90, 30))
return im
def draw_boat(px=96):
im = Image.new("RGB", (px, px), GRAY)
d = ImageDraw.Draw(im)
d.polygon([(6, 64), (90, 64), (74, 88), (20, 88)], fill=(160, 80, 40))
d.rectangle([45, 6, 50, 64], fill=(230, 220, 200))
d.polygon([(50, 8), (86, 56), (50, 56)], fill=(250, 245, 225))
return im
if __name__ == "__main__":
out, stats, panels = {}, {}, []
for name, img, seed in [("tractor", draw_tractor(), 0),
("star", draw_star(), 1),
("boat", draw_boat(), 3)]:
atoms, ledger = fit_image(img, n_atoms=140, iters=400, seed=seed)
r = np.hypot(atoms[:, 0], atoms[:, 1])
stats[name] = {"atoms": len(atoms),
"psnr_db": round(ledger["final_psnr_db"], 1),
"radius_p95": round(float(np.percentile(r, 95)), 2)}
out[name] = np.asarray(atoms).round(5).tolist()
panels.append((render_atoms(np.asarray(atoms), 160)
.transpose(1, 2, 0) * 255).astype(np.uint8))
print(name, stats[name])
json.dump(out, open("studio/builtins.json", "w"))
Image.fromarray(np.concatenate(panels, 1)).save("builtins_preview.png")
print("wrote studio/builtins.json")