# Voronoi mesh of a circular image

I have a circular image (below) and would like to obtain a Voronoi mesh.

I am able to obtain the centers of the cells inside the image as

cells = WatershedComponents[image];
centers00 = ComponentMeasurements[cells, "Centroid"];
centers0 = centers00[[All, 2]] pixel;


I have tried many things (ie intersection, bounding, ...) but no one works fine. Any ideas?

• see crop-a-voronoi-diagram-and-get-a-proper-meshregion i.e make VoronoiMesh and crop it on disk. g=Graphics[{Opacity[.5],LightGray,Disk[{0,0},1]}]; pts=RandomReal[{-1,1},{25,2}]; Show[VoronoiMesh[pts],g] Commented Jun 25 at 14:18
• A C++ program that computes the mesh given the center is in arxiv.org/abs/1110.3349 Commented Jun 26 at 10:46

As I stated in your previous question, you should use EdgeFilter then measure the centroids:

image = Import["https://i.sstatic.net/2fjQth5M.png"];
edge = EdgeDetect[image, 2];
centers = ComponentMeasurements[edge, "Centroid"] // Values;

HighlightImage[image, Point@centers, ImageSize -> 400]



And now create the clipped Voroni Mesh:


imgBounds = Transpose[{{0, 0}, ImageDimensions[image]}];
vm = VoronoiMesh[centers, imgBounds,
MeshCellStyle -> {{2, All} -> Black, {1, All} -> White}]



You can also convert this back to an image, and multiply by the circle part of the image to see how well it lines up. I have to delete the white border around the Voroni Mesh in order for this to line up:

scene = Image@Show[vm, Graphics[{Magenta, Point[centers]}]];

(*get rid of white border*)
blackPix = ImageValuePositions[scene, Black];
bounds = MinMax /@ (Transpose[blackPix]);
argTake = Join[{scene}, Reverse@bounds];
scene = ImageTake @@ argTake;

(*rescale to image size*)
scene = ImageResize[scene, ImageDimensions[image]];

circ = Binarize[image, 0.99] // ColorNegate;
ImageMultiply[scene, circ] + ColorNegate[circ]



And we see the Voroni Mesh looks pretty comparable to the original image.

If you want to keep using your method, you can use WatershedComponents, but you need to delete all the small, noisy watersheds outside of the circle:

cells = WatershedComponents[image];
cellImg = cells // Colorize


This can be accomplished with DeleteSmallComponents:

minSize = 100;
newCells = DeleteSmallComponents[cellImg, minSize]


And now measure the centroids and highlight:

centers00 = ComponentMeasurements[newCells, "Centroid"];
centers0 = centers00[[All, 2]] ;
HighlightImage[image, Point@centers0]


And apply the same method as before for creating the clipped Voroni Mesh, turning it into an image, and looking at the circular part:

vm = VoronoiMesh[centers0, imgBounds,
MeshCellStyle -> {{2, All} -> Black, {1, All} -> White}];
scene = Image@Show[vm, Graphics[{Magenta, Point[centers0]}]];

(*get rid of white border*)
blackPix = ImageValuePositions[scene, Black];
bounds = MinMax /@ (Transpose[blackPix]);
argTake = Join[{scene}, Reverse@bounds];
scene = ImageTake @@ argTake;

(*rescale to image size*)
scene = ImageResize[scene, ImageDimensions[image]];

circ = Binarize[image, 0.99] // ColorNegate;
ImageMultiply[scene, circ] + ColorNegate[circ]


VoronoiMesh[centers0]

Crop as needed.

See neat example of resource function HyperbolicDistance

The following is a cut down version using Beltrami model and metric just to show (not as good as neat example). Credit to the resource function.

h = ResourceFunction["HyperbolicDistance"];
r = RandomPoint[Disk[], 20];
nf = Nearest[r -> "Distance",
DistanceFunction -> (h[#1, #2, "Beltrami"] &)];
func[{x_, y_}] :=
Module[{d = nf[{x, y}, 2], t},
t = 1 - Clip[Rescale[d[[1]], {-6, 6}, {0, 1}]];
Max[t, d[[1]]/d[[2]]]];
DensityPlot[func[{x, y}], {x, y} \[Element] Disk[{0, 0}, 0.99],
Epilog -> {White, Point[r]}, PlotPoints -> 50]


20 random points in unit disk. The following gif is ten examples: