Lire, modifier et écrire un géotiff avec GDAL en python

11

J'essaie d'apprendre les ficelles du traitement d'image de télédétection en utilisant les liaisons Python GDAL et numpy. Dans un premier temps, je lis un fichier géotiff Landsat8, je fais une manipulation simple et j'écris le résultat dans un nouveau fichier. Le code ci-dessous semble fonctionner correctement, sauf que le raster d'origine est sauvegardé dans le fichier de sortie, plutôt que le raster manipulé.

Tous les commentaires ou suggestions sont les bienvenus, mais en particulier les notes expliquant pourquoi le raster manipulé n'apparaît pas dans le résultat.

import os
import gdal

gdal.AllRegister()

file = "c:\~\LC81980242015071LGN00.tiff"
(fileRoot, fileExt) = os.path.splitext(file)
outFileName = fileRoot + "_mod" + fileExt

ds = gdal.Open(file)
band = ds.GetRasterBand(1)
arr = band.ReadAsArray()

[cols, rows] = arr.shape
arr_min = arr.Min()
arr_max = arr.Max()
arr_mean = int(arr.mean())

arr_out = numpy.where((arr < arr_mean), 10000, arr)

driver = gdal.GetDriverByName("GTiff")
outdata = driver.Create(outFileName, rows, cols, 1, gdal.GDT_UInt16)
outband = outdata.GetRasterBand(1)
outband.WriteArray(arr_out)
outdata = None

print arr_min
> 0
print arr_max
> 65535
print arr_mean
> 4856

J'utilise Python 2.7.1 sur une machine Windows 7 32 bits.

Hans Roelofsen
la source
Je l'ai fait fonctionner sur un DEM (Ubuntu, python 2.7.1) et il a produit le résultat attendu, avec tout en dessous de la valeur moyenne fixée à 10000 et écrit sur un nouveau tiff. Vous ne copiez pas la géotransformation vers la nouvelle image, elle n'est donc pas projetée, vous devrez donc peut-être en tenir compte lorsque vous essayez de la visualiser (il y a une seule ligne pour le faire, mais je vais devoir la creuser). Si vous pouvez modifier votre question avec la sortie de gdainfo -stats original.tiffet gdal-config --versionaussi cela pourrait aider.
Steven Kay
Salut, merci de regarder ça! Je sais que j'ai négligé la géotransformation, j'ai pensé à mâcher plus tard. Je vois cependant l'image de sortie entière (en utilisant Irfanview), donc ça ne peut pas être ça je pense. Je générerai les informations que vous avez demandées lorsque je serai de retour ce soir.
Hans Roelofsen du
Bonjour, j'ai du mal à fournir les informations que vous avez demandées. J'utilise la liaison Python GDAL et je ne sais pas comment les commandes que vous spécifiez correspondent à une commande Python. Dans tous les cas, j'utilise GDAL-1.11.2-cp27-none-win32, tel qu'acquis à partir d' ici . Je mettrai à jour mon article avec quelques statistiques sur le .tiff d'origine.
Hans Roelofsen
que serait arr_min?
fluidmotion
arr_min = 0. J'ai mis à jour le message pour le montrer. Merci!
Hans Roelofsen

Réponses:

13

Votre script ne contient pas la méthode ds.FlushCache, qui enregistre sur disque ce que vous avez en mémoire à la fin des modifications. Voir ci-dessous une version corrigée de votre exemple. Notez que j'ai également ajouté deux lignes pour définir la projection et la géotransformation en entrée

import os
import gdal

file = "path+filename"
ds = gdal.Open(file)
band = ds.GetRasterBand(1)
arr = band.ReadAsArray()
[cols, rows] = arr.shape
arr_min = arr.min()
arr_max = arr.max()
arr_mean = int(arr.mean())
arr_out = numpy.where((arr < arr_mean), 10000, arr)
driver = gdal.GetDriverByName("GTiff")
outdata = driver.Create(outFileName, rows, cols, 1, gdal.GDT_UInt16)
outdata.SetGeoTransform(ds.GetGeoTransform())##sets same geotransform as input
outdata.SetProjection(ds.GetProjection())##sets same projection as input
outdata.GetRasterBand(1).WriteArray(arr_out)
outdata.GetRasterBand(1).SetNoDataValue(10000)##if you want these values transparent
outdata.FlushCache() ##saves to disk!!
outdata = None
band=None
ds=None
Andrea Massetti
la source
Le fichier externe n'est pas projeté. Je lis un fichier HDF5 et je sélectionne la projection de la bande que je veux exporter GetProjection()délivre le bon EPSG, mais il semble ne pas être appliqué. Chaîne GDAL manquante? Merci!
Michael
que dois-je remplacer outdata.GetRasterBand(1).WriteArray(arr_out)pour écrire une image multispectrale qui a plus d'une bande?
Sai Kiran
Le "1" dans driver.Create () indique le nombre de bandes. Ensuite, vous pouvez écrire sur chaque bande avec outdata.GetRasterBand (band_number). Cela commence à 1, pas à zéro.
Andrea Massetti