1

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[#]} & /@ 
   clusteredEdgePoints]}

{enter image description here, enter image description here}

Question:

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

Anjan Kumar
  • 4,979
  • 1
  • 15
  • 28
  • 2
    Consider something like FindClusters[edgePoints, 2, Method -> "Agglomerate", CriterionFunction -> "RSquared"]. Playing around with Method and CriterionFunction is worthwhile. – Carl Lange May 24 '19 at 18:50

1 Answers1

4

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

Niki Estner
  • 36,101
  • 3
  • 92
  • 152
  • 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? – Anjan Kumar May 24 '19 at 19:46
  • I realized that points obtained using Position[MorphologicalComponents[Dilation[edgeImg, 5]], 1] are not ordered. Is there a way I could order them? – Anjan Kumar May 25 '19 at 03:30
  • 1
    @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 – Niki Estner May 25 '19 at 05:46
  • 2
    If you only have a point set and need to find connected components, your best bet is using graph algorithms (see e.g. https://mathematica.stackexchange.com/questions/95425/can-i-get-the-curvature-at-any-point-of-a-random-curve/95442#95442, https://mathematica.stackexchange.com/questions/80683/reconstruction-of-interrupted-paths-in-images/88579#88579). But as you can see, this is much more complicated than using a function returning closed contours, like ContourDetect, ZeroCrossings or MorphologicalPerimeter – Niki Estner May 25 '19 at 05:54
  • Thanks for your reply. I tried: MorphologicalPerimeter[img // Binarize], it does seem to return closed contours, however, I am not sure how to get the contour points for the inner and outer ellipses. Do I have to apply MorphologicalComponents[] on top of this? – Anjan Kumar May 25 '19 at 08:44
  • 1
    So you don't want "clusters" (i.e. sets of connected points), but ordered contours? You could just use ComponentMeasurements[img, "Contours"] for that – Niki Estner May 25 '19 at 09:58
  • Thank you. That is exactly what I want. – Anjan Kumar May 25 '19 at 11:47