SciPy和PyTorch都有多种插值2D图像的方法。然而,对于三次插值,它们似乎没有做同样的事情。为什么它们如此不同?
到目前为止,我发现下面的代码似乎在order=1
/mode=linear
/mode=bilinear
上做同样的事情(直到浮点错误):
scipy.interpolate.interpn
scipy.ndimage.map_coordinates
torch.nn.functional.interpolate
与align_corners=True
torch.nn.functional.grid_sample
与align_corners=True
然而,在顺序3中,它们都彼此不同。
由于有这么多不同的功能,我将接受部分答案,解释其中一些之间的差异。
这是一个(尝试的)最小示例(仍然很长)。这个例子只是简单地使用插值方法对随机图像进行上采样。
# Computations
import numpy as np
import numpy.typing
import torch
from scipy.interpolate import interpn
from scipy.ndimage import map_coordinates
from torch.nn.functional import interpolate, grid_sample
# Visualizations
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
def get_interpolated_values(
original_size: tuple[int, int],
sample_size: tuple[int, int],
order: int,
) -> list[np.typing.NDArray], list[str]:
'''Returns list of interpolated images with labels for which interpolation
method was used.'''
# Initialize source values for interpolation
values = np.random.rand(*original_size)
order2str = [
'nearest',
'linear',
None,
'cubic',
]
# Initialize data collection
labels = []
interpolated_values = []
# Scipy interpn
labels.append('scipy.interpn')
interpolated_values.append(
interpn(
points=(
np.mgrid[0 : original_size[0]],
np.mgrid[0 : original_size[1]],
),
values=values,
xi=np.stack(np.mgrid[
0 : original_size[0] - 1 : sample_size[0] * 1j,
0 : original_size[1] - 1 : sample_size[1] * 1j,
], axis=-1),
method=order2str[order],
bounds_error=True,
)
)
# Scipy map_coordinates
labels.append('scipy.map_coordinates')
interpolated_values.append(
map_coordinates(
input=values,
coordinates=np.mgrid[
0 : original_size[0] - 1 : sample_size[0] * 1j,
0 : original_size[1] - 1 : sample_size[1] * 1j,
],
order=order,
mode='constant',
)
)
# Torch interpolate with align_corners
value_tensor = torch.from_numpy(values)[None, None, ...]
labels.append('torch.interpolate')
interpolated_values.append(
interpolate(
input=value_tensor,
size=sample_size,
align_corners=True,
mode="bi" + order2str[order],
).squeeze().numpy()
)
# Torch grid sample with corners
labels.append('torch.grid_sample')
interpolated_values.append(
grid_sample(
input=value_tensor,
grid=torch.from_numpy(
np.mgrid[
-1 : 1 : sample_size[0] * 1j,
-1 : 1 : sample_size[1] * 1j,
],
).moveaxis(0, -1).unsqueeze(0).flip(-1),
padding_mode='zeros',
mode="bi" + order2str[order],
align_corners=True,
).squeeze().numpy()
)
return interpolated_values, labels
def visualize(interpolated_values, labels):
# Visualize each interpolated result
fig, ax_row = plt.subplots(1, len(interpolated_values))
for i_ax, ax in enumerate(ax_row):
ax.set_title(labels[i_ax])
im = ax.imshow(interpolated_values[i_ax], vmin=0, vmax=1)
plt.colorbar(im)
# Visualise differences between methods
fig, ax_grid = plt.subplots(
len(interpolated_values),
len(interpolated_values),
)
fig.suptitle('Interpolation differences')
for i_ax, ax_row in enumerate(ax_grid):
for j_ax, ax in enumerate(ax_row):
if i_ax == j_ax:
# Add label in diagonal
ax.text(
*((n - 1) / 2 for n in interpolated_values[i_ax].shape),
s=labels[i_ax],
ha='center',
va='center',
)
# Plot difference matrix with colorbar
diff = interpolated_values[i_ax] - interpolated_values[j_ax]
im = ax.imshow(np.abs(diff))
plt.colorbar(im)
def main():
interpolated_values, labels = get_interpolated_values(
original_size = (4, 4),
sample_size = (5, 5),
order = 3,
)
visualize(interpolated_values, labels)
plt.show()
if __name__ == "__main__":
main()
以下是3阶的可视化绝对差:
1条答案
按热度按时间f5emj3cl1#
(部分答案)interpn(它是RegularGridInterpolator上的一个方便的 Package 器)和www.example.com _coordinates之间的区别ndimage.map是,后者假设等距整数值网格,而前者允许更一般的网格间距(仍然规则,但可以在维度之间变化)。下面是scipy文档中的一个例子:
https://docs.scipy.org/doc/scipy/tutorial/interpolate/ND_regular_grid.html