26

Pythonを使用してblinear補間を実行したいと思います。
高さを補間したいGPSポイントの例は次のとおりです。

B = 54.4786674627
L = 17.0470721369

既知の座標と高さの値を持つ 4 つの隣接点を使用します。

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

そして、ここに私の原始的な試みがあります:
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

ここで z0 と z1
z01  z0  z11

     z
z00  z1   z10

私は 31.964 を取得しますが、他のソフトウェアからは 31.961 を取得します。
私のスクリプトは正しいですか?
別のアプローチを提供できますか?



2022 年編集:
この質問の公開から 10 年以上経った今でも、新しい回答を提供してくださっているすべての方々に感謝します。

4

8 に答える 8

47

これは、使用できる再利用可能な関数です。これには、doctests とデータ検証が含まれます。

def bilinear_interpolation(x, y, points):
    '''Interpolate (x,y) from values associated with four points.

    The four points are a list of four triplets:  (x, y, value).
    The four points can be in any order.  They should form a rectangle.

        >>> bilinear_interpolation(12, 5.5,
        ...                        [(10, 4, 100),
        ...                         (20, 4, 200),
        ...                         (10, 6, 150),
        ...                         (20, 6, 300)])
        165.0

    '''
    # See formula at:  http://en.wikipedia.org/wiki/Bilinear_interpolation

    points = sorted(points)               # order points by x, then by y
    (x1, y1, q11), (_x1, y2, q12), (x2, _y1, q21), (_x2, _y2, q22) = points

    if x1 != _x1 or x2 != _x2 or y1 != _y1 or y2 != _y2:
        raise ValueError('points do not form a rectangle')
    if not x1 <= x <= x2 or not y1 <= y <= y2:
        raise ValueError('(x, y) not within the rectangle')

    return (q11 * (x2 - x) * (y2 - y) +
            q21 * (x - x1) * (y2 - y) +
            q12 * (x2 - x) * (y - y1) +
            q22 * (x - x1) * (y - y1)
           ) / ((x2 - x1) * (y2 - y1) + 0.0)

以下を追加することで、テスト コードを実行できます。

if __name__ == '__main__':
    import doctest
    doctest.testmod()

データセットで内挿を実行すると、次が生成されます。

>>> 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),
    ]
>>> bilinear_interpolation(54.4786674627, 17.0470721369, n)
31.95798688313631
于 2011-12-28T23:14:56.063 に答える
10

これが役立つかどうかはわかりませんが、scipy を使用して線形補間を行うと、別の値が得られます。

>>> import numpy as np
>>> from scipy.interpolate import griddata
>>> n = np.array([(54.5, 17.041667, 31.993),
                  (54.5, 17.083333, 31.911),
                  (54.458333, 17.041667, 31.945),
                  (54.458333, 17.083333, 31.866)])
>>> griddata(n[:,0:2], n[:,2], [(54.4786674627, 17.0470721369)], method='linear')
array([ 31.95817681])
于 2011-12-28T22:59:41.500 に答える
7

hereからインスピレーションを得て、次のスニペットを思いつきました。API は、同じテーブルを何度も再利用できるように最適化されています。

from bisect import bisect_left

class BilinearInterpolation(object):
    """ Bilinear interpolation. """
    def __init__(self, x_index, y_index, values):
        self.x_index = x_index
        self.y_index = y_index
        self.values = values

    def __call__(self, x, y):
        # local lookups
        x_index, y_index, values = self.x_index, self.y_index, self.values

        i = bisect_left(x_index, x) - 1
        j = bisect_left(y_index, y) - 1

        x1, x2 = x_index[i:i + 2]
        y1, y2 = y_index[j:j + 2]
        z11, z12 = values[j][i:i + 2]
        z21, z22 = values[j + 1][i:i + 2]

        return (z11 * (x2 - x) * (y2 - y) +
                z21 * (x - x1) * (y2 - y) +
                z12 * (x2 - x) * (y - y1) +
                z22 * (x - x1) * (y - y1)) / ((x2 - x1) * (y2 - y1))

次のように使用できます。

table = BilinearInterpolation(
    x_index=(54.458333, 54.5), 
    y_index=(17.041667, 17.083333), 
    values=((31.945, 31.866), (31.993, 31.911))
)

print(table(54.4786674627, 17.0470721369))
# 31.957986883136307

このバージョンにはエラー チェックがなく、インデックスの境界 (またはそれを超えて) で使用しようとすると問題が発生します。エラー チェックとオプションの外挿を含む完全なバージョンのコードについては、こちらを参照してください

于 2013-12-26T19:03:05.383 に答える
3

matplotlib の interp 関数も参照できます。

于 2012-01-19T13:14:07.647 に答える
2

関数を実行するポイントfloorは、通常、座標が2つの離散座標の間にある値を補間しようとすることだと思います。ただし、最も近い点の実際の実際の座標値が既にあるように見えるため、単純な計算になります。

z00 = n[0][2]
z01 = n[1][2]
z10 = n[2][2]
z11 = n[3][2]

# Let's assume L is your x-coordinate and B is the Y-coordinate

dx = n[2][0] - n[0][0] # The x-gap between your sample points
dy = n[1][1] - n[0][1] # The Y-gap between your sample points

dx1 = (L - n[0][0]) / dx # How close is your point to the left?
dx2 = 1 - dx1              # How close is your point to the right?
dy1 = (B - n[0][1]) / dy # How close is your point to the bottom?
dy2 = 1 - dy1              # How close is your point to the top?

left = (z00 * dy1) + (z01 * dy2)   # First interpolate along the y-axis
right = (z10 * dy1) + (z11 * dy2)

z = (left * dx1) + (right * dx2)   # Then along the x-axis

あなたの例からの翻訳には少し誤った論理があるかもしれませんが、その要点は、他の近隣点よりも補間目標点にどれだけ近いかに基づいて、各点に重みを付けることができるということです。

于 2011-12-28T22:06:03.367 に答える