J'ai un raster avec lequel j'aimerais faire quelques interpolations ponctuelles. Voici où j'en suis:
from osgeo import gdal
from numpy import array
# Read raster
source = gdal.Open('my_raster.tif')
nx, ny = source.RasterXSize, source.RasterYSize
gt = source.GetGeoTransform()
band_array = source.GetRasterBand(1).ReadAsArray()
# Close raster
source = None
# Compute mid-point grid spacings
ax = array([gt[0] + ix*gt[1] + gt[1]/2.0 for ix in range(nx)])
ay = array([gt[3] + iy*gt[5] + gt[5]/2.0 for iy in range(ny)])
Jusqu'à présent, j'ai essayé la fonction interp2d de SciPy :
from scipy import interpolate
bilinterp = interpolate.interp2d(ax, ay, band_array, kind='linear')
cependant, j'obtiens une erreur de mémoire sur mon système Windows 32 bits avec un raster 317 × 301:
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "C:\Python25\Lib\site-packages\scipy\interpolate\interpolate.py", line 125, in __init__
self.tck = fitpack.bisplrep(self.x, self.y, self.z, kx=kx, ky=ky, s=0.)
File "C:\Python25\Lib\site-packages\scipy\interpolate\fitpack.py", line 873, in bisplrep
tx,ty,nxest,nyest,wrk,lwrk1,lwrk2)
MemoryError
Je l'admets, j'ai une confiance limitée dans cette fonction SciPy, car les paramètres bounds_error
ou fill_value
ne fonctionnent pas comme indiqué. Je ne vois pas pourquoi je devrais avoir une erreur de mémoire, car mon raster est 317 × 301, et l' algorithme bilinéaire ne devrait pas être difficile.
Quelqu'un a-t-il rencontré un bon algorithme d'interpolation bilinéaire, de préférence en Python, éventuellement adapté avec NumPy? Des astuces ou des conseils?
(Remarque: l' algorithme d'interpolation du plus proche voisin est un gâteau facile:
from numpy import argmin, NAN
def nearest_neighbor(px, py, no_data=NAN):
'''Nearest Neighbor point at (px, py) on band_array
example: nearest_neighbor(2790501.920, 6338905.159)'''
ix = int(round((px - (gt[0] + gt[1]/2.0))/gt[1]))
iy = int(round((py - (gt[3] + gt[5]/2.0))/gt[5]))
if (ix < 0) or (iy < 0) or (ix > nx - 1) or (iy > ny - 1):
return no_data
else:
return band_array[iy, ix]
... mais je préfère de loin les méthodes d'interpolation bilinéaire)
la source
MemoryError
parce que NumPy essaie d'accéder au-delà de votreband_array
? Vous devriez vérifierax
etay
.gt
.Réponses:
J'ai traduit la formule ci-dessous (de Wikipedia ) en langage Python pour produire l'algorithme suivant, qui semble fonctionner.
Notez que le résultat sera retourné avec une précision apparemment plus élevée que les données source, car il est classé dans le
dtype('float64')
type de données NumPy . Vous pouvez utiliser la valeur de retour avec.astype(band_array.dtype)
pour que le type de données de sortie soit identique au tableau d'entrée.la source
Je l'ai essayé localement pour des résultats similaires, mais je suis sur une plate-forme 64 bits, donc il n'a pas atteint la limite de mémoire. Essayez plutôt d'interpoler de petits morceaux du tableau à la fois, comme dans cet exemple .
Vous pouvez également le faire avec GDAL, à partir de la ligne de commande, ce serait:
Pour effectuer l'opération équivalente en Python, utilisez ReprojectImage () :
la source
ReprojectImage
technique intégrée de GDAL .J'ai eu le problème exact dans le passé et je ne l'ai jamais résolu en utilisant interpolate.interp2d. J'ai réussi à utiliser scipy.ndimage.map_coordinates . Essayez ce qui suit:
scipy.ndimage.map_coordinates (band_array, [ax, ay]], order = 1)
Cela semble donner la même sortie que bilinéaire.
la source
scipy.interpolate.interp2d () fonctionne très bien avec scipy plus moderne. Je pense que les anciennes versions supposent des grilles irrégulières et ne profitent pas des grilles régulières. J'obtiens la même erreur que vous avec scipy. version = 0.11.0, mais sur scipy. version = 0.14.0, il fonctionne heureusement sur une sortie de modèle 1600x1600.
Merci pour les indices dans votre question.
la source