10
$\begingroup$

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?

$\endgroup$
6
  • $\begingroup$ 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.) $\endgroup$ Commented Nov 2, 2013 at 11:02
  • $\begingroup$ @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? $\endgroup$
    – RVoight
    Commented Nov 2, 2013 at 11:10
  • $\begingroup$ @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. $\endgroup$
    – RVoight
    Commented Nov 2, 2013 at 11:16
  • $\begingroup$ 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. $\endgroup$ Commented Nov 2, 2013 at 11:34
  • $\begingroup$ @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. $\endgroup$
    – RVoight
    Commented Nov 2, 2013 at 11:35

2 Answers 2

13
$\begingroup$

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

$\endgroup$
4
  • $\begingroup$ I don't have the rep. to upvote you, but I follow you now. I didn't know how ImageTrim worked! $\endgroup$
    – RVoight
    Commented Nov 2, 2013 at 11:47
  • $\begingroup$ @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. $\endgroup$
    – halirutan
    Commented Nov 2, 2013 at 11:51
  • $\begingroup$ @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. $\endgroup$ Commented Nov 2, 2013 at 11:54
  • $\begingroup$ @nikie Ahh, haven't notice this before. $\endgroup$
    – halirutan
    Commented Nov 2, 2013 at 12:06
5
$\begingroup$

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

$\endgroup$
2
  • $\begingroup$ 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)? $\endgroup$
    – RVoight
    Commented Nov 2, 2013 at 11:36
  • $\begingroup$ @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. $\endgroup$
    – halirutan
    Commented Nov 2, 2013 at 11:45

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.