如何在Python中执行双线性插值?

双线性插值是用两个变量估计函数的未知值以填充网格或二维空间中的间隙的过程。它是使用已知值并重复执行线性插值来填充间隙的方法。

它基于加权平均值并对最接近的值重新采样以估计新值。

插值本身有许多用途和应用。它主要用于图像处理、数据分析、生成音乐等等。

双线性插值也有许多应用。它用于图像处理、计算机视觉、数值分析、数字地形建模等。

请参阅本文以了解如何对一维空间进行插值。

双线性插值

让我们深入理解双线性插值的概念。如上所述,它是基于一组已知值估计新值的过程。

它考虑四个最近邻居的基于距离的加权平均值来插值所需的位置。让我们直观地理解这一点。

假设您有一个如下所示的二维值网格。

二维网格

假设您想在这些已知点之间找到一个点。我们计算每个已知点到新点之间的距离并计算加权平均值以估计新点可能是什么。让我们通过以下方式可视化网格。设 A 为要估计的新点。我们计算每个已知点到所需估计值的新点之间的距离。

可视化网格

让我们看看如何使用两个非常知名的库 numpy 和scipy来实现双线性插值。

使用 Numpy 进行双线性插值

numpy 中没有直接执行双线性插值的内置模块。当使用 Numpy 执行此类任务时,我们需要借助其数值函数手动计算所有内容。这有助于我们更好地理解这个过程。

我们将手动插入一个值,然后使用 matplotlib 将其可视化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 号
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import numpy as np
import matplotlib.pyplot as plt
def bi_interpolation(arr, x, y):
    height, width = arr.shape
    x1 = int(x)
    y1 = int(y)
    x2 = x1 + 1
    y2 = y1 + 1
    if x2 >= width:
        x2 = x1
    if y2 >= height:
        y2 = y1
 
    p11 = arr[y1, x1]
    p12 = arr[y2, x1]
    p21 = arr[y1, x2]
    p22 = arr[y2, x2]
 
    x_diff = x - x1
    y_diff = y - y1
 
    interpolated = (p11 * (1 - x_diff) * (1 - y_diff) +
                          p21 * x_diff * (1 - y_diff) +
                          p12 * (1 - x_diff) * y_diff +
                          p22 * x_diff * y_diff)
 
    return interpolated
 
arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])
x = 1.5
y = 1.5
interpolated = bi_interpolation(arr, x, y)
print("Interpolated value at ({x}, {y}): {interpolated_value}")
xx, yy = np.meshgrid(range(arr.shape[1]), range(arr.shape[0]))
plt.plot(xx, yy, 'ko')
for i in range(arr.shape[0]):
    for j in range(arr.shape[1]):
        plt.text(j, i, f'{arr[i, j]}', ha='center', va='center')
plt.plot(x, y, 'ro')
plt.text(x, y, f'Interpolated: {interpolated:.2f}', ha='left', va='bottom')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Bilinear Interpolation')
plt.show()

这是解释。

首先,我们导入两个 Python 库——numpy 和 matplotlib。

接下来,我们定义一个函数bi-interpolation,对名为 arr 的数组在 x 和 y 坐标处执行插值。

x1 = int(x)
y1 = int(y)
x2 = x1 + 1
y2 = y1 + 1

x 和 y 值将转换为整数,因此如果有任何小数值,则会被截断。整数值存储在名为 x1 和 y1 的变量中。

x2 和 y2 是靠近给定点(x 和 y)的点。

if x2 >= width:
    x2 = x1
if y2 >= height:
      y2 = y1

此代码片段确保点不会超出数组的尺寸,并根据数组的高度和宽度进行调整。

p11 = arr[y1, x1]
p12 = arr[y2, x1]
p21 = arr[y1, x2]
p22 = arr[y2, x2]

这将创建我们插入新点所需的点。

x_diff 和 y_diff 存储实际点与我们给出的点(x 和 y)之间的差异。

接下来的四行将权重分配给新点周围的点。结果存储在名为 interpolated 的变量中。函数到此结束。

arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])
x = 1.5
y = 1.5
interpolated = bi_interpolation(arr, x, y)

我们传递给函数的数组和我们想要插入新点的坐标在接下来的两行中初始化。使用指定值调用该函数。

接下来,我们打印插值并绘制插值后的网格。

Interpolated value at (1.5, 1.5): 7.0
使用 Numpy 进行双线性插值

使用 SciPy 进行双线性插值

与 numpy 库不同,scipy 库确实有专用的插值方法。我们将使用该方法并插入一个新点。只需几行代码即可。

1
2
3
4
5
6
7
8
import numpy as np
from scipy.interpolate import griddata
points = np.array([[0, 0], [0, 1], [1, 0], [1, 1],[2,1],[2,2],[1,2],[0,2]]) 
values = np.array([1, 4, 7, 9,3,8,2,7]) 
x = 0.5 
y = 0.5
interpolated_value = griddata(points, values, (x, y), method='nearest')
print("Interpolated value at ({x}, {y}): {interpolated_value}")

我们导入 numpy 库和“scipy”库的“griddata”模块进行插值。

我们正在定义轴的坐标点及其相应的值。接下来,我们指定插值点的坐标。

interpolated_value 存储使用最近插值器的 griddata 方法的插值结果。

打印插值值。

使用 Scipy 进行双线性插值

我们可以借助 matplotlib 可视化插值后的网格。

1
2
3
4
5
6
7
8
9
10
plt.plot(points[:, 0], points[:, 1], 'ko', label='Input Points')
for i, val in enumerate(values):
    plt.text(points[i, 0], points[i, 1], str(val), ha='center', va='bottom')
plt.plot(x, y, 'ro', label='Interpolated Point')
plt.text(x, y, f'Interpolated: {interpolated_value:.2f}', ha='left', va='bottom')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Bilinear Interpolation')
plt.legend()
plt.show()
可视化

结论

总之,我们讨论了双线性插值的定义及其广泛应用。双线性插值基于加权平均值,并对最接近的值重新采样以估计新值。它重复执行线性插值以填充间隙。

我们已经学习了如何使用两个库(numpy 和 scipy)执行双线性插值。虽然 numpy 没有内置的方法来执行插值,但我们可以使用它的其他函数来手动执行插值。

scipy 库确实有一个专门用于执行插值的函数,并且执行插值要容易得多,因为我们所要做的就是创建一个网格并指定点。

我们还使用 matplotlib 库来可视化结果。

参考

您可以在此处找到 SciPy 文档。

Numpy 文档。

您可以在此堆栈溢出答案链中找到双线性插值的其他方法。