Consider the following image

enter image description here

I would like to cluster the points obtained after edge detection and subsequently, would like to color the clustered edge points.

My attempt:

img = URLExecute["https://i.stack.imgur.com/4q309.png"];
edgeImg = img // EdgeDetect;
edgePoints = PixelValuePositions[edgeImg, 1];
clusteredEdgePoints = FindClusters[edgePoints, Method -> "NeighborhoodContraction"];
{edgeImg, Graphics[{ColorData["DarkRainbow"][RandomReal[]], Line[#]} & /@ 

{enter image description here, enter image description here}


One can observe, FindClusters did not group inner and outer ellipses. How should I tell FindClusters to group inner and outer ellipses? or is there any other alternative?

Note: I would like to keep the question as general as possible that is I would not want to enter the number of clusters explicitly.

Some other images can be as follows:

img1 = URLExecute["https://i.stack.imgur.com/Z150N.png"];
img2 = URLExecute["https://i.stack.imgur.com/spkHI.png"];

enter image description here, enter image description here

  • 2
    $\begingroup$ Consider something like FindClusters[edgePoints, 2, Method -> "Agglomerate", CriterionFunction -> "RSquared"]. Playing around with Method and CriterionFunction is worthwhile. $\endgroup$ – Carl Lange May 24 at 18:50

So, you want to find connected components of all edge pixels that are less than N pixels apart?

You could use MorphologicalComponents for this:

MorphologicalComponents[Dilation[edgeImg, 5]]*
  ImageData[edgeImg] // Colorize

enter image description here

  • $\begingroup$ Thanks for the answer. I would like to connect the clustered edge points using Lines too. I have tried this: Graphics[Line@ Position[MorphologicalComponents[Dilation[edgeImg, 5]], 1]], but it gives a black image. Where did I go wrong? $\endgroup$ – Anjan Kumar May 24 at 19:46
  • $\begingroup$ I realized that points obtained using Position[MorphologicalComponents[Dilation[edgeImg, 5]], 1] are not ordered. Is there a way I could order them? $\endgroup$ – Anjan Kumar May 25 at 3:30
  • 1
    $\begingroup$ @AnjanKumar: I wouldn't go down that route - there are too many morphological special cases and pitfalls. (Take e.g. the two little line segments at the bottom of the O image above - where would you connect them to?) It's way simpler to use something like MorphologicalPerimeter[img] that is guaranteed to return closed contours than using EdgeDetect and then trying to reconstruct them $\endgroup$ – Niki Estner May 25 at 5:46
  • 2
    $\begingroup$ If you only have a point set and need to find connected components, your best bet is using graph algorithms (see e.g. mathematica.stackexchange.com/questions/95425/…, mathematica.stackexchange.com/questions/80683/…). But as you can see, this is much more complicated than using a function returning closed contours, like ContourDetect, ZeroCrossings or MorphologicalPerimeter $\endgroup$ – Niki Estner May 25 at 5:54
  • 1
    $\begingroup$ So you don't want "clusters" (i.e. sets of connected points), but ordered contours? You could just use ComponentMeasurements[img, "Contours"] for that $\endgroup$ – Niki Estner May 25 at 9:58

Your Answer

