How does ConstantPadImageFilter work

Can someone help me understand how ITK’s ConstantPadImageFilter works? I was expecting to get an image with slightly different origin and the same spacing when padding:

pad_filter = itk.ConstantPadImageFilter[ImageType, ImageType].New()
pad_filter.SetPadLowerBound((1, 1, 1))                             
pad_filter.SetPadUpperBound((1, 1, 1))                             

When I do pad_filter.GetOutput().GetOrigin() I get [-180.631, -368.631, -44.8] and for the spacing I get [0.738281, 0.738281, 2], while the reader.GetOutput() is the same.

On the other hand, I tried a simple example using SimpleITK instead, and it correctly changes the origin by reducing by one spacing. I would expect that ITK pad_filter's output origin would be [-181.369, -369.369, -46.8].

Is the behavior of ITK normal?

PS: What’s also not clear is how itk.TriangleMeshToBinaryImageFilter works. Does this take into account the origin and spacing of the info image? It seems like even if I change the origin of the image passed to SetInfoImage, it doesn’t have an effect on the final result.

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.

TriangleMeshToBinaryImageFilter does take spacing into account:

… and it should be taking InfoImage into account too:

The ConstantPadImageFilter, like all the ITK filters, will not affect the input image. So the image from reader->GetOutput will not be affected. Instead the Update method returns a new image with the new, padded dimensions and the offset origin.

Sorry, I think my wording was misleading. I meant that the origin I get of the pad_filter output is the same origin I get from the reader output. I know that the reader output is not supposed to change, but I expected the origin of the pad_filter output to be reduced by one spacing wrt to the reader origin.

I tried something and now I’m a bit confused on how ITK works:

pad_filter = itk.ConstantPadImageFilter[ImageType, ImageType].New()
itk.imwrite(pad_filter.GetOutput(), 'temp.nii.gz')                 
padded_image = pad_filter.GetOutput()                              

The above outputs the following:

itkPointD3 ([-180.631, -368.631, -44.8])
itkPointD3 ([-180.631, -368.631, -44.8])
itkPointD3 ([-181.369, -369.369, -42.8])

Why writing to disk and reading back produces the correct result while calling GetOutput() after properly calling Update() gives the wrong result?

The results are not wrong. As @dzenanz said the output of ITK’s ConstantPadImageFilter set’s the output image’s largest possible regions to start with a negative index. The Origin is defined as the physical point of the zero index, not the smallest index.

Most (all?) file formats don’t support non-zero starting indexes, so the origin is fixed up when writing to disk.This can be confusing.

All of SimpleITK’s images have the largest possible region with a starting index of 0. This is a simplification done in SimpleITK so that an image just needs a size attribute, and not the full largest possible region. SimpleITK runs a post filter step to fix up a filters output’s largest possible region and origin to ensure this consistency with the SimpleITK image model.

1 Like

I see. I didn’t know that ITK images can have negative indices that’s why I did not completely understand @dzenanz’s answer. Can I read more about this somewhere?

Section 4.1.4 of the ITK Software Guide should be helpful.

1 Like