11
$\begingroup$

This is a bit of a follow-up to a previous question: How can I merge multiple sets of morphological components (perhaps selected using different metrics)?

I've run into a few problems recently where it's actually rather difficult to select morphological components in an image based on size or geometry metrics, and really it would be much easier to just click on them, or to select them based on a coordinate in their interior.

Consider the task of selecting an arbitrary subset of morphological components in this image:

Import["https://i.sstatic.net/gSXIj.png"]

Is something like this possible?


Here's an update based on nikie's comment, where I believe he's suggesting we can do this:

image = Binarize[Import["https://i.sstatic.net/gSXIj.png"]];
m = MorphologicalComponents[image];
m // Colorize

exMorphologicalComponentNumOne = PixelValue[Image[m], {50, 214}]
exMorphologicalComponentNumOneTEST = PixelValue[Image[m], {49, 213}]

exMorphologicalComponentNumTwo = PixelValue[Image[m], {206, 146}]
exMorphologicalComponentNumTwoTEST = PixelValue[Image[m], {203, 142}]

This, I believe, is telling us the index value for the morphological components containing the pixels at {50, 214} and at {206, 146} in the image. Here, PixelValue simply takes a pixel coordinate and returns whatever is sitting at this index in ImageData[image]. So if you look at the output for MorphologicalComponents[image], you'll notice that the matrix is the same size as the output from ImageData[image] and that the positions in the image corresponding to a morphological component carry the value of the component's index.

This is a very good start (thank you nikie!), but it still isn't clear to me how to quickly select a subset of morphological components based on their index. It would also be really nice to be able to to the click-based selection I mention in the title, since here, we have to write down and retype coordinates using the locator pane. This becomes kind of time consuming if we need to select a large subset of morphological components in multiple images.

$\endgroup$
2
  • 3
    $\begingroup$ You can select a point in an image using LocatorPane, and your can use PixelValue to get the pixel value of an image at that point. If you call PixelValue on Image[MorphologicalComponents[binaryImage]], it'll give you the label index at that point. (Sorry, I don't have time for a full answer right now, but if you look at the documentation for these functions, you should be able to piece it together.) $\endgroup$ Commented Nov 3, 2013 at 21:46
  • 1
    $\begingroup$ @nikie I posted some code based on your comment. If you decide post an answer later, please ping me and I'll delete mine $\endgroup$ Commented Nov 3, 2013 at 22:11

2 Answers 2

17
$\begingroup$

Based on nikie's comment:

i = Import["https://i.sstatic.net/gSXIj.png"];
k = Image[MorphologicalComponents[i]];
DynamicModule[{pts = {{-1, 1}/2}}, 
              {LocatorPane[Dynamic[pts], Image[k, ImageSize -> 300], LocatorAutoCreate -> True, 
                           Appearance -> Graphics[{Red, Disk[]}, ImageSize -> 10]], 
               Dynamic@SelectComponents[k, "Label", MemberQ[PixelValue[k, #] & /@ Round@pts, 1. #] &]}]

enter image description here

Previous answer

i = Import["https://i.sstatic.net/gSXIj.png"]; 
k = Image[MorphologicalComponents[i]];
DynamicModule[{pts = {{-1, 1}/2}}, 
               {LocatorPane[Dynamic[pts], Image[k, ImageSize -> 300], LocatorAutoCreate -> True, 
                            Appearance -> Graphics[{Red, Disk[]}, ImageSize -> 10]], 
               PixelValue[k, #] & /@ Dynamic@Round@pts}]

Mathematica graphics

$\endgroup$
17
  • $\begingroup$ This is really nice. How does one add more points by clicking? And is there a way to select morphological components based on a list like your {28, 30, 16, 10} array? $\endgroup$
    – RVoight
    Commented Nov 3, 2013 at 22:13
  • $\begingroup$ @RVoight just "Alt"+Click. See the LocatorAutoCreate help $\endgroup$ Commented Nov 3, 2013 at 22:14
  • $\begingroup$ @RVoight I don't understand your other q $\endgroup$ Commented Nov 3, 2013 at 22:15
  • $\begingroup$ Provided a list of the morphological components we wish to select, how can we do something like: SelectComponents[m, "Index", {28, 30, 16, 10}]? $\endgroup$
    – RVoight
    Commented Nov 3, 2013 at 22:18
  • 1
    $\begingroup$ Interesting: I normally magnify my notebooks 150%, which causes interpolation at the boundaries of components. Clicking there selects the component with label equal to the mean of the labels of the adjacent components, if there is one. Not a big problem (click in the middle). But the magnification occurs in the Front End, and I couldn't figure out how to control the resampling. $\endgroup$
    – Michael E2
    Commented Nov 4, 2013 at 11:26
4
$\begingroup$

Here's a different solution I was working on.

 c = Import["https://i.sstatic.net/gSXIj.png"];   
 Manipulate[
     Column[{
       Show[
        components // Colorize,
        Graphics[Locator[x, Background -> Orange]]
        ],
       Text["Color index: " <> ToString[components[[Sequence @@ ({-#[[2]], #[[1]]} &@Round[x])]]]]
       }],
     {x, Locator, Appearance -> None},
     Initialization :> (
       x = ImageDimensions[c]/2;
       components = MorphologicalComponents[c];
       )
     ]

scrn

I suppose the difference is that I didn't turn the matrix into an image, so I had to convert between indices and coordinates, unnecessarily adding complexity to the solution.

$\endgroup$
4
  • $\begingroup$ I think your array indices are off by one, because coordinates start at 0 and indices start at 1. I always try to avoid these coordinate to array index conversions, because I never get them right, either. $\endgroup$ Commented Nov 4, 2013 at 7:54
  • $\begingroup$ @nikie I made it hard to try this out because I didn't originally include the image in my code. I've updated it. But I've tried this side by side with belisarius' solution and it yields the same answer. But I definitely agree, I will be using the other method whenever it's possible in the future. $\endgroup$
    – C. E.
    Commented Nov 4, 2013 at 8:03
  • $\begingroup$ You won't see a difference unless you position the locator right at the edge of a component. But you can try to get a pixel value of e.g. the Lena test image with these indices and with PixelValue, and you should get a different result. $\endgroup$ Commented Nov 4, 2013 at 8:21
  • $\begingroup$ @nikie I get what you're saying now, thanks for pointing that out. $\endgroup$
    – C. E.
    Commented Nov 4, 2013 at 8:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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