This tool can manipulate or generate large swaths of image data stored in numpy files. It's a sandbox for implementing operations in C++ that are either slow or non-existent in pillow, scikit-image, or the SciPy ecosystem.
Since it's just a command line tool, it doesn't contain any
FFI messiness. Feel free to contribute
by adding your own command, but keep it simple! Add a cc
file to the commands
folder and make a pull request.
This is just a toy library. For serious C++ applications you might want to look at xtensor (which can read / write npy files) and xtensor-io. To achieve huge speed-ups with numpy, see numba.
Build and run clumpy.
cmake -H. -B.release -GNinja && cmake --build .release
alias clumpy=$PWD/.release/clumpy
clumpy help
Generate two octaves of simplex noise and combine them.
clumpy generate_simplex 500x250 0.5 16.0 0 noise1.npy
clumpy generate_simplex 500x250 1.0 8.0 0 noise2.npy
python <<EOL
import numpy as np; from PIL import Image
noise1, noise2 = np.load("noise1.npy"), np.load("noise2.npy")
result = np.clip(np.abs(noise1 + noise2), 0, 1)
Image.fromarray(np.uint8(result * 255), "L").show()
EOL
Create a distance field with a random shape.
clumpy generate_dshapes 500x250 1 0 shapes.npy
clumpy visualize_sdf shapes.npy rgb shapeviz.npy
python <<EOL
import numpy as np; from PIL import Image
Image.fromarray(np.load('shapeviz.npy'), 'RGB').show()
EOL
Create a 2x2 atlas of distance fields, each with 5 random shapes.
for i in {1..4}; do clumpy generate_dshapes 250x125 5 $i shapes$i.npy; done
for i in {1..4}; do clumpy visualize_sdf shapes$i.npy shapes$i.npy; done
python <<EOL
import numpy as np; from PIL import Image
a, b, c, d = (np.load('shapes{}.npy'.format(i)) for i in [1,2,3,4])
img = np.vstack(((np.hstack((a,b)), np.hstack((c,d)))))
Image.fromarray(img, 'RGB').show()
EOL
Create a nice distribution of ~20k points, cull points that overlap certain areas, and plot them. Do all this in less than a second and use only one thread.
clumpy bridson_points 500x250 2 0 coords.npy
clumpy generate_dshapes 500x250 1 0 shapes.npy
clumpy cull_points coords.npy shapes.npy culled.npy
clumpy splat_points culled.npy 500x250 u8disk 1 1.0 splats.npy
python <<EOL
import numpy as np; from PIL import Image
Image.fromarray(np.load("splats.npy"), "L").show()
EOL
You may wish to invoke clumpy from within Python using os.system
or subprocess.Popen
.
Here's an example that generates 240 frames of an advection animation with ~12k points, then brightens up the last frame and displays it. This entire script takes about 1 second to execute and uses only one core (3.1 GHz Intel Core i7).
from numpy import load
from PIL import Image
from os import system
def clumpy(cmd):
result = system('./clumpy ' + cmd)
if result: raise Exception("clumpy failed with: " + cmd)
clumpy('generate_simplex 1000x500 1.0 8.0 0 potential.npy')
clumpy('curl_2d potential.npy velocity.npy')
clumpy('bridson_points 1000x500 5 0 pts.npy')
clumpy('advect_points pts.npy velocity.npy 30 1 0.95 240 anim.npy')
Image.fromarray(load("000anim.npy"), "L").point(lambda p: p * 2).show()
Create a visualization of pendulum's phase space.
clumpy pendulum_phase 4000x2000 0.9 2 5 field.npy
clumpy bridson_points 4000x2000 20 0 pts.npy
clumpy advect_points pts.npy field.npy 2.5 5 0.99 400 phase.npy