Photographs of block prints, each print 8cm square. They are made using 3d printed blocks. The designs are generated using code written in Python.
These final two images show some of the inked blocks and a print in process with a jig to guid the align the blocks.
Visualization of earthquakes in the San Francisco Bay Area. Grey value indicates the magnitude of the most recent quake (top), all quakes in the past 24 hrs (bottom), and max quake each day for the past 30 days (middle).
Made using a Raspberry Pi Zero W and a Pimoroni Inky wHAT, mounted in an 8 inch square frame.
A simple automaton toy based on a design in the book Making Simple Automata by Robert Race.
These drawings were extracted from images using a combination of OpenCV and a genetic algorithm.
First, OpenCV is used to find contour lines and canny edges in the images. On the left are all the lines found this way (typically hundreds of lines) that have been post-processed a bit to smooth longer lines.
On the right are 20 lines selected by the genetic algorithm. The algorithm generates 100 drawings, each with a different set of lines from the drawing on the left. It then automatically evaluates the fitness of each drawing and creates a new generation of 100 drawing, selecting characteristics more often from the highest rated drawings and tossing in some random mutations.
The goal is to capture the essence of the original image in just a few vector lines so that a drawing robot can efficiently recreate it. Below are more examples.
The effects of mutations in one generation of spirographs. Choosing only one graph to survive from the previous generation (not a natural thing to do) results in 36 offspring from the one graph. It is an good way to check the impacts of mutations in the genetic algorithm and has an interesting outcome. The parent graph is below.
This Spirograph algorithm is not a strict interpretation of the physical Spirograph device but it generates some very similar and interesting results. The basic algorithm is to blend three circular equations together. Specifically, for values of i from 0 to 2 pi, an x and a y value are generated with :
x = r1 * cos(nr1 * i + o1) + r2 * cos(nr2 * i + o2) + r3 * cos(nr3 * i + o3); y = r1 * sin(nr1 * i + o1) + r2 * sin(nr2 * i + o2) + r3 * sin(nr3 * i + o3);
In many ways, this is like having three lines of length (set as r1, r2, and r3) being placed end to end with each one rotated a given number of times (set as nr1, nr2, and nr3). Each of the rotations also can be offset (set by o1, o2, o3).
Two different graphs can be drawn in this way and each of those graphs can be duplicated by changing the number of iterations (o iterations would hide graph). Each iteration can be offset by an angle or have its radius scaled.
Building on the previous waves study, this sketch creates it’s own image from three dimensional Perlin noise. For each frame, an image is generated and variations in the brightness are used to vertically offset the horizontal lines, forming waves.
The running sketch (below) shows a frame of the noise and the waves below.