5
$\begingroup$

The function MorphologicalComponents works on both images and matrices, as in the following code:

list = {{2, 4, 0, 0, 0}, {5, 6, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 5, 1}, {0, 0, 0, 8, 9}};
mc = MorphologicalComponents[list];
MatrixForm[list]
MatrixForm[mc]

Image of the output from the above code

I would have hoped ComponentMeasurements could be used similarly. For example:

ComponentMeasurements[list, "Mean"]

Unfortunately this does not work. For my requirements I found instead I can simply use:

ComponentMeasurements[Image[list], "Mean"]

This provides the desired result:

Output from the above code, showing the mean calculated correctly

However it feels like a bit of a hack, and I'm worried about it not working consistently, and for other measurements. Is there a better way to calculate the mean of these regions separated by zeroes. More generally is there a function similar to ComponentMeasurements that works with matrices?

$\endgroup$
  • $\begingroup$ This seems like a bug. According to the documentation, ComponentMeasurements should accept an integer label matrix as input. It just doesn't work reliably. You can use ComponentMeasurements[{Image[list], mc}, "Mean"], if you don't trust it to work consistently with just an image argument. $\endgroup$ – Niki Estner Jul 13 '18 at 9:38
  • $\begingroup$ Oh ok. Actually my main concern was that in some instances the function Image[list] might change the values of list, perhaps if they are too large or too small. Perhaps not. I'm not familiar with Image[] $\endgroup$ – Tom Jul 13 '18 at 9:44
  • $\begingroup$ @NikiEstner It'as not a bug. "Mean" makes no sense for a label matrix, only for an image. However, we can provide both an image and a label matrix, as {image, labelMat}. $\endgroup$ – Szabolcs Jul 13 '18 at 9:45
  • $\begingroup$ @Tom Are you sure you are not confusing a label matrix with a matrix of intensity values (i.e. basically an image)? They are conceptually different things. For a label matrix, wrapping by Image is not a hack, it's plainly wrong. For the latter, it's also not a hack, it's the normal way to work with such data. $\endgroup$ – Szabolcs Jul 13 '18 at 9:45
  • $\begingroup$ Yes, my list is indeed a matrix of intensity values. I find it odd that I have to convert to an image for the function ComponentMeasurements , whereas I can leave it as a matrix for MorphologicalComponents. Perhaps I'm making a fuss out of nothing ;) $\endgroup$ – Tom Jul 13 '18 at 9:52
4
$\begingroup$

It is important to be aware of the distinction between matrices of intensity values (i.e. representing images) and matrices of label values (i.e. representing components).

If you have a matrix of intensity values, wrap it with Image. This is what signals to ComponentMeasurements to treat it as an image, and not as labels. You may want to specify the underlying pixel type. Note that Bit, Byte and Bit16 clip below and above the minimum and maximum values, while Real32 and Real do not clip the data (they simply display everything above 1 as white and everything below 0 as black, but they do preserve these out-of-range values intact). Image will not modify the data you pass to it, except for potential clipping when one of the integral pixel types is specified (Bit, Byte, Bit16).

A label matrix is a matrix of integer values where entries (pixels) having the same value are considered to belong to the same component. A label matrix is often used in conjunction with an image. It indicates which pixel of that image are part of the same component. The most general syntax for ComponentMeasurements is

ComponentMeasurements[{image, labelMatrix}, ...]

If you only provide an image, the label matrix is automatically computed (MorphologicalComponents).

Some quantities, such as "Count" depend only on the label matrix and not the image. In this case, it is allowed to provide only a label matrix.

Some other quantities, such as "Mean", require intensity values. In this case, it is necessary to provide the image too.


To summarize:

ComponentMeasurements won't work with a plain matrix of intensity values because it decides what the input represents (intensities or labels) based on its datatype (i.e. Head).

  • If the input is an Image, it is always treated as intensities.

  • If the input is a matrix (List, MatrixQ), then it is always treated as labels.

$\endgroup$
  • $\begingroup$ Thanks for the answer :) Although I am not confusing label matrices with a matrix of intensity values. I just don't understand why the process of calculating the mean of connected regions can't be done on a matrix itself, without wrapping it in an image. For example MorphologicalComponents can find the connected regions of a matrix, without one needing to wrap it as an image. $\endgroup$ – Tom Jul 13 '18 at 10:54
  • $\begingroup$ @Tom Because the function uses the head to distinguish between intensity values and label values. Head = List --> labels, Head = Image --> intensities. Also, I don't believe there are any disadvantages to convert to Image, but I can see many advantages (e.g. checking of the values and dimensions needs to be done once only; after conversion they're guaranteed to be correct) $\endgroup$ – Szabolcs Jul 13 '18 at 10:56
  • $\begingroup$ Ok I understand now. Thanks for the reassurance and clarification regarding using Image function. $\endgroup$ – Tom Jul 13 '18 at 10:59
  • $\begingroup$ @Tom I tried to clarify and edited out the "confusing" part—sorry about that. $\endgroup$ – Szabolcs Jul 13 '18 at 11:02
  • $\begingroup$ Looks really clear now, great :) $\endgroup$ – Tom Jul 13 '18 at 12:13

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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