

Another piece of “wiskunst,“ which is a portmanteau of the Dutch words wiskunde (meaning mathematics) and kunst (meaning art) — sadly, I can’t find a nice equivalent term in English. Made with Chatgpt o4-mini-high and Google Colab.
import numpy as np from PIL import Image from scipy.spatial import cKDTree, Delaunay from skimage.draw import line def generate_structured_voronoi_delaunay( width=4096, height=4096, num_sites=2000, seed=42 ): np.random.seed(seed) # 1) Generate random sites sites = np.column_stack([ np.random.randint(0, width, size=num_sites), np.random.randint(0, height, size=num_sites) ]) # 2) Voronoi labeling tree = cKDTree(sites) xv, yv = np.meshgrid(np.arange(width), np.arange(height)) pts = np.column_stack([xv.ravel(), yv.ravel()]) labels = tree.query(pts, k=1)[1].reshape((height, width)) # 3) Delaunay edges → pixel list tri = Delaunay(sites) edge_set = set() for simplex in tri.simplices: for (i, j) in [(0,1), (1,2), (2,0)]: x0, y0 = sites[simplex[i]] x1, y1 = sites[simplex[j]] rr, cc = line(int(y0), int(x0), int(y1), int(x1)) valid = (rr>=0)&(rr
=0)&(cc >16)&0xFF G = (all_colors>>8)&0xFF B = all_colors&0xFF palette = np.column_stack([R,G,B]).astype(np.uint8) # 5) Prepare the output image img = np.zeros((height, width, 3), dtype=np.uint8) # 6) Paint edges as a luminance‐sorted gradient edge_colors = palette[:num_edge_pixels] # compute luminance lum_e = 0.299*edge_colors[:,0] + 0.587*edge_colors[:,1] + 0.114*edge_colors[:,2] sorted_colors_e = edge_colors[np.argsort(lum_e)] # sort edge coords in raster order flat_idx = edges[:,0]*width + edges[:,1] scan_order = np.argsort(flat_idx) for idx, e_i in enumerate(scan_order): r, c = edges[e_i] img[r, c] = sorted_colors_e[idx] # mark those pixels off‐limits for region filling is_edge = np.zeros(total_pixels, dtype=bool) is_edge[edges[:,0]*width + edges[:,1]] = True # 7) Fill each Voronoi region with its own radial luminance gradient ptr = num_edge_pixels flat_labels = labels.ravel() for site_idx in range(num_sites): # all pixels in this region (flat indexes) region_mask = flat_labels == site_idx region_mask[is_edge] = False pix_idxs = np.nonzero(region_mask)[0] n = len(pix_idxs) if n == 0: continue # slice off this region's colors and sort by luminance block = palette[ptr:ptr+n] ptr += n lum_b = 0.299*block[:,0] + 0.587*block[:,1] + 0.114*block[:,2] sorted_block = block[np.argsort(lum_b)] # get (r,c) coords and sort them by distance to the site rs = pix_idxs // width cs = pix_idxs % width dy = rs - sites[site_idx,1] dx = cs - sites[site_idx,0] dists = np.hypot(dx, dy) order = np.argsort(dists) # paint for color, idx in zip(sorted_block, order): r = rs[idx] c = cs[idx] img[r, c] = color # 8) Save result Image.fromarray(img).save("structured_voronoi_delaunay_4096.png") print("Saved structured_voronoi_delaunay_4096.png") if __name__ == "__main__": generate_structured_voronoi_delaunay()
Date | |
---|---|
Colors | 16,777,216 |
Pixels | 16,777,216 |
Dimensions | 4,096 × 4,096 |
Bytes | 50,269,888 |