File size: 2,600 Bytes
e85709c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/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")