在 Python 中从扭曲的矩形 2D 网格到任意点的双线性插值

问题描述

手头的任务看似简单: 我有一个二维数据网格。数据可用于 X 和 Y 坐标的二维数组,以及我想要插入的输入变量。这意味着我可以使用矩形单元格绘制数据,这意味着可以使用双线性插值。不幸的是,数据没有与坐标精确对齐,也没有精确间隔。创建数据时涉及到一些数字,这意味着所有采样位置都有点偏离,并且单元格间距平滑但不均匀。

我想从这个输入网格插值到一组预定义的样本坐标(而不是简单地细化网格)。

简而言之,我的输入类型的示例是:

# a nice,regular grid
Xs,Ys = np.meshgrid(np.linspace(0,1,num=3),np.linspace(0,num=5))
# ...perturbed by some systematic and some random noise ...
X_in = Xs + np.random.normal(scale=0.03,size=(5,3))
# ...and some systematic deviation
Y_in = (Ys + np.random.normal(scale=0.03,3)))* (1 + Xs**1.5)

# and some variable at each node to interpolate
Z_in = np.random.normal(scale=1,3))

所以 (X_in,Y_in) 是形状 (n,m) 的数组,它定义了一个具有四边形单元的网格,而 Z_in 是另一个相同形状的数组,它在该网格中的每个节点提供一个值。我正在寻找一些 Python 库,它在这些单元格之间执行 Z_in 的双线性插值。

然而,到目前为止我发现的所有方法要么忽略矩形结构(并对数据进行三角测量,或通过任意点云拟合一些 2D 样条),要么需要一个完美的矩形和等距网格作为输入(我的是不是)。

似乎不适用的答案/方法示例:

This answer 建议使用 scipy.ndimage.map_coordinates -- 但它有效地使用了 2D 输入数据数组的索引作为坐标,这对我不起作用。

scipy.interpolate.interp2d 需要规则网格(由 1D X 和 Y 数组提供的节点位置)或不规则网格,该网格被展平,这意味着算法无法知道哪些节点形成单元格。这意味着它要么通过非结构化数据拟合一些样条,要么对其进行三角测量。并且它只插入到规则网格或单个点上。

scipy.interpolate.RectBivariateSpline 推荐用于网格数据的插值,但只接受与坐标系完美对齐的输入点。

还有一个用于插值的 Matplotlib 工具包,我认为它应该能够做这种事情,因为它也可以对矩形网格进行插值等高线图,但事实证明,即使 mpl_toolkits.basemap.interp 接受任意四边形网格作为插值目标,它不能将它们用作输入...... 仔细检查后发现,在绘制输入数据时,即使 matplotlib.plt.contour() 似乎也没有执行双线性插值:

plt.contour(X_in,Y_in,Z_in,levels=np.linspace(Z_in.min(),Z_in.max(),50))
plt.plot(X_in,'k-')
plt.plot(X_in.T,Y_in.T,'k-')

The input data,plotted,with grid lines marking the sampling locations and quadrilateral cells

如您所见,单元格内的轮廓线是直的,但使用双线性插值时,它们不应该是,并且某些单元格的中间不应该有那些空的四边形区域。我怀疑 Matplotlib 只在单元格边缘找到轮廓值,并在它们之间简单地绘制直线。

我发现两个 explanations of the maths 的双线性插值来自不完全对齐的网格,但我希望在某处遇到现成的实现,因为我确信这种任务并不罕见,并且 numpy 或 scipy 实现(如果存在)可能比我自己实现的任何东西都要快。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)