Skip to content
lucaskrantz.se

Project

teardrop

A local image-processing system that rebuilds stills and GIFs from triangle meshes.

Year
2026
Role
Creative coding, image processing, tool design

Teardrop is a local Python system for image obfuscation and stylisation. It finds the subject, measures where the image carries detail, and spends more geometry around those areas.

The starting point was the beetle on Massive Attack's Mezzanine cover. I wanted a way to keep the shape and mood of an image while breaking up the original detail.

A caiman lizard redrawn as a grainy monochrome triangle mesh
The lizard cinematic preset combines subject masking, dense triangulation, monochrome tones, and grain.

What it does

  • Finds the main subject with a generated or prepared mask
  • Builds an importance map from edges, corners, and local contrast
  • Spends a fixed point budget across contours, details, and open areas
  • Builds a Delaunay triangle mesh from those points
  • Colours each triangle from the source image
  • Adds optional tone, grain, texture, fracture, and vignette passes

The mesh can be sparse and rough or dense enough to hold small features. A fixed seed makes the same settings reproducible.

  1. The source owl engraving before Teardrop processing

    Source

  2. The corrected binary subject mask used for the owl

    Subject mask

  3. Detected edges in the owl source image

    Edges

  4. High-density sampling points distributed over the owl

    Sampling points

  5. The resulting Delaunay triangle wireframe over the owl

    Triangulation

  6. The final high-density polygon render of the owl

    Final render

The current high-density debug pass, from source and mask through edges, sampling, triangulation, and final render.

Every stage can be written to disk. A poor result can usually be traced to the mask, point plan, mesh, colour sampling, or style pass. Fixed seeds and saved masks also make runs easier to compare.

Mesh density controls how much structure survives. More triangles can preserve an eye or a fine outline, while fewer triangles produce a stronger abstraction. Recognisable silhouettes can remain, so the output does not guarantee anonymity.

1,107 points
Drag the control to change the number of sampling points. The source, corrected mask, unified renderer, seed, and output size stay fixed while point density changes.

Masks come first

Teardrop can use GrabCut, line-art detection, SAM2 prompts, a saved mask, or the whole frame. The mask sets the boundary where later stages spend their points. Saving a good mask makes the final work repeatable and allows manual correction.

Two masks and two triangle renders of a pale moth, showing a clean subject mask and an expanded mask that includes the background
The pale-detail preset finds more wing structure, but its expanded mask also absorbs parts of the background.

The moth shows why the order matters. Extra contrast and denser sampling recover faint detail, but they cannot repair an incorrect subject boundary. I check the mask first, then the point plan, and style the image last.

Animation

GIFs pass through the same pipeline frame by frame. Stable mode reuses the first frame's mask, sample points, mesh, and style seed. This keeps the geometry from flickering when the camera and subject stay in place. Frame timing and looping are kept in the exported file.

A rotating spiral made from fine white marks
Source animation.
The same rotating spiral rebuilt as a stable monochrome triangle mesh
Stable line-art topology.

The preview takes every third frame from the 24-frame source. Its eight output frames keep the original 40 ms timing and infinite loop. The geometry remains fixed while each frame supplies new triangle colours.

A six-panel animation debug view showing the source frame, mask, importance map, background mesh, subject mesh, and final composite
The first processed frame exposes the shared mask, importance signal, meshes, and final composite.

Independent mode recalculates the mask and geometry for moving subjects, though the mesh can change visibly between frames. Stable mode works best with a fixed camera and centred composition. GIF export uses a shared 256-colour palette; APNG is available when smooth alpha and full colour matter.

Working with the tool

The command-line interface covers the full pipeline and works well for repeatable runs and batches. A small local browser interface handles the common workflow: upload an image or GIF, choose the mesh density and look, select a mask method, and export the result. Both interfaces save their work locally. Processing size and export size are separate, so a small working canvas can be enlarged without changing the mesh.

The project is written in Python with Pillow, OpenCV, SciPy, and Gradio. The source and usage notes are on GitHub.