libreria interpolacion instalar hermite como aplicaciones python math coordinates interpolation geo

interpolacion - Cómo realizar una interpolación bilineal en Python



scipy python 3 (5)

Aquí hay una función reutilizable que puedes usar. Incluye doctests y validación de datos:

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)

Puede ejecutar el código de prueba agregando:

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

Ejecutar la interpolación en su conjunto de datos produce:

>>> 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

Me gustaría realizar la interpolación blinear usando python.
Ejemplo de punto gps para el que quiero interpolar altura es:

B = 54.4786674627 L = 17.0470721369

utilizando cuatro puntos adyacentes con coordenadas conocidas y valores de altura:

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


Y aquí está mi intento primitivo:

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


donde z0 y z1

z01 z0 z11 z z00 z1 z10


Obtengo 31.964 pero de otro software obtengo 31.961.
¿Mi guión es correcto?
¿Puede usted proporcionar otro enfoque?


Creo que el punto de hacer una función de floor es que generalmente se busca interpolar un valor cuya coordenada se encuentra entre dos coordenadas discretas. Sin embargo, parece que ya tiene los valores reales de coordenadas reales de los puntos más cercanos, lo que hace que sea matemática simple.

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

Puede haber un poco de lógica errónea en la traducción de su ejemplo, pero la esencia de esto es que puede ponderar cada punto en función de cuánto más cerca esté del punto de la interpolación que sus otros vecinos.


Inspirado desde here , se me ocurrió el siguiente fragmento. La API está optimizada para reutilizar muchas veces la misma tabla:

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))

Puedes usarlo así:

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

Esta versión no tiene comprobación de errores y se encontrará con problemas si intenta usarla en los límites de los índices (o más allá). Para obtener la versión completa del código, incluida la verificación de errores y la extrapolación opcional, consulte here .


No estoy seguro de si esto ayuda mucho, pero obtengo un valor diferente cuando hago interpolación lineal usando 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])