Nearest neighbour interpolation

I seem to be getting a linear interpolation output even when trying to use Nearest neighbour.

Code:

#!/usr/bin/env python3

import vtk
from vtk.util.numpy_support import vtk_to_numpy, numpy_to_vtk
import numpy as np


def vtkToNumpy(data):
    np_arr = vtk_to_numpy(data.GetPointData().GetScalars())
    dims = data.GetDimensions()
    numpy_data = np_arr.reshape(dims[2], dims[1], dims[0])
    numpy_data = numpy_data.transpose(2, 1,0)

    return numpy_data

def numpyToVTK(data):
    flat_data_array = data.transpose(2,1,0).flatten()
    vtk_data_array = numpy_to_vtk(flat_data_array)
    vtk_data = numpy_to_vtk(num_array=vtk_data_array, deep=True, array_type=vtk.VTK_UNSIGNED_CHAR)

    img = vtk.vtkImageData()
    img.GetPointData().SetScalars(vtk_data)
    img.SetDimensions(data.shape)
    img.SetOrigin([0, 0, 0])
    img.SetSpacing([1, 1, 1])

    return img


def main():
    img = np.zeros((5, 5, 5), dtype=np.uint16)
    img[1:4, 1:4, 1:3] = 5
    img[2:4, 2:4, 4:9] = 11

    vtkImg = numpyToVTK(img)

    resample = vtk.vtkImageResample()
    resample.SetInputData(vtkImg)
    resample.SetInterpolationModeToNearestNeighbor()
    resample.InterpolateOff()
    resample.SetBackgroundColor([0, 0, 0, 0])
    resample.SetBackgroundLevel(0)
    resample.SetOutputSpacing([0.5, 0.5, 0.5])
    resample.Update()

    resampleNpImg = vtkToNumpy(resample.GetOutput())

    print("\nOriginal size", vtkImg.GetDimensions())
    print("Original center", vtkImg.GetOrigin())
    print("Original spacing", vtkImg.GetSpacing())

    print("\nResampled size", resample.GetOutput().GetDimensions())
    print("Resampled center", resample.GetOutput().GetCenter())
    print("Resampled spacing", resample.GetOutput().GetSpacing())

    print("\noriginalImg", np.unique(img), "\n\n", img)
    print("\nresampleNpImg", np.unique(resampleNpImg), "\n\n", resampleNpImg)


if __name__ == "__main__":
    main()

Output:

Original size (5, 5, 5)
Original center (0.0, 0.0, 0.0)
Original spacing (1.0, 1.0, 1.0)

Resampled size (9, 9, 9)
Resampled center (2.0, 2.0, 2.0)
Resampled spacing (0.5, 0.5, 0.5)

originalImg [ 0  5 11] 

 [[[ 0  0  0  0  0]
  [ 0  0  0  0  0]
  [ 0  0  0  0  0]
  [ 0  0  0  0  0]
  [ 0  0  0  0  0]]

 [[ 0  0  0  0  0]
  [ 0  5  5  0  0]
  [ 0  5  5  0  0]
  [ 0  5  5  0  0]
  [ 0  0  0  0  0]]

 [[ 0  0  0  0  0]
  [ 0  5  5  0  0]
  [ 0  5  5  0 11]
  [ 0  5  5  0 11]
  [ 0  0  0  0  0]]

 [[ 0  0  0  0  0]
  [ 0  5  5  0  0]
  [ 0  5  5  0 11]
  [ 0  5  5  0 11]
  [ 0  0  0  0  0]]

 [[ 0  0  0  0  0]
  [ 0  0  0  0  0]
  [ 0  0  0  0  0]
  [ 0  0  0  0  0]
  [ 0  0  0  0  0]]]

resampleNpImg [ 0  1  3  5  6 11] 

 [[[ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]]

 [[ 0  0  0  0  0  0  0  0  0]
  [ 0  1  1  1  1  1  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  1  1  1  1  1  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]]

 [[ 0  0  0  0  0  0  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  3  5  5  5  3  0  0  0]
  [ 0  3  5  5  5  3  0  0  0]
  [ 0  3  5  5  5  3  0  0  0]
  [ 0  3  5  5  5  3  0  0  0]
  [ 0  3  5  5  5  3  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]]

 [[ 0  0  0  0  0  0  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  3  5  5  5  3  0  0  0]
  [ 0  3  5  5  5  3  0  1  3]
  [ 0  3  5  5  5  3  0  3  6]
  [ 0  3  5  5  5  3  0  3  6]
  [ 0  3  5  5  5  3  0  3  6]
  [ 0  1  3  3  3  1  0  1  3]
  [ 0  0  0  0  0  0  0  0  0]]

 [[ 0  0  0  0  0  0  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  3  5  5  5  3  0  0  0]
  [ 0  3  5  5  5  3  0  3  6]
  [ 0  3  5  5  5  3  0  6 11]
  [ 0  3  5  5  5  3  0  6 11]
  [ 0  3  5  5  5  3  0  6 11]
  [ 0  1  3  3  3  1  0  3  6]
  [ 0  0  0  0  0  0  0  0  0]]

 [[ 0  0  0  0  0  0  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  3  5  5  5  3  0  0  0]
  [ 0  3  5  5  5  3  0  3  6]
  [ 0  3  5  5  5  3  0  6 11]
  [ 0  3  5  5  5  3  0  6 11]
  [ 0  3  5  5  5  3  0  6 11]
  [ 0  1  3  3  3  1  0  3  6]
  [ 0  0  0  0  0  0  0  0  0]]

 [[ 0  0  0  0  0  0  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  3  5  5  5  3  0  0  0]
  [ 0  3  5  5  5  3  0  3  6]
  [ 0  3  5  5  5  3  0  6 11]
  [ 0  3  5  5  5  3  0  6 11]
  [ 0  3  5  5  5  3  0  6 11]
  [ 0  1  3  3  3  1  0  3  6]
  [ 0  0  0  0  0  0  0  0  0]]

 [[ 0  0  0  0  0  0  0  0  0]
  [ 0  1  1  1  1  1  0  0  0]
  [ 0  1  3  3  3  1  0  0  0]
  [ 0  1  3  3  3  1  0  1  3]
  [ 0  1  3  3  3  1  0  3  6]
  [ 0  1  3  3  3  1  0  3  6]
  [ 0  1  3  3  3  1  0  3  6]
  [ 0  1  1  1  1  1  0  1  3]
  [ 0  0  0  0  0  0  0  0  0]]

 [[ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0]]]

The output should only contain 5s and 11s with Nearest neighbour method. Tried using InterpolateOff too, but same result. Are there any other flags I need to set to get an output with only [5, 11]?

Thanks for the test script. I have confirmed that this “unwanted interpolation” occurs in the master branch. It doesn’t seem to occur in the release branch.

Until I’ve tracked down and fixed this problem, you can use this alternative method for controlling the interpolation:

    interp = vtk.vtkImageInterpolator()
    interp.SetInterpolationModeToNearest()

    resample = vtk.vtkImageResample()
    resample.SetInputData(vtkImg)
    #resample.SetInterpolationModeToNearestNeighbor()
    #resample.InterpolateOff()
    # use external interpolator
    resample.SetInterpolator(interp)