# 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

random.seed(42)
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):
subdiv.insert(RandomPoint())``````

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.
cv2.circle(
img, (int(center), int(center)), 3, (0, 0, 0), cv2.FILLED, cv2.LINE_AA, 0)``````

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

``plt.imshow(img)``

If you use 42 as the seed, you should see exactly:
{"ft_lang_label":"__label__en","ft_lang_prob":0.759638,"math_prob":0.9699311,"size":2048,"snap":"2023-14-2023-23","text_gpt3_token_len":557,"char_repetition_ratio":0.09148728,"word_repetition_ratio":0.0,"special_character_ratio":0.28564453,"punctuation_ratio":0.19955157,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.99357975,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-06-09T05:11:58Z\",\"WARC-Record-ID\":\"<urn:uuid:81cac43a-e3bc-42af-98eb-80537f1a513a>\",\"Content-Length\":\"93312\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:2d21dc20-dce4-49e2-80fa-b9e1cfdb3e6b>\",\"WARC-Concurrent-To\":\"<urn:uuid:6954876c-f35e-4097-8098-05f886447f1b>\",\"WARC-IP-Address\":\"192.0.78.24\",\"WARC-Target-URI\":\"https://kchodorow.com/2022/10/13/generating-voronoi-cells-in-python/\",\"WARC-Payload-Digest\":\"sha1:DLDHB3NKNZO4LXIV5TOWMLEYU2X3XYJF\",\"WARC-Block-Digest\":\"sha1:ZTJP2JXNSVWR4L7J5U46IGEQTCP76J4J\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-23/CC-MAIN-2023-23_segments_1685224655247.75_warc_CC-MAIN-20230609032325-20230609062325-00523.warc.gz\"}"}