Generating Voronoi cells in Python

Voronoi cells are basically the shape you see soap suds make. They have a lot of cool properties that I wanted to use for image generation, but I didn’t want to have to figure out the math myself. I found this really excellent tutorial on generating Voronoi cells, which goes into some interesting history about them, too!

However, the Python code was a little out-of-date (and I think the author’s primary language was C++), so I wanted to clean up the example a bit.

It’s always a little tricky combining numpy and cv2, since numpy is column-major and cv2 is row-major (or maybe visa versa?) so I’m doing a rectangle instead of a square to make sure the coordinates are all ordered correctly. I started with some initialization:

import cv2
from matplotlib import pyplot as plt
import numpy as np

width = 256
height = 128
num_points = 25

Then we can use the Subdiv2D class and add a point for each cell:

subdiv  = cv2.Subdiv2D((0, 0, width, height))

def RandomPoint():
  return (int(random.random() * width), int(random.random() * height))

for i in range(num_points):

Then it just spits out the cells!

# Note that this is height x width!
img = np.zeros((height, width, 3), dtype=np.uint8)

def RandomColor():
  """Generates a random RGB color."""
  return (
    random.randint(0, 256), 
    random.randint(0, 256), 
    random.randint(0, 256))

# idx is the list of indexes you want to get, [] means all.
facets, centers = subdiv.getVoronoiFacetList(idx=[])
for facet, center in zip(facets, centers):
  # Convert shape coordinates (floats) to int.
  ifacet = np.array(facet, int)

  # Draw the polygon.
  cv2.fillConvexPoly(img, ifacet, RandomColor(), cv2.LINE_AA, 0)

  # Draw a black edge around the polygon.
  cv2.polylines(img, np.array([ifacet]), True, (0, 0, 0), 1, cv2.LINE_AA, 0)

  # Draw the center point of each cell.
    img, (int(center[0]), int(center[1])), 3, (0, 0, 0), cv2.FILLED, cv2.LINE_AA, 0)

Finally, write img to a file or just it display with:


If you use 42 as the seed, you should see exactly:

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: