Using an image as a mask

I want to retrieve the original intensities of image but only if the voxel is 1 in the foreground mask

My code looks like this:

# compute foreground image
# -------------------------------------
bg_data = sitk.GetArrayFromImage(background)
fg_data = np.zeros(bg_data.shape)
fg_data[np.where(bg_data == 0)] = 1  # opposite to background
foreground = sitk.GetImageFromArray(fg_data)

# apply mask
sitk.Mask(image, foreground, maskingValue=1, outsideValue=0)

I am getting this error:

RuntimeError: Exception thrown in SimpleITK Mask: Users/runner/work/1/sitk/Code/Common/include/sitkDualMemberFunctionFactory.hxx:178:sitk::ERROR: Pixel type: 16-bit signed integer is not supported in 3D byN3itk6simple15MaskImageFilterE

What should I do?

Hello @Diego_C ,

The code is a bit complicated, not sure what you are trying to achieve with the back and forth via numpy. Below is a simple example which creates a binary mask via thresholding and zeros out all the voxels that are in the background.

import SimpleITK as sitk

image = sitk.ReadImage('training_001_ct.mha')
foreground_mask = image>0
foreground_image = image*sitk.Cast(foreground_mask, image.GetPixelID())
1 Like

When you get this type of error you need to inspect the image inputs to the filter. Look at the image dimensions, pixel types, meta-data etc.

The Mask filter support most sensible combinations for it’s image arguments:

In [1]: import SimpleITK as sitk

In [2]: img = sitk.Image([16]*3,sitk.sitkFloat32)

In [3]: mask = sitk.Image([16]*3, sitk.sitkInt16)

In [4]: sitk.Mask(img, mask)
Out[4]: <SimpleITK.SimpleITK.Image; proxy of <Swig Object of type 'std::vector< itk::simple::Image >::value_type *' at 0x7fab28ba8d50> >

Unlike when the multiplication operator which requires the images to be the same type ( thus why the Cast was needed.

For you case I suspect that there is a mismatch in number of dimensions in the images after converting to and fro NumPy. Unfortunately, since your code is not self contained I can not reproduce it. If you initialized the background and image with something like background = sitk.Image([32]*2, sitk.sitkFloat32) the could would be self contained.

Hi @blowekamp

No mismatch in number of dimensions between input and foreground (filter inputs).

I managed to fix the problem like this:

sitk.Mask(image, sitk.Cast(foreground,sitk.sitkInt8), maskingValue=1, outsideValue=0)

So it looks like I needed to specify the pixel type of the numpy array I was using to build the foreground mask.

Masking Behaviour

I am a bit confused though about the mask masking in or masking out behaviour?

My foreground mask is 1 for the head and 0 for the background, so I was expecting as a result of using the masking filter to see only the “head” voxels using:

  sitk.Mask(image, sitk.Cast(foreground,sitk.sitkInt8), maskingValue=1, outsideValue=0)

but this is what I obtained:

In contrast, if I change the instruction to:

sitk.Mask(image, sitk.Cast(foreground,sitk.sitkInt8), maskingValue=0, outsideValue=0)

Then I obtain the expected result:

So I thought that the maskingValue parameter referred to the intensity value in the mask that the filter would use to select voxels in from the original input. But I am seeing this is not the case.

What is maskingValue?



1 Like

From the sitk::MaskImageFilter doxygen page:

if pixel_from_mask_image != masking_value
 pixel_output_image = pixel_input_image
 pixel_output_image = outside_value

The current brief documentation for the filter is: “Mask an image with a mask.” Suggestions for a brief line to better describe this behavior are welcome.