Computers today have enough power to draw billions of triangles on screen every second.

That’s great for media creators because they don’t have to work nearly as hard to optimize their assets, but there’s a certain charm to the aesthetics that fall out of the pursuit of simplicity.

Keeping an image readable and recognizable while stripping away detail is a fun challenge and the results are often striking:

A few years ago I wrote a script that stylizes any image as low-poly. Here’s a few samples processed through that script:

The first version of this generator (Kon) was Python-based, using numpy, opencv, and scipy. It got the job done, but it was slow - about 15 seconds per image.

I figured I could do better, so I revisited the generator to do a Rust rewrite.

How it works

I’ll start with this beetle I photographed at MacRitchie reservoir:

Step 1: Smart Point Sampling

The key to a good low-poly image is choosing the right points. Instead of random sampling, Kon uses a Sobel filter to focus on edges and important features.

The Sobel gradient of an image highlights changes in intensity - it’s bright where there’s high-frequency detail and dark where the intensity doesn’t change much. Essentially, it acts like an edge detector.

To further emphasize the most salient edges, I also raise the contrast on the Sobel gradient by exponentiating it:

We then run weighted random sampling over the gradient image to pick a set of points to act as the basis for our low-poly image’s polygons:

Step 2: Delaunay Triangulation

Once the points are picked, they’re connected with Delaunay triangulation, which ensures well-formed triangles without overlap.

  • Built with the spade crate for efficient triangulation.
  • Edge handling to prevent artifacts or gaps.
  • Parallelized with Rayon for speed.

Step 3: Coloring the Polygons

Each triangle’s color is determined using:

  • K-Means clustering for dominant colors.
  • Median Cut for color quantization.
  • Mean color fallback for tiny triangles.

To make sure everything worked, I generated debug images at different stages. This made it easy to spot issues like uneven point distribution and triangulation artifacts.

What’s Next?

Kon is a lot faster now, but there’s still a lot missing and many ways to improve it. Here’s a few things I’ve been thinking about:

  • Manual Point Placement – Let users tweak key points.
  • WASM GUI – A browser-based interactive tool.
  • More Polygon Types – Triangles are great, but what about hexagons? And other shapes?
  • Selective Effects – Low-poly only on certain parts of an image.
  • GPU Acceleration – CUDA or Vulkan for real-time processing.
  • Low-Poly Video – Extending the approach to moving frames.

Inspiration

When I revisited this project, I found other great takes on low-poly generation:

If you want to try the generator, check out the GitHub repo