vtkImageFourierCenter behaves differently from np.fft.fftshift ?

Dear all:
I am confused with vtkImageFourierCenter, which seems to behave quite differently from numpy’s fftshift. Consider the following simple example:

import numpy as np
import vtk
import vtk.numpy_interface.dataset_adapter as dsa

# Creating a simple vtk image (2 components, each component is 0,1,2,3, etc)
N = 4
vtk_image = vtk.vtkImageData()
vtk_image.SetDimensions([N, N, 1])
vtk_image.AllocateScalars(vtk.VTK_DOUBLE, 2)
n_tuples = vtk_image.GetPointData().GetScalars().GetNumberOfTuples()
for k_tuple in range(n_tuples):
    vtk_image.GetPointData().GetScalars().SetTuple2(k_tuple, k_tuple, k_tuple)

np_image = np.array(dsa.WrapDataObject(vtk_image).PointData["ImageScalars"][:,0] + 1j * dsa.WrapDataObject(vtk_image).PointData["ImageScalars"][:,1]).reshape((N,N))
np_image
# array([[ 0. +0.j,  1. +1.j,  2. +2.j,  3. +3.j],
#           [ 4. +4.j,  5. +5.j,  6. +6.j,  7. +7.j],
#           [ 8. +8.j,  9. +9.j, 10.+10.j, 11.+11.j],
#           [12.+12.j, 13.+13.j, 14.+14.j, 15.+15.j]])

# Shifting the image using numpy
np_image_shift = np.fft.fftshift(np_image)
np_image_shift
# array([[10.+10.j, 11.+11.j,  8. +8.j,  9. +9.j],
#           [14.+14.j, 15.+15.j, 12.+12.j, 13.+13.j],
#           [ 2. +2.j,  3. +3.j,  0. +0.j,  1. +1.j],
#           [ 6. +6.j,  7. +7.j,  4. +4.j,  5. +5.j]])

# Shifting the image using vtk
vtkImageFourierCenter = vtk.vtkImageFourierCenter()
vtkImageFourierCenter.SetInputData(vtk_image)
vtkImageFourierCenter.Update()
vtk_image_shift = vtkImageFourierCenter.GetOutput()

np.array(dsa.WrapDataObject(vtk_image_shift).PointData["ImageScalars"][:,0] + 1j * dsa.WrapDataObject(vtk_image_shift).PointData["ImageScalars"][:,1]).reshape((N,N))
#array([[ 5. +5.j,  6. +6.j,  7. +7.j,  4. +4.j],
#          [ 9. +9.j, 10.+10.j, 11.+11.j,  8. +8.j],
#          [13.+13.j, 14.+14.j, 15.+15.j, 12.+12.j],
#          [ 1. +1.j,  2. +2.j,  3. +3.j,  0. +0.j]])

Any insight on this would be super useful…thanks in advance!

Looks like an off-by-one error in vtkImageFourierCenter. Specifically this line in vtkImageFourierCenter.cxx where it computes the shift:

    mid0 = (wholeMin0 + wholeMax0) / 2;

In the case of a 4x4 image, wholeMin0 is 0 and wholeMax0 is 3 (i.e. the smallest and largest pixel index). So vtkImageFourierCenter computes the shift to be (0 + 3)/2 = 1. But the shift should be 2, not 1.

Likewise, VTK’s Spectrum.py test, which is supposed to test vtkImageFourierCenter, has an incorrect test image. The test image has the center of the spectrum at pixel index (129,129) instead of at the correct location (128,128):

Spectrum

This bug has existed in VTK from the very beginning. Strange that it wasn’t caught before.

2 Likes