Change Pixel values of Images where expression

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:

sitk.Mask(x, sitk.Not(x > 1), 1))

Is there no other, more convenient way?

Hello @reox,

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))
1 Like

For this particular case you could do:

sitk.Clamp(x,upperBound=1)

Also x <= 1 should be equivalent to sitk.Not(x > 1)

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.

I suspected that there would be functions for certain tasks :slight_smile: I just have to read more of the API I guess :wink:
Clamp seems to be very useful!

yep, that works well with the Mask too.