15
$\begingroup$

I have been trying to find a way to separate the various closed paths that can be output by EdgeDetect. For example, taking the output of:

ColorNegate@EdgeDetect@Graphics[Style[Text["8"], 400]]

enter image description here

I'd like to be able to obtain a list like:

enter image description here

I'd really love to show some progress I made on this, but to be honest, I'm stuck at the beginning. I really don't know how to attack this one. The naïve approach might be to take one black pixel, then go around it registering adjacent pixels as part of the same path, while erasing them from the original image. But I don't expect this to be anything other than painfully slow, and there probably are some Mathematica image manipulation functions that I could leverage. So, how would you advise me to start?

$\endgroup$
14
$\begingroup$

You can use MorphologicalComponents to get the different loops:

With[{components = MorphologicalComponents@EdgeDetect@Graphics[Style[Text["8"], 400]]},
    ColorNegate@Image[1 - Unitize[components - #]] & /@ Range[Max[components]]]

enter image description here

Trying this on other similar characters — {"A", "B", "g", "9"}

enter image description here

$\endgroup$
7
$\begingroup$

This is partly derived from Vitaliy answer here.

pic = 
  Thinning@
   Binarize[
    GradientFilter[
     Rasterize[Style["8", FontFamily -> "Times"], ImageSize -> 500] //
       Image, 1]];
pdata = Position[ImageData[pic, DataReversed -> True]\[Transpose], 1];
lcp = ListCurvePathPlot[pdata, Axes -> None]

My only change is the massaging to get the '8' upright.

Mathematica graphics

Now it's pretty easy to get the paths from it:

Graphics /@ Cases[lcp, Line[a_], Infinity]

Mathematica graphics

$\endgroup$
7
$\begingroup$

While R.M. and belisarius answers certainly work, they seem a bit complex for me, extracting separate masks out of MorphologicalComponents's output. It gets a lot simpler if you use ComponentMeasurements instead, which simply returns a list of masks for each component (as sparse arrays, so might be more efficient, too):

edges = EdgeDetect@Graphics[Style[Text["8"], 400]]; (* taken from belisarius's answer *)
masks = ComponentMeasurements[edges, "Mask"];
Image /@ masks[[All, 2]]
$\endgroup$
6
$\begingroup$

In the same spirit as RM's answer

mc = MorphologicalComponents[EdgeDetect@Graphics[Style[Text["8"], 400]]];
Image /@ (Array[Replace[mc, {{Except[#] -> 0}}, {2}] &, Max@mc][[All, 1]])

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.