Algorithm 填充二维阵列的间隙

Algorithm 填充二维阵列的间隙,algorithm,interpolation,bicubic,bilinear-interpolation,Algorithm,Interpolation,Bicubic,Bilinear Interpolation,我有一个稀疏填充的数组,如下所示。是否有一种算法可以用线性意义上的值填充所有空格?即,根据周围的原始值推断 我看过双线性插值和双三次插值,但还有其他的吗 | 1 | 2 | 3 | 4 | 5 | 6 | 7 --------------------------------------------------------------------------------- 1 | 2 | 3

我有一个稀疏填充的数组,如下所示。是否有一种算法可以用线性意义上的值填充所有空格?即,根据周围的原始值推断

我看过双线性插值和双三次插值,但还有其他的吗

     |    1    |    2   |    3    |    4    |    5    |    6    |    7
---------------------------------------------------------------------------------
1    | 
2    |
3    |             55
4    |             50                                     12         6
5    |             45                                                19
6    |             xxx 
7    |             35        45       50        yyy
8    |
9    |
10   |
11   |
12   |                       zzz
13   |
14   |
15   |
例如,我希望xxx在40附近,yyy在50附近。但是,zzz可能有一个更随机的值。不过请注意:我希望填充每个空格,而不仅仅是xxx、yyy和zzz。并且能够对任何人口稀少的阵列执行此操作


有这样一种算法吗?

有一百万种这样的算法存在。首先,你有一些已知值的字典,比如:

known_values = {
    (2, 3): 55.0,
    (2, 4): 50.0,
    (2, 5): 45.0,
    (2, 7): 35.0,
    (3, 7): 45.0,
    (4, 7): 50.0,
    (6, 4): 12.0,
    (7, 4): 6.0,
    (7, 5): 19.0,
}
def interpolate(known_values, p):
     total_weight = 0.0
     total_sum = 0.0
     for q, value in known_values:
         if p == q:
             return value
         d_square = (p[0] - q[0])**2 + (p[1] - q[1])**2
         total_weight = total_weight + 1.0 / d_square
         total_sum = total_sum + value / d_square
     return total_sum/total_weight
最简单的方法是说,任何点的值都是所有填充点的加权平均值。按距离平方的1/2对其进行称重。因此,在上述情况下,您的代码如下:

known_values = {
    (2, 3): 55.0,
    (2, 4): 50.0,
    (2, 5): 45.0,
    (2, 7): 35.0,
    (3, 7): 45.0,
    (4, 7): 50.0,
    (6, 4): 12.0,
    (7, 4): 6.0,
    (7, 5): 19.0,
}
def interpolate(known_values, p):
     total_weight = 0.0
     total_sum = 0.0
     for q, value in known_values:
         if p == q:
             return value
         d_square = (p[0] - q[0])**2 + (p[1] - q[1])**2
         total_weight = total_weight + 1.0 / d_square
         total_sum = total_sum + value / d_square
     return total_sum/total_weight
只要矩阵中有任何填充的数据,该解决方案就会起作用

然而,从你问这个问题的方式来看,你可能需要一个平滑的插值,它在任何一个小区域内近似线性。一种方法是查找
(a,b,c)
,使函数
a*x+b*y+c
最小化误差平方的加权和,权重为从所需点到已知点的距离的四次方。(前两个幂次可以撤消面积的平方,其他两个幂次的权重更大。)

这里使用最小二乘法计算误差的原因是数学计算简单。当
a
b
c
中的微小变化不会对值产生太大变化时,即偏导数为0,您将精确地最小化。因此,这三个偏导数给出了三组线性方程组。在3个变量中求解3个方程相当容易


然而,推导过程又长又乱。如果你想尝试,你应该看看通常的最小二乘法推导,并尝试通过细节工作。然后尝试实现它。但是,只有当你真的想尝试对远离数据点的点进行线性投影时,才可以尝试这种方法。

有一百万种这样的算法存在。首先,你有一些已知值的字典,比如:

known_values = {
    (2, 3): 55.0,
    (2, 4): 50.0,
    (2, 5): 45.0,
    (2, 7): 35.0,
    (3, 7): 45.0,
    (4, 7): 50.0,
    (6, 4): 12.0,
    (7, 4): 6.0,
    (7, 5): 19.0,
}
def interpolate(known_values, p):
     total_weight = 0.0
     total_sum = 0.0
     for q, value in known_values:
         if p == q:
             return value
         d_square = (p[0] - q[0])**2 + (p[1] - q[1])**2
         total_weight = total_weight + 1.0 / d_square
         total_sum = total_sum + value / d_square
     return total_sum/total_weight
最简单的方法是说,任何点的值都是所有填充点的加权平均值。按距离平方的1/2对其进行称重。因此,在上述情况下,您的代码如下:

known_values = {
    (2, 3): 55.0,
    (2, 4): 50.0,
    (2, 5): 45.0,
    (2, 7): 35.0,
    (3, 7): 45.0,
    (4, 7): 50.0,
    (6, 4): 12.0,
    (7, 4): 6.0,
    (7, 5): 19.0,
}
def interpolate(known_values, p):
     total_weight = 0.0
     total_sum = 0.0
     for q, value in known_values:
         if p == q:
             return value
         d_square = (p[0] - q[0])**2 + (p[1] - q[1])**2
         total_weight = total_weight + 1.0 / d_square
         total_sum = total_sum + value / d_square
     return total_sum/total_weight
只要矩阵中有任何填充的数据,该解决方案就会起作用

然而,从你问这个问题的方式来看,你可能需要一个平滑的插值,它在任何一个小区域内近似线性。一种方法是查找
(a,b,c)
,使函数
a*x+b*y+c
最小化误差平方的加权和,权重为从所需点到已知点的距离的四次方。(前两个幂次可以撤消面积的平方,其他两个幂次的权重更大。)

这里使用最小二乘法计算误差的原因是数学计算简单。当
a
b
c
中的微小变化不会对值产生太大变化时,即偏导数为0,您将精确地最小化。因此,这三个偏导数给出了三组线性方程组。在3个变量中求解3个方程相当容易


然而,推导过程又长又乱。如果你想尝试,你应该看看通常的最小二乘法推导,并尝试通过细节工作。然后尝试实现它。但是,只有当你真的想做一个线性投影到远离你有数据的点的时候,才可以试着这样做。

这个问题可以被看作是一个“双变量插值”问题,在这个领域有大量的研究。您可以在Wiki中搜索“多元插值”,并在“二维”部分下查找算法


在各种方法中,双线性/双三次插值需要数据形成网格,而您的数据却不是这样。Delaunay三角剖分方法不适用于您案例中需要的外推。逆加权距离法易于实现,适合外推,但结果往往不令人满意。我个人建议使用径向基函数,只要你没有太多的数据点(比如数千个)。

这个问题可以看作是一个“双变量插值”问题,在这个领域有大量的研究。您可以在Wiki中搜索“多元插值”,并在“二维”部分下查找算法


在各种方法中,双线性/双三次插值需要数据形成网格,而您的数据却不是这样。Delaunay三角剖分方法不适用于您案例中需要的外推。逆加权距离法易于实现,适合外推,但结果往往不令人满意。我个人建议使用径向基函数,只要数据点不太多(比如数千个)。

我已经在GitHub上上传了我自己的解决方案,它使用薄板样条线方法:


我在GitHub上上传了我自己的解决方案,它使用薄板样条线方法: