Hi All,
I’m still very much a beginner in Mathematica and have struggled with this one.
I would like to load an image, identify polygons, then if any polygons are open, close them with a line or a curve, then save the new image.
I have no idea even how to approach this.
Any advice would be appreciated.
Can you provide some sample images?
Attached is what I was thinking of.
That is a nice problem! Here is one way to separate single candidates for polygons and close them:
img = Import[
"https://community.wolfram.com//c/portal/getImageAttachment?filename=shapes.jpg&userId=1703851"];
pts = PixelValuePositions[DeleteSmallComponents[Thinning@ColorNegate@Binarize[img], 10], 1];
clusters = FindClusters[pts, Method -> "SpanningTree"];
orders = Last@*FindShortestTour /@ clusters;
polygs = MapThread[Polygon[#1[[#2]]] &, {clusters, orders}];
grph=Graphics[{Orange, EdgeForm[{Thick, Black}], polygs}]
This can be exported as image like so:
Export["ClusterPolygs.png", grph]
Regards – Henrik
[1]: https://community.wolfram.com//c/portal/getImageAttachment?filename=ClusterPolygs.png&userId=32203
Wow, that’s really elegant. Thanks Henrik!
Hi Henrik
That is a nice problem!
And your solution is very nice too!
Well, thank you, Rohit! But it is rather Mathematica which makes it really easy and elegant!
Best Regards --Henrik
I wonder if there are any other approaches to this problem? If anyone has any alternative suggestions, it would be great to hear from you?
ahmed
(Ahmed Elbanna)
February 2, 2023, 2:56pm
9
Amazing @Henrik Schachner ! Thank you for sharing. I was wondering why there are 8 clusters so I had to make an extra code line to realize that cluster 3 and 5 are from the same polygon.
Ahmed,
I was wondering why there are 8 clusters …
well, that is strange! This effect seems to be depending on the version of MMA:
on 13.1 (where the code was originally written) you get 7 clusters;
on 13.2 you actually get 8 clusters - as you did;
One not really elegant solution is to explicitly input the number of clusters:
clusters = FindClusters[pts, 7, Method -> "SpanningTree"]
Maybe anyone has a better method.
ahmed
(Ahmed Elbanna)
February 2, 2023, 3:55pm
11
I wrote the exact same code line to get 7 clusters. Anyway, this doesn’t affect the final result. Thank you again.
Yes, with Mathematica there are almost always other approaches possible. Here is one on the basis of image manipulation (but the result is less convincing):
img0 = Import["https://community.wolfram.com//c/portal/getImageAttachment?filename=shapes.jpg&userId=1703851"];
img = ImagePad[Thinning@Dilation[DeleteSmallComponents[ColorNegate@Binarize[img0], 10], 3], 50];
mcp = MorphologicalComponents[img];
indx = Rest@DeleteDuplicates@Flatten[mcp];
singleImgs = Table[Image[Map[If[# == c, 1, 0] &, mcp, {2}]], {c, indx}];
width = (1 /. ComponentMeasurements[#, "Width"] & /@ singleImgs)/2;
ColorNegate@ImagePad[ImageAdd@MapThread[Closing[#1, #2] &, {singleImgs, width}], -50]
Ahmed,
here is annother idea that might help separating the clusters in a clean way, just replace this line:
pts = PixelValuePositions[
Thinning@Dilation[DeleteSmallComponents[ColorNegate@Binarize[img], 10], 3],
1]
The dilation of the contours (before Thinning again) makes sure that a single contour is really connected. With this I always get:
clusters = FindClusters[pts, Method -> "SpanningTree"];
Length[clusters]
(* Out: 7 *)
Thanks again Henrik. Lots of ideas to play around with!
ahmed
(Ahmed Elbanna)
February 3, 2023, 4:34pm
15
Same here. Thank you, Henrik, for the tip.