Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

When I ask ComponentMeasurements to return "IntensityData" for some set of rectangular morphological components:

m = MorphologicalComponents[image, Method -> "BoundingBox"];
intensityDataArray = ComponentMeasurements[{m, image}, "IntensityData"][[All, 2]];

The pixel value data is returned as an unpartitioned one-dimensional array. This makes it difficult for me to understand where a particular pixel is in the image. Now, if I know the exact dimensions of each morphological component, I suppose I could fix the problem using Partition. I could also fix the problem with Partition if I could ask for something like a bounding square instead of a bounding rectangular box, though I don't think this is possible (is it?).

Besides manually measuring the dimensions of each rectangular morphological component, is there a workaround to fix this problem?

Letting m consist of strictly rectangular morphological components, it would, for example, be very nice to be able to write something like:

ComponentMeasurements[m, "Dimensions"][[All, 2]]

And have this return something like:

{{5,8}, {87, 40}, {7, 7}, ...}

Meaning that we have morphological components of dimensions $(x, y) = (5 \times 8)$, $(87 \times 40)$, $(7 \times 7)$, and so forth. Here, we're provided ordered values for the extent of the component along the $x$- and $y$-axes, respectively, allowing us to trivially use Partition to restore the cropped section of an image underlying a morphological component (i.e. the image one would have if a morphological component is used as a "cropping mask").


Clarification: Masking approaches are really neat, but not quite what I'm looking for here unless they're part of a larger approach. I need a method of grabbing the pixel data strictly underlying a morphological component (for a set of morphological components) and retaining $(x, y)$ data for each pixel. My downstream procedure then does further image processesing on this rectangular matrix. If I do a matrix multiplication masking procedure, I still need to trim away the dark space to get down to a bounding box (the size of the morphological component mask).

Also, it seems a little wasteful to have to perform multiplication operation on all pixels in the image to accomplish my goal?

share|improve this question
    
I think "IntensityData" is meant to be used for histogram processing, where the position of the intensities doesn't matter. Couldn't you just measure the "BoundingBox" instead and pass the result to ImageTrim to cut out the right area of the image? You can measure "Mask" to get a sparse array where the pixels of the component are set to 1. (I'm not sure what you're trying to achieve, I that's what I use when I need both the intensity and the location of the pixels in a component.) –  nikie Nov 2 '13 at 11:02
    
@nikie How do I ask for the dimensions of a rectangular morphological component? If I can do this, I can just use Partition, right? I mean, I can figure this out up to rotation and reflection symmetries using metrics like Elongation, but how do I nail down the orientation as well? –  RVoight Nov 2 '13 at 11:10
    
@nikie I'll also note that I have maybe a few thousand of these morphological components, so I'm kind of hoping for some automated solution. –  RVoight Nov 2 '13 at 11:16
    
Use Partition on the returned IntensityData? I don't think so, because some lines might be longer than others. At least unless the components are all perfectly rectangular. –  nikie Nov 2 '13 at 11:34
    
@nikie I'm specifying that the morphological components are bounding boxes, and must be rectangular. I'll try to clarify this better in the question. –  RVoight Nov 2 '13 at 11:35
show 1 more comment

2 Answers 2

up vote 6 down vote accepted

I'm answering the question you posted in a comment:

but how do I then crop to a bounding box around that component

List I said, the easiest way is probably to measure the "BoundingBox"es and pass them to ImageTrim:

image=ExampleData[{"TestImage","APC"}]

enter image description here

m=MorphologicalComponents[Binarize@ColorNegate[ColorConvert[image,"Grayscale"]]];
Colorize[m]

enter image description here

components=ComponentMeasurements[{m,image},{"Area","BoundingBox"},#1>100&];
ImageTrim[image,#]&/@components[[All,2,2]]

enter image description here

share|improve this answer
    
I don't have the rep. to upvote you, but I follow you now. I didn't know how ImageTrim worked! –  RVoight Nov 2 '13 at 11:47
    
@RVoight Please note that you still have to mask this! Otherwise you work on all the image values and not only on the ones from your component. –  halirutan Nov 2 '13 at 11:51
    
@halirutan: He doesn't if his components are all rectangular (because of Method -> "BoundingBox"). Otherwise, you're right of course. I just wanted to show how BoundingBox and ImageTrim can work together and didn't want to complicate things with masking. –  nikie Nov 2 '13 at 11:54
    
@nikie Ahh, haven't notice this before. –  halirutan Nov 2 '13 at 12:06
add comment

Why don't you use the "Mask" for a component to separate it in the original image?

image = ExampleData[{"TestImage", "JellyBeans"}];
m = MorphologicalComponents[
   Binarize@ColorNegate[ColorConvert[image, "Grayscale"]]];

mask = ComponentMeasurements[m, "Mask"];
ImageMultiply[image, Image[3 /. mask]]

In this way you can extract from the original image

Mathematica graphics

the 3rd component

Mathematica graphics

Answer to your comment

ImageTrim as suggested by nikie is better than using ImageTake because you can give it the bounding box directly.

mask = ComponentMeasurements[m, {"Mask", "BoundingBox"}];
ImageTrim[ImageMultiply[image, Image[First[# /. mask]]], 
   Last[# /. mask]] & /@ Range[Length[mask]]

Mathematica graphics

share|improve this answer
    
It's great to know we can do this, but how do I then crop to a bounding box around that component (my components are already rectangular)? –  RVoight Nov 2 '13 at 11:36
    
@RVoight You just use "BoundingBox" as additional measure and provide this to ImageTake. Be careful, because the ordering of the min/max box values is different and you have to incorporate the image dimensions in y direction. –  halirutan Nov 2 '13 at 11:45
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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