使用Scipy.ndimage旋转含np.nan的数组出现值异常问题
问题描述
我有一个来自.tif格式LiDAR表面的高程数组,示例数组如下:
from scipy.ndimage import rotate import numpy as np test_surface_nan = [[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], [np.nan, np.nan, np.nan, 1, np.nan, np.nan, np.nan], [np.nan, np.nan, 1, 2, 1, np.nan, np.nan], [np.nan, 1, 2, 3, 2, 1, np.nan], [np.nan, np.nan, 1, 2, 1, np.nan, np.nan], [np.nan, np.nan, np.nan, 1, np.nan, np.nan, np.nan], [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan]]
尝试执行以下代码将数组旋转45度,使有效值起始于第1行:
test_surface_array_nan = np.array(test_surface_nan) test_surface_array_nan_rotated = rotate(test_surface_array_nan,45,reshape=True)
但得到的结果中,原大于0的有效值变为np.nan,原np.nan元素变为0,与预期结果不符:
maybe_test_surface_nan = [ [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], [np.nan, 1, np.nan, 1, np.nan, 1, np.nan], [np.nan, np.nan, 2, np.nan, 2, np.nan, np.nan], [np.nan, 1, np.nan, 3, np.nan, 1, np.nan], [np.nan, np.nan, 2, np.nan, 2, np.nan, np.nan], [np.nan, 1, np.nan, 1, np.nan, 1, np.nan], [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan]]
问题原因
scipy.ndimage.rotate默认使用三阶样条插值(order=3),当数组包含np.nan时,插值计算会因NaN的传播特性,将原本的有效值也转换成NaN。- 默认填充模式为
mode='reflect',但NaN的存在会导致填充逻辑失效,旋转后的空白区域最终被0替代,出现原NaN区域变成0的情况。
解决办法
调整rotate函数的参数,避免NaN传播并指定正确的填充值:
- 使用最近邻插值(
order=0),阻止插值过程中NaN破坏有效值; - 设置填充模式为
mode='constant',并指定填充值为np.nan,确保空白区域用NaN填充而非0; - 保留
reshape=True适配旋转后的数组尺寸。
修改后的代码示例:
from scipy.ndimage import rotate import numpy as np test_surface_nan = [[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], [np.nan, np.nan, np.nan, 1, np.nan, np.nan, np.nan], [np.nan, np.nan, 1, 2, 1, np.nan, np.nan], [np.nan, 1, 2, 3, 2, 1, np.nan], [np.nan, np.nan, 1, 2, 1, np.nan, np.nan], [np.nan, np.nan, np.nan, 1, np.nan, np.nan, np.nan], [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan]] test_surface_array_nan = np.array(test_surface_nan) # 调整参数后的旋转代码 test_surface_array_nan_rotated = rotate( test_surface_array_nan, 45, reshape=True, order=0, # 最近邻插值 mode='constant', cval=np.nan # 空白区域填充NaN ) print(test_surface_array_nan_rotated)
注:旋转后数组尺寸会变为10x10(原7x7旋转45度的最小外接矩形),若需保持7x7尺寸可去掉reshape=True,但会裁剪部分内容。
内容的提问来源于stack exchange,提问作者Patstro
相关产品推荐
相关产品推荐

