How to Create Generative Pencils

How to Create Generative Pencils

As outlined in my recent article Basic Concepts of Generative Arts: Random Walks, lines resembling pencil strokes can be generated by using random walks. If you adapt the pseudocode shown there (and below again for illustrative purposes) to use a range of random walks using a more or less random variety of transparency (alpha) you’ll get lines that create generative pencils in a nutshell.

First Things First: A Random Walk

Here’s the basic pseudocode from the random walks article listed again:

Pseudocode Illustration:

# Pseudocode for a simple 1D random walk
initialize position at the origin
initialize number of steps

for step in range(number_of_steps):
# randomly choose a direction (left or right)
direction = random.choice([-1, 1])

# take a step in the chosen direction
position = position + direction

# print the current position
print(“Step:”, step+1, “Position:”, position)

Starting at the left and walking towards the right side using the pseudocode above and iterating results in the following images:

One random walk.

Basic concepts - random walks - n=1, w=1023

Five random walks.

Basic concepts - random walks - n=5, w=1023

Ten random walks.

Basic concepts - random walks - n=9, w=1023

A lot more random walks.

Basic concepts - random walks - n=30x2, w=1023

The last image looks a lot like pencil strokes and we’re going to use it as starting point to generate pencil strokes using random walks. It might need more layers with lower alpha (transparency) each but the concept goes into the right direction to create generative pencils. Please notice that all lines generated this way are wider at the end than they are at the beginning. We will come back to this later.

Creating Generative Pencils: Let’s Get Started With Some Lines

Using the concept outlined above using more than one random walks, let’s say we use n=10 as a start, and draw them from left to right starting at a certain point (x,y) = (0,y_0). If y_0 was the starting point of all random walks shown below this is the resulting image:

Basic concepts - random walks - n=9, w=1023

We can refine the sketch by using more random walks per instance (y_0), shuffling the starting point of each instance by adding a random integer to each y coordinate of the starting point. The result looks like the image below (n=10):

generative pencils in the making

n = 30:

generative pencils in the making

n=50:

generative pencils in the making

The result still looks very predictable and programmatic. When you’re drawing with pencils by hand, not every stroke is the same. There are differences in the transparency, thickness, randomness. Let’s start by adding variety in transparency, and reducing starting point variety (to create more defined lines).

With alpha (transparency) randomly assigned within n=50 random walks:

generative pencils in the making

n=100:

generative pencils in the making

All above images are based on random walks with dx = 1 pixel. Using lines with different step widths might add to the realness of creating generative pencils, so let’s give it a try and start with a step width of two pixels (2 px) while keeping the abive settings first (n=50 random walks, random alpha for each walk):

generative pencils in the making - experimenting with different step widths

Same as above, but with a smaller range of starting point samples (y0)

generative pencils in the making - experimenting with different step widths

Using a step with of three pixels (alpha range has been adjusted to [100, 205], too):

generative pencils in the making - experimenting with different step widths

Using a step width of four pixels with the settings used above:

generative pencils in the making - experimenting with different step widths

A step width of three pixels as shown above looks more realistic than four pixels, so let’s stop playing around with step width for now. The next step is to adjust the generative pencil strokes to shapes other than lines. Let’s start with some curves.

Creating Generative Pencils: Curves

Gererating curves turned out to be more difficult than just lines. When using polar coordinates to draw circles you need corresponding x and y values for each angle you’re drawing, and randomness has to be added to these two coordinates. Using polar coordinates, the images below show the first version of a generative pencil curve.

generative pencils in the making - experimenting with curvesgenerative pencils in the making - experimenting with curves

generative pencils in the making - experimenting with curvesgenerative pencils in the making - experimenting with curves

On the right side of each circle the end of the line is much wider than the beginning. This results from the addition of the random walks. The same phenomenon can already be seen when looking at the straight lines above and has been mentioned earlier. To fix this issue, we need some transformations first.

Generative Pencils Using Transformations

Using the vertical distance dy between the endpoint and the starting point the needed rotation angle phi_rot is determined:

phi_rot = sin(dy/width) 

By rotating the whole line, the random walk instance in question, by minus one times phi_rot we get aligned endpoints.

generative pencils in the making - working on details

generative pencils in the making - working on details

generative pencils in the making - working on details


This code generated surprises.

This arrticle has a corresponding Github repository.

« »