使用SciPy ndimage.zoom处理含NaN数组时高阶插值全为NaN的解决方法
解决scipy.ndimage.zoom高阶插值时NaN全填充的问题
scipy.ndimage.zoom的高阶插值(二次、三次)输出全NaN的核心原因是该工具不原生支持忽略NaN值。高阶插值需要更大的邻域窗口计算新像素值,只要窗口内存在一个NaN,计算结果就会被污染成NaN;而线性插值的窗口更小,在你的测试案例中刚好有效点能覆盖计算需求,所以能得到部分有效结果。
以下是两种可行的解决方案:
方案一:用scipy.interpolate.griddata实现忽略NaN的高阶插值
griddata可直接基于有效点进行插值,自动忽略NaN区域,完全匹配你的需求:
import numpy as np from scipy.interpolate import griddata z_test = np.array([[0, 1, 3], [1, 3, 5], [2, 4, np.nan]]) zoom_factor = 20 # 提取原始数组中的有效点坐标与对应值 y, x = np.indices(z_test.shape) valid_mask = ~np.isnan(z_test) points = np.column_stack((x[valid_mask], y[valid_mask])) values = z_test[valid_mask] # 生成缩放后的目标网格坐标 new_shape = (z_test.shape[0] * zoom_factor, z_test.shape[1] * zoom_factor) new_y, new_x = np.indices(new_shape) new_points = np.column_stack((new_x.ravel(), new_y.ravel())) # 执行二次/三次插值 quadratic_interp = griddata(points, values, new_points, method='quadratic').reshape(new_shape) cubic_interp = griddata(points, values, new_points, method='cubic').reshape(new_shape)
方案二:先补全NaN再用ndimage.zoom进行高阶插值
如果一定要使用ndimage.zoom工具,可以先通过插值补全原始数组中的NaN,再执行缩放:
import numpy as np from scipy import ndimage from skimage.restoration import inpaint_biharmonic z_test = np.array([[0, 1, 3], [1, 3, 5], [2, 4, np.nan]]) zoom_factor = 20 # 用双调和插值补全NaN区域 mask = np.isnan(z_test) filled_z = inpaint_biharmonic(z_test, mask, channel_axis=None) # 执行二次/三次缩放 quadratic_zoom = ndimage.zoom(filled_z, zoom=zoom_factor, order=2) cubic_zoom = ndimage.zoom(filled_z, zoom=zoom_factor, order=3)
内容的提问来源于stack exchange,提问作者Marcus K.
相关产品推荐
相关产品推荐

