All Posts: By Date

  • Radial Point Squeezing - If we have a bunch of points that are uniformly spaced, we can squeeze them radially so that they yield a halftoned image. For example, if we have points distributed along a phyllotactic spiral, we can squeeze them to get a skull: How does this work? Math math math. As usual, we want to match […]
  • Approximate TSP Paths - Let’s say you have lots of points, and you want to visit them rapidly. And you’re too lazy to solve the full TSP. How well do different approximations work? That is, how far would you have to travel to visit each point? Let’s say you have N points that are uniformly randomly distributed in a […]
  • Scribble Art - Let’s scribble! There are other papers that have used scribbling for halftoning images, but I want to add a bit more math. A simple model is to have a circle that travels along a base curve. We can parameterize this as: . To use this for halftoning, we should know the curve length (per period) […]
  • HalftonePAL - HalftonePAL is a program written in Processing that lets you make halftoned versions of your images using circles, dots, and lines. You can change the size of the shapes, which pattern to use, switch between black or white paper (and the opposite ink), and more! It can save the output as SVG, JPG, or TXT […]
  • Approximate Circle Packing - I’d like to be able to have a region that is densely packed with non-overlapping circles, whose sizes vary spatially in a pre-defined way. There are lots of resources for Poisson-disk sampling, but that doesn’t result in snugly packed circles. Time to do some tinkering! Random search The laziest way to do this: try to […]
  • Renaming Cities Based on their Coordinates - While driving through Normandy, I was struck by the wackiness of a lot of the local place names. This is amplified by the large linguistic flow through the area, and local dialects that I’m not familiar with, but still felt very silly. For example: Looking at names like these, I figured that I could make […]
  • New Image via Cut-and-Paste - Previously, (1, 2) I’ve chopped one picture into square sections to make a new image. This time, I want to take freeform sections from a larger image to make a smaller one. This is basically like taking scissors to a magazine, then putting together the pieces to make a new picture. Let’s call the magazine […]
  • Lithophane-based Hidden Images - I received a comment with a great idea: try to hide images in pairs of lithophanes! Lithophanes are thin sheets of an opaque and translucent material with varying thickness that display an image when held up to light. The image is bright where the material is thin, and dark where the material is thick. Previously, […]
  • Four Images from Two Transparencies - Previously, I used polarized sheets to generate images. That’s too complicated to physically make, so it’s time to try something else. How about just two transparent films with black marks? Then we can try to encode four images that are revealed by overlapping the two, and rotating the top film. This sort of rotation problem […]
  • Polarization Images - Have you ever played with polarized films? If they’re aligned, they look transparent. If they-re misaligned by 90 degrees, they become opaque. Let’s use this to make pictures! The intensity of transmission is governed by Malus’s Law, which says that the intensity is , where is the misalignment of the two films. Now how can […]
  • More Fourier Noise Contours - Previously, I used single-frequency Fourier noise to do some halftoning. This time, I’ll use broad-frequency noise. I’ll filter 2D white noise with a gaussian with standard deviation . This reduces the high-frequency content. Let’s call the filtered noise , and the gradient-scaled version. Skipping all the tedious probability work, the pdf of the gradient-scaled noise […]
  • Estimating Zero-Contour Length of Fourier Noise - One way to do stochastic halftoning is to draw contours of noise functions. For example, you can make 2D single-frequency Fourier noise, and draw a contour wherever the noise crosses the zero-level. If you do this with wavelength L, over an area of A, the total arc length turns out to be very nearly 2.2*A/L. […]
  • Checkerboard Distortion Halftoning - In a previous post, I deformed a grid of lines to halftone an image. I wanted to do the same thing with a checkerboard, but I figured that it would be similarly difficult and would require optimization. So I used the same optimization framework with a checkerboard, applied it to a brightness ramp, and found: […]
  • Grid Distortion Halftoning - Imagine that we have a screen door, and we want to push around the wires to make an image. It’s not a simple problem! There’s a fixed number of wires in each direction, so how do we properly distribute them? Let’s define a pair of phase maps for x and y, and . We’ll draw […]
  • Joukowski Airfoil Performance - The Joukowski transformation is a great way to study basic airfoils using potential flow. It gives a nice way to derive the Kutta condition, as well as the classic lift slope . But in all those demonstrations, I never saw the lift and drag curves of the Joukowski airfoil! Luckily, I have XFOIL to remedy […]
  • Color Mapping: Swapping Image Palettes - Sometimes you want one picture to have the color scheme of another. This is called color mapping or transfer. When I was making the rearranged images, I was concerned that I would get bad matches if I didn’t make sure the images were similar enough. It was helpful to ensure that their brightness histograms matched, […]
  • Spiral Halftoning - Let’s halftone an image with some overlapping wiggly spirals! I want to draw N lines, spiraling out from the center of the image, and have them each slightly offset. With the proper offset, this will create the (approximately) proper darkness. With image darkness k, line width w, and line spacing L, we can get a […]
  • Geometrically Approximating Pi - Archimedes found good estimates of pi by computing the perimeter of regular polygons that fit snugly inside and outside a circle. I’d like to take this basic approach and add some more modern twists. I say more modern, but I don’t mean cutting-edge. Taylor series are from the 1700s CE, compared to Archimedes living in […]
  • The Sleekest Airfoil - What does a minimum force airfoil look like? I basically want to make a fairing that minimizes the total force over the range of 0-5 degrees. This mostly means reducing the lift generated at non-zero angles of attack, while keeping the drag manageable. Minimizing lift on an airfoil feels oddly perverse. I suppose that’s why […]
  • Improving the NACA 0015 Airfoil - The four-digit NACA airfoil is perfectly decent, which is a bit surprising considering it was first published way back in 1933. Since it was designed before computers, I’m sure that it could be improved. The general form of the thickness equation is: This does not provide the proper thickness, but ensures a rounded leading edge […]
  • Airfoils with Circular Leading Edges - Airfoils are generally thickest somewhere around the middle. The classic NACA four-digit airfoils are thickest at 30% of the chord, and laminar flow airfoils are thicker around the 50% mark. Let’s throw out the received wisdom and make some airfoils that are thickest close to the front. Rather than working with a lifting body, let’s […]
  • Conformal Mapping: Point Vortex Near a Corner - I wanted to know what a point vortex would do near a corner with an arbitrary angle. Time to dust off the complex analysis! A really useful summary of using complex analysis to model potential flow is here. I will use the method of images to ensure that there is no flow through the wall, […]
  • Advection-Diffusion of Ink - I want to have the ink on a photo clump together, leading to a black and white image. This is a sort of flow, so my first thought is to take a look at the advection-diffusion equation. Let’s say that the ink distribution across an image is , the diffusion factor is , and the […]
  • Rearrange a Picture into Itself - Previously, I took one photo and rearranged its squares to make a version of another photo. How about a sillier version, where you use one image to re-make itself? The simple answer is to just keep every square in its original place, but that’s no fun at all. Instead, we can add the requirement that […]
  • Text Processing of The Dresden Files: Word2Vec - In my previous post, I did some statistical analyses of the Dresden Files novels. Now I want to do some fancy stuff with vectors. Word2Vec is a method for turning a bunch of words in text into related vectors, as the name implies. Using a shallow neural network, it represents finds vectors such that words […]
  • Text Processing of The Dresden Files: Statistics - The Dresden Files is a series of very fun books by Jim Butcher, with a wizard detective getting into trouble and saving the world and all that. I’ve wanted do do some Natural Language Processing (NLP) on a body of text, and with fifteen novels so far (two more later this year!), this is a […]
  • Photomosaics, with repetition - Previously, I recreated an image by rearranging squares of another image. Typical photomosaics allow for repeated use of tiles, so I’ll try that for comparison. I’ll still allow rotation, as it helps the edges so much. The image on the left is the result: It works, but isn’t great. The repeated use of certain tiles […]
  • Rearrange a picture into another - I want to take one image, chop it into square tiles, and use those to make an approximation of another image. When the images are the same size, the simplest version is identical to the assignment problem. This is a classical optimization problem that has been well studied. In those terms, there is a “cost” […]
  • Image Approximation with Constant-Color Shapes - I want to approximate images using constant-color shapes. Given a shape, how do we choose where to put it? We have the original image, , and the approximate image, . I want to place a shape, , with area on such that it improves the approximation. First, define the average color under the shape (which […]
  • Line Integral Convolution - Line integral convolution, or LIC, is a nice way to get a sense of the directions of a flow field. By averaging a noisy image along sections of streamlines, you get some nice streaks. Look at this example, applied to the flow around a spinning cylinder: There are a couple main parameters to tweak: the […]
  • Evenly Spaced Streamlines - There’s a whole body of literature out there for illustrating vector fields. One topic is ‘evenly spaced streamlines’: lines that follow a direction field, and don’t get too close to each other. How do we do this? From a starting point, use the midpoint method to figure out the position of the next point. If […]
  • Angled Splitulate - I’ve refined image approximations with rectangles and triangles. Let’s try with splitting regions into two with a straight line, and filling each part with the average color that they’re covering. This is the same basic idea as the rectangles, except that now the line can be at any angle, rather than just vertical or horizontal. […]
  • Halftoning with Reaction-Diffusion Patterns - The easiest way to make a reaction-diffusion pattern involves two blurs and a comparison. It doesn’t give the full fancy dynamics of other approaches, but it works well for halftoning. This simple method avoids differential equations, and works with just image filtering. At each step, the activation chemical spreads with radius , and the inhibition […]
  • Image Triangulation: Voronoi Method - Voronoi diagrams are great, so let’s use them to stylize images. First, let’s just throw a bunch of points on an image, and compute the Voronoi diagram. Then for each cell, we fill it with the average or median color within: Hmm. That’s not great. It doesn’t pay attention to the edges at all, and […]
  • Image Triangulation - Previously, I split an image into a bunch of rectangles. What about using triangles? This requires more thought, as it’s a little trickier to divide up the plane using triangles. The natural solution is to keep track of a set of vertices, then use a Delaunay triangulation to split up the image. First, let’s do […]
  • Image Quadrangulation - I want to represent an image with a bunch of rectangles. Let’s say that each shape has constant color, as a start. First, fill a rectangle with the average color that it covers. That’s the initial approximation. Wherever the error in a rectangle (between the original image and the approximation) is too big, subdivide that […]
  • Pulled String Art - Check out this art style! They dip a string in ink, lay it on a page, fold the page over, and pull the string out of the bottom. It leaves nice floral patterns with the ink, and is pleasantly complex and organic. I wanted to mimic this style algorithmically, so the first thing that I […]
  • Solving Tic Tac Toe, Making it Interesting? - Tic Tac Toe (TTT) is a minimally complicated game, so it is relatively easy to find all possible moves and see which will lead you to a victory, tie, or loss. I’ve never solved TTT before, so I threw together some code to do that! Solving Tic Tac Toe Without removing boards that are effectively […]
  • Modfied Voronoi Diagrams and Stippling - Stippling is pretty neat. Draw a bunch of points and get an image? I like it. This post works up from basic Voronoi diagrams to anisotropic stippling with multiple dot sizes. I’ll stick to 2D for all this, since I like drawing pictures. Voronoi Diagrams A Voronoi diagram divides up the plane into regions that […]
  • Messing with Image Classification - There’s so much buzz about image recognition these days, I felt like I wanted to join in. Long ago, I saw an excellent project by Tom White in which he used image classification to generate abstract drawings reminiscent of an object. Basically, he made a feedback loop between an image generator and the image classifier, […]
  • Tools for line drawings - Here’s a collection of useful tools for making line drawings with a pen plotter. I assume that the drawing is composed of lines, where each one is defined as a series of points connected with straight line segments. A point can be considered a degenerate line, with no segments. Bounding box intersection If you have […]
  • FFT-based Line Smoothing - With a jagged or noisy signal, Fourier filtering can be pretty useful for cleaning up the unwanted noise. Line drawings can be considered signals just as easily as time-varying signals, so let’s get ready for some Fourier transforms! The basic idea of smoothing (with length scale L) a polyline with a Fourier transform: Re-sample along […]
  • Chaikin-like Smoothing, Through Vertices - The standard Chaikin smoothing is a corner-cutting algorithm, which leads to nice results, but it no longer passes through the vertices of the original path. In cases where we trust the vertices more than the segments, what are we to do? Well, invent a new method, of course. Ideally, I want to give this method […]
  • Traveling Salesman Problems and Variants - If you’re drawing these lines on a computer, there is no need to sort the lines cleverly. However, if you plan to use a machine to draw them, you want to minimize the total time that the machine is moving. If you don’t optimize the line-drawing order, you could spent a lot of extra time […]
  • Ph.D. Research: Problem Solving - A PhD is an exercise in learning to define and solve problems. This post will describe some of those problems and how I addressed them. I would have liked to see this sort of post back then, and hopefully this will give some idea of the process. This is, of course, very focused on experimental […]
  • Image Orientation - I want to get a sense of the local angle of features in an image. This is a tall order at times, and isn’t even clearly defined. Do you want to follow the local gradient of the image? Be parallel to lines? We’ll try various methods and see what works. I’ll show a comparison of […]
  • Equal Area Map Projections - I’m most interested in making equal-area projections of spheres onto different shapes. For example, turning a spherical map of Earth into regular polyhedra. I’ll talk about the math I’ve used for these, and show some of the results. And exellent reference for map projections is Map Projections: A Working Manual. I’ll be using this equirectangular […]
  • Not Classic Dithering on a Grid - I wanted to try some different grid-based dithering methods, so here we go: quadtree subdivisions, dither matrices, dithering along space-filling curves, and a hill-climbing optimization. Quadtree Dithering This uses recursive subdivision to distribute blackness in the image. The general idea is to make sure that each subdivision contains an integer number of black dots, and […]
  • Dithering on Grids - Dithering takes an image and tries to represent it with a series of uniformly sized elements: pixels for digital images, or dots of ink for a pen plotter. I’ll assume that the background is white, and ink is black. To get an approximation of continuous gray levels, only some of the possible points will be […]
  • Eikonal Stripes - The Eikonal equation is an approximation used in solving wave equations, and it turns out to also be good for stripes! We try to make a phase map, (), based on the brightness of the image (), with , where is the minimum wavelength desired. This can be approximately solved with the gray-weighted distance transform, […]
  • Generative Lumber - Wood is a curious material. You can see its history in a slice, due to its imperfect rings. I wanted to recreate a simplified version of this. First, I created a skeleton of line segments to represent the trunk and branches. From these, I created a 3D distance map. If I plotted the contours of […]
  • Splash! - I’ve been wanting to generate patterns that look like splashes. It’s tempting to simulate attractive particles flying through the air, and then see where they intersect the ground, but that’s more intensive than is necessary. Instead, I pretended to throw some metaballs at the ground: Those look like splashes to me! To generate these required […]
  • Ambiguous Digits 2: Generative Adversarial Network - I’m still interested in making ambiguous-looking numbers. Last time, I trained a neural network to identify pictures of handwritten numbers, and then used that to create images that look like one digit when right-side-up, and a different one when upside-down. This time, I’ll use a Generative Adversarial Network (GAN). A GAN is a pair of […]
  • Ambiguous Digits 1: Classification-based - I wanted to create a set of numbers that look like different numbers when they’re rotated 180°, but I especially wanted a computer to do it for me. I’ve been using TensorFlow recently, and that sounded like a good place to start. There is a standard data set used for number identification, the MNIST database, […]
  • Proper Orthogonal Decomposition - Time for some competing acronyms. Fluids people like to call this technique Proper Orthogonal Decomposition (POD), statisticians call it Principal Component Analysis (PCA), and so on and so on. Whatever you want to call it, it’s basically an eigenvector decomposition of the data you toss into it. That means that it optimally splits the data […]
  • Processing Vector Fields - In my PhD research, I had to deal with a lot of data.  Particularly with movies of particles moving around in water. These movies were processed, via Particle Image Velocimetry, to give vector fields of the velocity in the flow.  For an example, here’s some rough data that I took of a cylinder in flow, […]
  • Oriented Noise Patterns - Smoothly varying patterns can be generated via inverse Fourier transforms (previously). These can be skewed to have noise at particular wavelengths and angles. Generating several of these fields at different angles then meshing them together (dependent on the image’s local orientation) gives a spatially-varying pattern of noise, which I’ve used for halftoning. Here’s a set […]
  • Simple cross-hatching - The simplest type of cross-hatching is to have a set number of hatching angles and constant spacing. The header image shows the result with 16 different angles. This can be extended to use other sorts of patterns. For example, here are orthogonal circular and radial lines: The number of overlapping lines was computed for each […]
  • Polygon Subdivision - I’ve mentioned that subdividing an image is useful for putting patterns within the divisions. This method uses the outline of the subdivisions to provide the darkness. The way this is done is to repeatedly break a shape into two parts: ensuring that the ratio of perimeter to blackness within is equal on both sides.  From […]
  • Space Colonization - I saw an interesting algorithm for creating branching veiny patterns called the Space Colonization Algorithm. Of course, I had to apply it to halftoning. Basically, the veins grow in the direction of their nearest destination points. Once the vein is close enough to a destination point, that destination is removed from the list, and growth […]
  • Scaly Rendering - I’ve been interested lately in approximating images using lines of constant width. To that end, I’ve made these: These patterns are grown iteratively. A shape begins growing from the unclaimed point closest to the center of the image. By sampling the brightness of the image, the size of the new shape is chosen such that […]
  • Multiple Color Channels - Let’s apply the half-toning techniques to the separate color channels of an image, like the header image above. Or the one below, where the stripes are no longer aligned with the gradients. This can be done with any of the halftoning methods, but the stripes have character.
  • Stippling: So Many Dots - How can we draw pictures with dots? This is called stippling, which involves putting a lot of dots across an image to approximate tones. On a white background, more (or larger) black dots result in a locally darker image. These two approaches are known as AM and FM stippling. AM – amplitude modulation – means […]
  • Seismographs - On the theme of using a single path to shade an image, one idea is to use a wiggling line. A shorter wavelength will result in a darker area, and vice versa. So I threw a little math at the problem, and here are the results of using square, triangle waves, and sine waves: A […]
  • Stripes: Improved - Those other stripes are nice sometimes, but what about varying the orientation and wavelength of the stripes? As before, the output can be formed by varying the wavelength or the width of the stripes. Here are comparisons of the two approaches on the Lena: Now how about the crossed patterns? Much improved, compared to the […]
  • Stripes: Distance from Edges - A quick one: the phase field can be computed as the scaled distance from edges in the image. Then apply the stripes math, and: This has reasonably interesting circular artifacts, but it is limited in how it responds to the image.
  • Stripes: Laplacians - What if we want stripes to respond to an image? Well, we can make a version of the image that has gradients that are roughly parallel to those of the original image. Then we can use those as the basis of some stripes. Say we want a phase field that has gradients that are parallel […]
  • Branching Lines - I was inspired by Rapidly Exploring Random Trees, and wanted to make a halftoning method based on that. I wanted more lines in dark areas and fewer in bright areas. With some tweaks on the concept, I’ve made something that works reasonably well. It probabilistically chooses new line segment endpoints that are relatively close to […]
  • My PhD: Vortex Generation and Modeling - My PhD focused on the “Experimental Generation and Modeling of Vortical Gusts and Their Interactions with an Airfoil.” You can see my thesis here. I was interested in seeing the effect of a vortex interacting with a parallel wing. Most research on the topic has been based on helicopters or propellers, but those have periodically […]
  • Generative Writing - I wanted to generate random hand-written letters and have them look like writing. I wanted each alphabet to have a unique style: aspect ratio of characters, sharpness, and number of strokes. In the following image, each row is a different generated alphabet. Seems to work alright. They are visually distinct, though sometimes too complicated. Now […]
  • Worm Trails - Branching patterns are great. Here, the little movers die upon hitting a path, and respawn at the location of another mover. With some tweaks, this system can make a lot of nice patterns. You can even play with it online here! The basic version is here: That’s fun to watch evolve, but there are so […]
  • Animated Rorschach Blots - Using metaballs and thresholding, here’s an animated Rorschach blot: You can play with a variety of options at this link.
  • Gingery Roots - You can get pretty nice patterns just by moving circles around. Here are some of them. I vary the speed, wiggliness, transparency, and coloration.
  • Trees - Trees are nice branching things. Here’s some pictures with generated trees. If you want to generate your own, play with the snowy trees here, and the colorful trees here.
  • Rug in the Wind - I wanted to make an image out of strings, like if the threads of a shag carpet were extended, and dyed to match the colors of an underlying image. The strings hanging statically are no fun, so I added some wind, based on Perlin noise. Here’s a gif of the result: There’s lots of different […]
  • Hill-Climbing With Shapes - This code randomly puts shapes on a background, and sees if the added shape brings the new image closer to a target image. If the shape does, it is jittered more until it’s done improving the image for a certain number of iterations. For example, using 40 triangles on the Lena image: Neat. How about […]
  • Quadtree Patterns - Also not very rigorous, but fun patterns. Basically divide the image up using quadtrees, and draw another sub-pattern if it needs to be darker. Check out squares: And circles: Not perfect, but I like the joining of the shapes.
  • String Art - Here’s another non-rigorous one! I was inspired by a post showing off a sort of string art: run black string along a series of pins on a white background, and build an image that way. Here’s a couple examples, using 100 pins arranged in a circle: The first image picks its path with the darkest […]
  • Merge and Split - I wanted an make an image that is sort of like growing branches, but in a simpler way. This isn’t a very rigorous method, but we can use the plane waves approach to make a neat image. Basically, find properly spaced points on a series of rows, then connect them across rows. This leads to […]
  • Stripes: Predefined Patterns - The simpler way to use stripes is as predefined patterns that aren’t responsive to the image. For example, here’s a few Lenas halftoned using such stripes.
  • Stripes: Plane waves - Stripes can be used as the partionless thresholding pattern, as was seen in a previous example. But what if we want the stripes to change in response to the image? Well, we can use a set of plane waves to march across the image. Here’s what happens when we do that in either direction. Neat! […]
  • Cylindrical Earth - Circles are too flat. What if we want to make a cylindrical Earth? We can take the same sort of approach, but we need a couple more parameters. Let’s say we have a cap radius and height , then we can make this: With the sphere radius , by matching the surface areas, the possible […]
  • Variable-Radius Flat Earth - No, not the conspiracy theory. For example, here is an Earth-splat: And here is an Earth-square: And both are equal-area projections! How did I do this? Math. Math math math. We’ll use spherical coordinates, with polar angle and azimuthal angle . This means that latitude is, in radians, , and longitude is . We’ll say […]
  • Stochastic Halftoning - Fancy patterns aren’t totally necessary. A field of random numbers can also provide a pattern with the right properties needed for local partitionless thresholding. Even simple white noise can work, as the header image shows. But that’s not so pretty. What about other colors of noise? Or minimum wavelengths? The following image shows different colors […]
  • Thresholding with a Pattern - Last time, I used the Cumulative Distribution Function of an image’s intensity to make a black and white image. This time, I’ll use a different pattern as the basis for halftoning the image.  For example, I’ll use the following pattern of circles on a regular grid: This time, instead of finding a threshold from the […]
  • Partitionless Halftoning - We’ve looked at two halftoning methods using thresholding: either directly on the image, or using a pattern. These require making subdivisions of the image to get any decent spatial resolution. Instead, we can specify properties of the pattern such that the pattern itself acts as a threshold. The black and white image can then be […]
  • Intro to Halftoning - The general idea behind halftoning is to render an image using a very limited number of colors. On this blog, I’ll focus particularly on rendering black and white images. The following image is the Lena test image, and its grayscale version (converted in MATLAB). I’ll be using these for most of the approaches that I […]
  • Earth as a Disc - I wanted an equal-area projection of the earth onto a disk. This is a simple one. We’ll use spherical coordinates, with polar angle and azimuthal angle . This means that latitude is, in radians, , and longitude is . We’ll say that the sphere has a radius of . We’ll have the North pole at […]