iterative image reconstruction using random cubic bézier strokes, accelerated on metal
showcase#
NOTE
images used here are all under open access by The Met
same input & different seeds → different reconstructions → simple animation:
build#
cargo build -r
usage#
splined: iterative image reconstruction with random cubic bézier strokes (metal-accelerated)
usage: splined <input> [args]
args:
-n, --number <u32> max splines to draw (default: (w*h)^0.7)
-b, --batch <u32> batch size per gpu step (default: 32)
-s, --seed <u64> rng seed (default: 0)
--max-gpu <f32> max gpu usage in (0, 1] (default: 1.0)
-l, --log <0..3> logging level (default: 1)
-o, --output <path> output file or dir (default: output.png)
-c, --current <path> current canvas image to resume from (single-file only)
--nth <u32> save every nth accepted stroke (uses -o as dir)
--bg <avg|r,g,b> initial canvas color (default: avg)
-a, --alpha <f32> stroke alpha in [0, 1] (default: 1)
--min-accept-ratio <f32> stagnant if accepted < batch*ratio (default: 0.02)
--max-stagnant-batches <u32> stop after this many stagnant batches (default: 10)
input:
- file: writes one image to -o/--output (default: output.png)
- dir: -o/--output must be a dir; mirrors input tree under it
- --nth: saves frames to output dir every nth accepted stroke; also writes final.png
examples:
splined in.png -o out.png
splined in.png -n 5000 -b 64 -s 42 -o out.png
splined in.png --nth 50 -o frames/
splined images/ -o results/ -n 5000 -b 64 -s 42 --nth 50
algorithm#
- convert input to oklab color space
- initialize canvas to image average (or
--bg) - repeat until target stroke count or convergence:
- sample batch of random cubic béziers (4 control points, uniform over image)
- rasterize each curve to coverage mask
- set stroke color to coverage-weighted mean of target pixels
- accept curves that strictly reduce squared oklab error (Δε² < 0)
- commit accepted strokes to canvas
- export final canvas
reference#
- Geometrize: a desktop app that geometrizes images into geometric primitives
todo#
- (better) antialiasing algorithm for drawing cubic bézier strokes
- support other gpu backends (e.g., wasm)