ResampleImageFilter 4D Images

Currently I am getting error when I try to use ResampleImageFilter over 4D image

In the following thread, it is mentioned that 4D support is only limited to ExtractImageFilter

File “/usr/local/lib/python3.5/dist-packages/SimpleITK/SimpleITK.py”, line 58541, in Execute
return _SimpleITK.ResampleImageFilter_Execute(self, *args)
RuntimeError: Exception thrown in SimpleITK ResampleImageFilter_Execute: /tmp/SimpleITK/Code/Common/include/sitkDualMemberFunctionFactory.hxx:218:
sitk::ERROR: Image dimension 4 is not supported

Hello SachidananAlle,

That is correct, SimpleITK’s ResampleImageFilter is not compiled with 4D image support. It does support resampling for 3D multi-channel images in the 3 spatial dimensions.

If you have a questions or need a suggestion of how to do an operation please clearly state your problem and questions.

For now, I could use ExtractImageFilter to get each slice from 4D image and apply the ResampleImageFilter and joined it later using JoinSeriesImageFilter

(But it will be great to see SITK supports that directly inside ResampleImageFilter)

Something like as follows:

def resample(self, new_spacing, new_size, image):
    resampler = sitk.ResampleImageFilter()
    resampler.SetInterpolator(sitk.sitkLinear)
    resampler.SetOutputSpacing(new_spacing)
    resampler.SetSize(new_size)

    resampler.SetOutputOrigin(image.GetOrigin())
    resampler.SetOutputDirection(image.GetDirection())
    img = resampler.Execute(image)
    return img

def get3dslice(image, slice=0):
    size = list(image.GetSize())
    if len(size) == 4:
        size[3] = 0
        index = [0, 0, 0, slice]

        extractor = sitk.ExtractImageFilter()
        extractor.SetSize(size)
        extractor.SetIndex(index)
        image = extractor.Execute(image)
    return image

# Resample 4D (SITK Doesn't support directly; so iterate through slice and get it done)
new_spacing = [sx,sx,sz]
new_size = [x,y,z]

images = []
size = list(image.GetSize())
for s in range(size[3]):
    img = get3dslice(image, s)
    img = resample(new_spacing, new_size, img)
    images.append(img)

join = sitk.JoinSeriesImageFilter()
image = join.Execute(images)
1 Like

Looks like a good solution to me. I have done similar things when working with 4D XYZC images. This approach is really asking for a reusable solution something like a python function decorator to operate slice_by_slice. Here is what I came up with:


def slicing_decorator(func):
    """
    A function decorator which extracts image slices of N-1 dimensions and calls func on each slice. The resulting
     images are then concatenated together with JoinSeries.
     
    :param func: A function which take a SimpleITK Image as it's first argument
    :return: The result of running func on each slice of image.
    """
    @wraps(func)
    def slice_by_slice(image, *args, **kwargs):

        size = list(image.GetSize())

        number_of_slices = size[-1]
        extract_size = size
        extract_index = [0]*image.GetDimension()

        img_list = []

        extract_size[-1] = 0
        extractor = sitk.ExtractImageFilter()
        extractor.SetSize(extract_size)

        for slice_idx in range(0, number_of_slices):


            extract_index[-1] = slice_idx
            extractor.SetIndex(extract_index)

            img_list.append(func(extractor.Execute(image), *args, **kwargs))

        return sitk.JoinSeries(img_list, image.GetOrigin()[-1], image.GetSpacing()[-1])

    return slice_by_slice


@slicing_decorator
def my_algo(image):
    print("Executing image of size: {0}".format(image.GetSize()))
    return sitk.SmoothingRecursiveGaussian(image)

2 Likes