In the digital age, we have grown used to the fact that it is possible to make a perfect copy of something. Since all digital data is just a series of bits, we don’t have to worry about imprecision, and we can employ all kinds of fancy error correction to make sure our copies are identical to the source material. It’s important to know that despite this, data isn’t always copied exactly: random noise can flip bits, and we often throw away information in the name of compression. Of course, this isn’t limited to digital information; legends, languages and memories evolve over time.

All this to say that if I wanted N pictures of the same circle, I could draw one and copy it N-1 times. This is obviously no fun, so I decided to copy them all by hand, and examine what kinds of error are introduced, and how they evolve.

Here’s my starting circle, drawn freehand with a mouse (freemouse?):

In retrospect, I probably should have started from a perfect circle, but this isn’t too bad

When copying, I would follow these two rules:

  1. Draw in a single stroke, without stopping or lifting the mouse
  2. Reproduce imperfections as closely as possible

When I first started doing this, I was thinking about ensō, the circular brushstrokes made by Zen Buddhists with the intent of allowing the body to create without the mind’s oversight (…I think). I guess I shouldn’t be surprised that my circles were not ensō, and that the mental effort of attempting repeated pixel-perfect tracing left me neither Zen nor zen.

Anyway, after 100 iterations, here’s how my circle evolved:

I don’t know about you, but I find this kind of mesmerising to watch. Here are a few observations that I’ll try to quantify below:

  1. My circle does not stay a circle for long. It only took 5 iterations for the start and end points to not line up, causing them to flail around for the next 95.
  2. The circle drifts upwards and to the right, almost hitting the rightmost edge of the frame. This doesn’t show up particularly well on the white background, but the line is only a few pixels away from the edge of the image in the final frames.
  3. The circle gets a lot more squiggly over time. This in itself shouldn’t be surprising, but the effect after 100 iterations is surprisingly large. In particular, we see fissures opening up and starting to wiggle around. Some of these (like the one at 2 o’ clock) are mouse slips, but most aren’t.
  4. Perhaps it’s just me, but the South-West and North-East quadrants of the circle seem much more badly behaved than the other two. Perhaps this says something about my mouse control?

To do anything quantitative with these circles, we’d better convert the images to something more pliable. Since I drew the circles with a stroke width of 5 pixels, it makes sense to skeletonize the line – i.e. trim it down until it is only one pixel thick. Luckily, there seem to be several Python libraries which have implemented this (I used skimage).

Once skeletonized, we can then fit a circle to the line so we can look at the deviations from circularity later I did this by placing the circle’s centre at the mean \(x\) and \(y\) coordinates of the line’s pixels, and set its radius to be the mean distance of pixels from the centre. I’m not convinced this is the best fitting circle, but it seems to work fine.

Finally, I can then unwrap the line to express the pixel’s locations in polar coordinates, centred on the circle:

I originally wanted to parametrise things along the path length of the circle, but this got messy fast. The main issue is that when skeletonized, some particularly spiky bits of the line end up as spurs off the main circle (you can see a few tiny spurs in panel 2 of the picture above). This makes counting length along the circle difficult, so I switched to just using angle as a coordinate.

OK, now we’ve got some useable data, let’s take a look at some of the points I listed earlier. Looking at the animation, it’s obvious that the circle gets squigglier over time. One way to describe this would be to look at the circle’s circumference as a function of time:

Well it’s definitely increasing, and showing a possible slowing after about 60 iterations. It’s difficult to get any more information out of just the circumference, so let’s look at something a bit more complex.

Since the squiggles I keep referring to can be thought of as waves distorting the shape of the circle, it makes sense to look at the Fourier series of the unwrapped points. We’ll consider a range of different wavelengths, and the coefficients of the resulting Fourier series will show what fraction of the distortion arises from waves with that particular wavelength.

So, for example, if the line were quite smooth but distorted into an ellipse, we would see large coefficients for long-wavelength disturbances, and low coefficients for the short-wavelength ones. On the other hand, if the shape of the circle were roughly right, but with lots of small deviations, the long-wavelength coefficients would be small, and the short-wavelength coefficients would be larger. Since my circles are basically neither, so should see perturbations (i.e. high coefficients) at a range of wavelengths. By the way, from now on, I’ll use ‘order’ to refer to the scale of the perturbations – this is the inverse of wavelength, so ‘high-order’ is ‘low-wavelength’ and vice versa.

Here are the results of the Fourier analysis for all 101 frames. In each image, the drawn circle is on the left, with its circle of (arguably-)best fit superimposed. Top right is the unwrapped points plotted by radius against angle, while plot below it shows the amplitude of the Fourier modes, up to \(n = 40\).

We can see that the power in each mode starts out low, but tends to grow over time (which is what we should expect). Other than that, there’s not a huge amount that I can deduce from these plots – basically just:

  1. The fact that the amplitude of the 1st-order component is not zero means that the circle’s position and/or radius are not optimal. You can also see this in the unwrapped plot in the top-right, where the whole line occasionally shifts and warps between frames – in theory, most of the line should stay still. This might be due to sections where the line loops back on itself (i.e. multiple values of the radius for a given angle), which make it hard to define what the circle of best fit even is.
  2. The 4th-order component is consistently quite large. This has the effect of making the circle more square – you can see this particularly on the right-hand side towards the end of the animation. I’m not sure there’s any particular significance here; with 40 components, the odds of one being particularly high for a while just due to random chance are pretty good.
  3. Besides that, there aren’t really any standout wavelengths. When drawing the circles, I wondered whether the drawing generally introduces errors with a particular length scale the fact that the amplitudes smoothly decrease for higher-order components shows that this isn’t the case.

OK – that’s definitely enough Fourier stuff for now. Let’s take a look at something else I spotted: the fact that big perturbations tend to appear in the bottom-left and top-right quadrants of the circle, while the other two stay comparatively smooth.

Now we could look at this by dividing the circle into its quadrants and repeating the Fourier analysis, but I’ve thought of a more interesting way: if we break the circle down into line segments, and look at the distribution of angles of those segments, differences in bumpiness in each quadrant should be visible as a surplus of lines pointing in a certain direction.

To show what I mean, here’s a simplified example using an octagon, and then showing what happens when you add a bump in a particular quadrant:

Here, ‘angle’ is measured between the line segment and vertical; since the lines aren’t directed, the graph repeats at an offset of 180\(^\circ\) (as each segment is counted twice). I feel like the graphs on the right are easier to interpret wrapped back onto a circle, so let’s do that, and see how they evolve over time:

(I’ve changed the lines into bars, since they’re a bit easier to follow when they’re jumping around)

The units of the plot’s radial axis are normalised to the average size of the bars for my starting circle. The growth of the bars over time reflects the growing circumference of the circles over time. While it’s nowhere near as clear cut as the octagon example, you can see a clear drift from a circle to a NE-SW pointing ellipse as the circle evolves. Here’s just that last frame for comparison:

This is pretty good evidence for the badly-behaved vs well-behaved quadrants idea. I won’t sell too much on the cause, but I suspect it’s to do with the fact that I’m right-handed. So if I’m more accurate with side-to-side motion of my hand (as opposed to forward-and-back), we’d expect to see more errors in regions where the line is perpendicular to the unreliable forward-and-back axis. If this were the case, then these slips would likely be closer to the North-South axis instead of the East-West, since my arm is aligned roughly SSW-NNE when using the mouse.

You can also see that the bars pointing East-West and North-South are usually pretty prominent, implying a bias toward drawing horizontal or vertical lines over diagonals. It’s hard to say whether this is caused by my perception, my mouse movement, or just representative of the fact that the drawing consists of pixels in a grid.

I hope this has been a useful primer on what to expect if you manually trace the same circle 100 times. If uniformity is what you’re after, you’ll need steadier hands than mine (or I could just introduce you to my friends Ctrl+C and Ctrl+V).

Leave a Reply

Your email address will not be published. Required fields are marked *