Selecting morphological components by clicking on them?

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["http://i.stack.imgur.com/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["http://i.stack.imgur.com/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.

• 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.) – Niki Estner Nov 3 '13 at 21:46
• @nikie I posted some code based on your comment. If you decide post an answer later, please ping me and I'll delete mine – Dr. belisarius Nov 3 '13 at 22:11

Based on nikie's comment:

i = Import["http://i.stack.imgur.com/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. #] &]}]


i = Import["http://i.stack.imgur.com/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}]


• 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? – RVoight Nov 3 '13 at 22:13
• @RVoight just "Alt"+Click. See the LocatorAutoCreate help – Dr. belisarius Nov 3 '13 at 22:14
• @RVoight I don't understand your other q – Dr. belisarius Nov 3 '13 at 22:15
• Provided a list of the morphological components we wish to select, how can we do something like: SelectComponents[m, "Index", {28, 30, 16, 10}]? – RVoight Nov 3 '13 at 22:18
• 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. – Michael E2 Nov 4 '13 at 11:26

Here's a different solution I was working on.

 c = Import["http://i.stack.imgur.com/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];
)
]


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.

• 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. – Niki Estner Nov 4 '13 at 7:54
• @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. – C. E. Nov 4 '13 at 8:03
• 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. – Niki Estner Nov 4 '13 at 8:21
• @nikie I get what you're saying now, thanks for pointing that out. – C. E. Nov 4 '13 at 8:27