Интерполяция по нерегулярной сетке - PullRequest
21 голосов
/ 14 июля 2010

Итак, у меня есть три пустых массива, которые хранят широту, долготу и некоторое значение свойства в сетке - то есть у меня есть LAT (y, x), LON (y, x) и, скажем, температура T ( у, х), для некоторых пределов х и у. Сетка не обязательно регулярная - на самом деле она трехполюсная.

Затем я хочу интерполировать эти значения свойств (температуры) на набор различных точек широты / долготы (сохраняемых как широта l1 (т), лон1 (т) около 10 000 т ...), которые не попадают на фактические точки сетки. Я пробовал matplotlib.mlab.griddata, но это занимает слишком много времени (в конце концов, это не совсем то, что я делаю). Я также пробовал scipy.interpolate.interp2d, но я получаю MemoryError (мои сетки имеют размер около 400x400).

Есть ли какой-нибудь хитрый, желательно быстрый способ сделать это? Я не могу не думать, что ответ очевиден ... Спасибо !!

Ответы [ 6 ]

9 голосов
/ 14 июля 2010

Попробуйте комбинацию взвешивания обратного расстояния и scipy.spatial.KDTree , описанного в SO взвешенное по обратному расстоянию idw-interpolation-with-python . Kd-деревья прекрасно работают в 2d 3d ..., обратное взвешивание является плавным и локальным, а число k = ближайших соседей можно варьировать в зависимости от скорости / точности.

4 голосов
/ 05 мая 2014

Есть хороший пример обратного расстояния от Roger Veciana i Rovira вместе с некоторым кодом, использующим GDAL для записи в geotiff, если вы в этом.

Это грубо дляобычная сетка, но при условии, что вы сначала проецируете данные в пиксельную сетку с помощью pyproj или чего-то еще, при этом внимательно следя за тем, какая проекция используется для ваших данных.

Копия его алгоритма с тестом :

from math import pow  
from math import sqrt  
import numpy as np  
import matplotlib.pyplot as plt  

def pointValue(x,y,power,smoothing,xv,yv,values):  
    nominator=0  
    denominator=0  
    for i in range(0,len(values)):  
        dist = sqrt((x-xv[i])*(x-xv[i])+(y-yv[i])*(y-yv[i])+smoothing*smoothing);  
        #If the point is really close to one of the data points, return the data point value to avoid singularities  
        if(dist<0.0000000001):  
            return values[i]  
        nominator=nominator+(values[i]/pow(dist,power))  
        denominator=denominator+(1/pow(dist,power))  
    #Return NODATA if the denominator is zero  
    if denominator > 0:  
        value = nominator/denominator  
    else:  
        value = -9999  
    return value  

def invDist(xv,yv,values,xsize=100,ysize=100,power=2,smoothing=0):  
    valuesGrid = np.zeros((ysize,xsize))  
    for x in range(0,xsize):  
        for y in range(0,ysize):  
            valuesGrid[y][x] = pointValue(x,y,power,smoothing,xv,yv,values)  
    return valuesGrid  


if __name__ == "__main__":  
    power=1  
    smoothing=20  

    #Creating some data, with each coodinate and the values stored in separated lists  
    xv = [10,60,40,70,10,50,20,70,30,60]  
    yv = [10,20,30,30,40,50,60,70,80,90]  
    values = [1,2,2,3,4,6,7,7,8,10]  

    #Creating the output grid (100x100, in the example)  
    ti = np.linspace(0, 100, 100)  
    XI, YI = np.meshgrid(ti, ti)  

    #Creating the interpolation function and populating the output matrix value  
    ZI = invDist(xv,yv,values,100,100,power,smoothing)  


    # Plotting the result  
    n = plt.normalize(0.0, 100.0)  
    plt.subplot(1, 1, 1)  
    plt.pcolor(XI, YI, ZI)  
    plt.scatter(xv, yv, 100, values)  
    plt.title('Inv dist interpolation - power: ' + str(power) + ' smoothing: ' + str(smoothing))  
    plt.xlim(0, 100)  
    plt.ylim(0, 100)  
    plt.colorbar()  

    plt.show() 
1 голос
/ 14 июля 2010

Здесь есть куча вариантов, лучший из которых будет зависеть от ваших данных ... Однако я не знаю готового решения для вас

Вы говорите, что ваши входные данные взяты из трехполярных данных. Существует три основных случая структурирования этих данных.

  1. Выборка из трехмерной сетки в трехполюсном пространстве, проекция обратно на 2d LAT, данные LON.
  2. Выборка из 2-мерной сетки в трехполярном пространстве, проецируемая на данные 2-й LAT LON.
  3. Неструктурированные данные в трехполярном пространстве, спроецированные в данные 2d LAT LON

Самым простым из них является 2. Вместо интерполяции в пространстве LAT LON, «просто» преобразуйте вашу точку обратно в пространство источника и интерполируйте там.

Другой вариант, который работает для 1 и 2, - это поиск ячеек, которые отображаются из триполярного пространства, чтобы покрыть вашу точку выборки. (Вы можете использовать структуру типа BSP или сетки для ускорения этого поиска). Выберите одну из ячеек и вставьте в нее интерполяцию.

Наконец, есть куча неструктурированных вариантов интерполяции ... но они, как правило, медленные. Мой личный фаворит - это использовать линейную интерполяцию ближайших N точек, найти эти N точек снова можно с помощью сетки или BSP. Еще один хороший вариант - Делоне триангулировать неструктурированные точки и интерполировать полученную треугольную сетку.

Лично, если бы мой меш был случай 1, я бы использовал неструктурированную стратегию, так как я бы беспокоился о необходимости поиска в ячейках с перекрывающимися проекциями. Выбор «правильной» ячейки будет затруднен.

0 голосов
/ 29 января 2015

Существует библиотека FORTRAN с именем BIVAR , которая очень подходит для этой проблемы.С помощью нескольких модификаций вы можете использовать его в python, используя f2py.

Из описания:

BIVAR - это библиотека FORTRAN90, которая интерполирует разрозненные двумерные данные Хироши Акимы.

BIVAR принимает набор (X, Y) точек данных, рассеянных в 2D, со связанными значениями данных Z, и может построить функцию гладкой интерполяции Z (X, Y), которая согласуется с данными даннымии может оцениваться в других точках на плоскости.

0 голосов
/ 14 июля 2010

Правильно ли я считаю, что ваши сетки данных выглядят примерно так (красный - старые данные, синий - новые интерполированные данные)?

альтернативный текст http://www.geekops.co.uk/photos/0000-00-02%20%28Forum%20images%29/DataSeparation.png

Это может быть немного грубый подход, но как насчет рендеринга ваших существующих данных в виде растрового изображения (opengl сделает простую интерполяцию цветов для вас с настроенными правильными параметрами, и вы можете представить данные в виде треугольников, которые должны быть довольно быстрым). Затем вы могли бы отобрать пиксели в местах новых точек.

Кроме того, вы можете отсортировать первый набор точек пространственно, а затем найти ближайшие старые точки, окружающие вашу новую точку, и выполнить интерполяцию на основе расстояний до этих точек.

0 голосов
/ 14 июля 2010

Я предлагаю вам взглянуть на особенности интерполяции GRASS (пакет ГИС с открытым исходным кодом) (http://grass.ibiblio.org/gdp/html_grass62/v.surf.bspline.html). Это не в python, но вы можете переопределить его или взаимодействовать с кодом C.

...