Skip to content
create or transform numpy images from the command line
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Build Status GitHub license

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 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()

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()

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()

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()

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()

You can’t perform that action at this time.