torch-interpol icon indicating copy to clipboard operation
torch-interpol copied to clipboard

resizing results consistency with skimage.transform.resize?

Open thuzjf opened this issue 1 year ago • 2 comments

Thanks for you to open source this amazing project. Recently I was searching for some pytorch-based resampling methods that support bspline interpolation to replace the skimage.transform.resize in my project for speed concerns, and fortunately I found this. I tested both methods(skimage resize and interpol.resize) on a 3D medical data and found that the results are consistent when order(interpolation) is 1 and 2, but not consistent when order is 3, 4 or 5, through the difference is very small. Is this expected?(I also tested SimpleITK's ResampleFilter, and the results are slightly different except for order 1) Are there some default params which I can utilize to make the results exactly the same? Thank you!

here is a tiny test case

shape=[16,512,512]
new_shape=[32,320,320]

a = np.random.rand(*shape)
at = torch.from_numpy(a).unsqueeze(0).unsqueeze(0)

b1=resize(a, new_shape, order=3, mode='edge', anti_aliasing=False)
b2=interpol.resize(at, shape=new_shape, anchor='edges', interpolation=3)
b2=b2.squeeze().numpy()

print(np.abs(b2-b1).sum())

thuzjf avatar Sep 20 '23 09:09 thuzjf

Hello,

I haven't done in depth comparisons, but I've quickly looked at skimage's code and:

  • skimage's uses scipy.zoom with grid_mode=True, which corresponds to interpol's anchor='edges' (you did this correctly)
  • skimage's mode corresponds to interpol's bound, and mode='edge' should be translated to bound='nearest'

Essentially the mapping between boundary modes goes like this

interpol scipy.zoom numpy.pad
'replicate' or 'nearest' 'nearest' 'edge'
'dct1' or 'mirror' 'mirror' 'reflect'
'dct2' or 'reflect' 'reflect' 'symmetric'
'dst1' or 'antimirror' n/a n/a
'dst2' or 'antireflect' n/a n/a
'dft' or 'wrap' 'wrap' 'wrap'
'zero' or 'zeros' 'constant' 'constant'

with skimage following the np.pad convention.

What happens if you add bound='nearest' to your example?

balbasty avatar Sep 20 '23 11:09 balbasty

Thank you for the quick response. I added bound='nearest' to my code and get the same results. I think the difference may not come from edge paddings, here is my testing code on 2D example for order=3, and we can see that the difference can appear in the central area:

import matplotlib.pyplot as plt
import numpy as np
import torch
import interpol
from skimage.transform import resize

shape=[512, 512]
new_shape=[320,320]
a = np.random.rand(*shape)
at = torch.from_numpy(a).unsqueeze(0).unsqueeze(0)

b1=resize(a, new_shape, order=3, mode='edge', anti_aliasing=False)
b2=interpol.resize(at, shape=new_shape, anchor='edges', interpolation=3, bound='nearest')
b2=b2.squeeze().numpy()
diff = np.abs(b2-b1)
print(diff.sum())

plt.matshow(diff)
plt.colorbar()

image

thuzjf avatar Sep 21 '23 02:09 thuzjf