For example, I want to set all pixel values of an image to 1 where the current pixel value is >1.
In numpy, this could be done in the following way:
x[x > 1] = 1
However, for Images that does not work:
# x -> SimpleITK.Image
x[x > 1] = 1
results in an IndexError: too many indices for image
But there are the Mask and MaskNegated functions. However, they are a little bit awkward to use.
Because if I want to specify x > 1 = 1, then I would need to use the MaskNegated, which throws me an error:
sitk.MaskNegated(x, x > 1, 1))
RuntimeError: Exception thrown in SimpleITK MaskNegated: /tmp/SimpleITK/Code/Common/include/sitkProcessObject.h:354:
sitk::ERROR: Failure to convert SimpleITK image of dimension: 2 and pixel type: "8-bit unsigned integer" to ITK image of dimension: 2 and pixel type: "64-bit float"!
And when using Mask, you need to use the opposite for searching:
Below is a short function that will allow you to set an arbitrary value to the set of pixels defined by a mask. The mask is an image with pixel type sitkUint8, with values of zero and one. This is the returned type from all the logical SimpleITK operators (==,<,>,<=,>=), or any arbitrary mask you define.
import SimpleITK as sitk
def set_mask_value(image, mask, value):
msk32 = sitk.Cast(mask, sitk.sitkFloat32)
return sitk.Cast(sitk.Cast(image, sitk.sitkFloat32) *
sitk.InvertIntensity(msk32, maximum=1.0) +
msk32*value, image.GetPixelID())
img = sitk.ReadImage('patient.mha')
#set all values under -500 to 200
sitk.Show(set_mask_value(img, img<-500, 200))
Hrmm… Looking at this error further it looks like MaskNegated is expecting both images to be the same type. However, this is contraction ( like your expectations ) common conventions for masks in SimpleITK. So that is a bug, that should be addressed.
I frequently use just the Mask filter because it is a dual dispatch type for filter which can accept any integer image for the mask argument making more flexible.