如何在Python中执行双线性插值
我想使用 python 执行双线性插值。
我想要插入高度的示例 GPS 点是:
B = 54.4786674627
L = 17.0470721369
使用具有已知坐标和高度值的四个相邻点:
n = [(54.5, 17.041667, 31.993), (54.5, 17.083333, 31.911), (54.458333, 17.041667, 31.945), (54.458333, 17.083333, 31.866)]
z01 z11
z
z00 z10
and here's my primitive attempt:
import math
z00 = n[0][2]
z01 = n[1][2]
z10 = n[2][2]
z11 = n[3][2]
c = 0.016667 #grid spacing
x0 = 56 #latitude of origin of grid
y0 = 13 #longitude of origin of grid
i = math.floor((L-y0)/c)
j = math.floor((B-x0)/c)
t = (B - x0)/c - j
z0 = (1-t)*z00 + t*z10
z1 = (1-t)*z01 + t*z11
s = (L-y0)/c - i
z = (1-s)*z0 + s*z1
where z0 and z1
z01 z0 z11
z
z00 z1 z10
I get 31.964 but from other software I get 31.961.
Is my script correct?
Can You provide another approach?
2022 年编辑:
我要感谢所有在这个问题发表十多年后仍然给出新答案的人。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这是您可以使用的可重用函数。它包括文档测试和数据验证:
您可以通过添加来运行测试代码:
在数据集上运行插值会产生:
Here's a reusable function you can use. It includes doctests and data validation:
You can run test code by adding:
Running the interpolation on your dataset produces:
不确定这是否有很大帮助,但在使用 scipy 进行线性插值时我得到了不同的值:
Not sure if this helps much, but I get a different value when doing linear interpolation using scipy:
受此处的启发,我想出了以下代码片段。该 API 针对多次重复使用同一个表进行了优化:
您可以像这样使用它:
此版本没有错误检查,如果您尝试在索引边界(或超出索引边界)使用它,您将遇到麻烦。有关代码的完整版本,包括错误检查和可选的外推,请查看此处。
Inspired from here, I came up with the following snippet. The API is optimized for reusing a lot of times the same table:
You can use it like this:
This version has no error checking and you will run into trouble if you try to use it at the boundaries of the indexes (or beyond). For the full version of the code, including error checking and optional extrapolation, look here.
基于此公式的 numpy 实现:
输入:
这里,
x_
是[x0,x1]
的列表,y_
是[y0,y1]
的列表输出:
A numpy implementation of based on this formula:
Input:
Here,
x_
is list of[x0,x1]
andy_
is list of[y0,y1]
Output:
也可以参考matplotlib中的interp函数。
You can also refer to the interp function in matplotlib.
我认为执行
floor
函数的要点是,通常您希望插入一个坐标位于两个离散坐标之间的值。然而,您似乎已经有了最近点的实际坐标值,这使得数学变得简单。从您的示例翻译时可能存在一些错误的逻辑,但其要点是您可以根据每个点比其他邻居更接近插值目标点的程度来对每个点进行加权。
I think the point of doing a
floor
function is that usually you're looking to interpolate a value whose coordinate lies between two discrete coordinates. However you seem to have the actual real coordinate values of the closest points already, which makes it simple math.There might be a bit of erroneous logic in translating from your example, but the gist of it is you can weight each point based on how much closer it is to the interpolation goal point than its other neighbors.
这与此处定义的解决方案相同,但应用于某些函数并与中可用的
interp2d
进行比较西皮。我们使用 numba 库使插值函数比 Scipy 实现更快。我们将其设置为一个相当大的插值数组来评估每种方法的性能。
示例函数为
性能测试
没有 numba 库
bilinear_interpolation
函数的 Python,在本例中,与numba
版本相同,只是我们进行了更改prange
在 for 循环中使用 python 正常range
,并删除函数装饰器jit
每个循环给出 7.15 秒 ± 107 毫秒(平均值 ± 标准差) 7 次运行,每次 1 次循环)
Python 与 numba numba
每个循环给出 2.65 ms ± 70.5 µs(7 次运行的平均值 ± 标准差,每次 100 次循环)
Scipy 实现
每个循环给出 6.63 ms ± 145 µs(7 次运行的平均值 ± 标准偏差,每次 100 个循环)
性能测试在“Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz”上执行
This is the same solution as defined here but applied to some function and compared with
interp2d
available in Scipy. We use numba library to make the interpolation function even faster than Scipy implementation.We make it quite a large interpolation array to assess the performance of each method.
The sample function is,
Performance Test
Python without numba library
bilinear_interpolation
function, in this case, is the same asnumba
version except that we changeprange
with python normalrange
in the for loop, and remove function decoratorjit
Gives 7.15 s ± 107 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Python with numba numba
Gives 2.65 ms ± 70.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Scipy implementation
Gives 6.63 ms ± 145 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Performance tests are performed on 'Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz'
我建议采用以下解决方案:
I suggest the following solution:
解决方案此处显示了双线性插值,我应用了他的方法此处。但我对这种方法的适应,简单地计算欧几里德距离到所有四个角的接近度,并将其用作简单的加权平均值,效果更好(我的适应在同一链接中)。
A solution here shows bilinear interpolation, I applied his method here. But my adaption of this method, simply computing a proximity to all four corners from Euclidian distance and using that as simple weighted average works much better (my adaption is in the same link).