ANTsX / ANTsPy

A fast medical imaging analysis library in Python with algorithms for registration, segmentation, and more.
https://antspyx.readthedocs.io
Apache License 2.0
586 stars 161 forks source link

pad_image does not adjust physical space #584

Closed cookpa closed 3 months ago

cookpa commented 3 months ago

As found in #582

The ITK ConstantPadImageFilter does not alter the physical space of the image. This is by design, the indices of the image region are adjusted, as explained here

https://discourse.itk.org/t/how-does-constantpadimagefilter-work/4592/2

PadImageFilter changes the region to be [-1, OriginalSize+1]. As origin refers to the location of pixel at index [0,0,0], it does not change. If you write that image to disk and read it again, you will notice the new origin (and region staring at 0 instead of -1). Spacing remains the same.

This holds true in ANTsPy, as you can pad an image and it remains in the same physical space:

ants.image_physical_space_consistency(im, padded)
True

However

>>> ants.image_write(padded, '/tmp/padded.nii.gz')
>>> pad_read = ants.image_read('/tmp/padded.nii.gz')
>>> ants.image_physical_space_consistency(im, pad_read)
False

SimpleITK adjusts metadata to avoid this

https://github.com/SimpleITK/SimpleITK/blob/master/Code/BasicFilters/include/sitkImageFilter.h#L64-L91

ants.crop_image also does this. Seems pad_image should as well?

ncullen93 commented 3 months ago

Interesting.. so the LOCAL_padImage.cxx file should be adjusted?

I can write a unit test, but just to clarify - the origin should shift after padding if it is to be like cropping, correct?

cookpa commented 3 months ago

That's how it's done for crop image, yes, the image region is reset to index from zero, and the physical coordinate of the (new) (0,0,0) voxel becomes the new origin. This keeps the location of the physical point (0.0,0.0,0.0) in the same place anatomically.

The origin should shift if the physical coordinate of voxel (0,0,0) moves as a result of the crop / pad. The pad_image function lets you pad anisotropically, so you could add voxels in such a way that doesn't change the origin. In that case, the voxel coordinates will still start from 0,0,0 and resetting the origin as in crop_image will produce the same physical space coordinates. We might want to do an "almost equals" check here so that we don't cause problems by moving the origin by 0.00001 mm due to precision errors.