Traitement d'image à l'aide de Python, GDAL et Scikit-Image

11

Je me bats avec un traitement et j'espère que je serai en mesure de résoudre ici.

Je travaille avec la télédétection appliquée à la foresterie, en particulier avec les données LiDAR. L'idée est d'utiliser Scikit-image pour la détection du sommet des arbres. Depuis que je suis nouveau en Python, j'ai considéré un grand triomphe personnel pour faire ce qui suit:

  1. Importez un CHM (avec matplotlib);
  2. Exécutez un filtre gaussien (avec le package scikit-image);
  3. Exécutez un filtre maxima (avec le package scikit-image);
  4. Exécutez peak_local_max (avec le package scikit-image);
  5. Montrer le CHM avec les maxima locaux (avec matplotlib);

Maintenant mon problème. Lorsque j'importe avec matplot, l'image perd ses coordonnées géographiques. Ainsi, les coordonnées que j'ai ne sont que des coordonnées d'image de base (par exemple 250 312). Ce dont j'ai besoin, c'est d'obtenir la valeur du pixel sous le point de maxima local dans l'image (points rouges dans l'image). Ici, dans le forum, j'ai vu un gars demander la même chose ( obtenir la valeur en pixels du raster GDAL sous le point OGR sans NumPy? ), Mais il avait déjà les points dans un fichier de formes. Dans mon cas, les points ont été calculés avec scikit-image (c'est un tableau avec les coordonnées de chaque sommet d'arbre). Je n'ai donc pas le fichier de formes.

En conclusion, ce que je veux à la fin, c'est un fichier txt avec les coordonnées de chaque maximum local en coordonnées géographiques, par exemple:

525412 62980123 1150 ...

Maximaux locaux (points rouges) dans un CHM

João Paulo Pereira
la source

Réponses:

11

Tout d'abord, bienvenue sur le site!

Les tableaux Numpy n'ont pas de concept de systèmes de coordonnées intégrés dans le tableau. Pour un raster 2D, ils sont indexés par colonne et ligne.

Notez que je fais l'hypothèse que vous lisez un format raster pris en charge par GDAL .

En Python, le meilleur moyen d'importer des données raster spatiales est avec le rasteriopackage. Les données brutes importées par rasterio sont toujours un tableau numpy sans accès aux systèmes de coordonnées, mais rasterio vous donne également accès à une méthode affine sur le tableau source que vous pouvez utiliser pour transformer les colonnes et lignes raster en coordonnées projetées. Par exemple:

import rasterio

# The best way to open a raster with rasterio is through the context manager
# so that it closes automatically

with rasterio.open(path_to_raster) as source:

    data = source.read(1) # Read raster band 1 as a numpy array
    affine = source.affine

# ... do some work with scikit-image and get an array of local maxima locations
# e.g.
# maxima = numpy.array([[0, 0], [1, 1], [2, 2]])
# Also note that convention in a numy array for a 2d array is rows (y), columns (x)

for point in maxima: #Loop over each pair of coordinates
    column = point[1]
    row = point[0]
    x, y = affine * (column, row)
    print x, y

# Or you can do it all at once:

columns = maxima[:, 1]
rows = maxima[:, 0]

xs, ys = affine * (columns, rows)

Et à partir de là, vous pouvez écrire vos résultats dans un fichier texte comme vous le souhaitez (je vous suggère de jeter un œil au module intégrécsv par exemple).

om_henners
la source
Merci beaucoup. On dirait que cela peut fonctionner. Depuis que je suis nouveau dans ce domaine, je dois encore me familiariser avec beaucoup de choses. Merci pour la patience.
João Paulo Pereira
1
Dans Rasterio 1.x, vous pouvez utiliser source.xy (ligne, colonne) pour obtenir les coordonnées géographiques.
bugmenot123
0

D'un rapide coup d'œil à matplotlib, je dirais que vous devez modifier les échelles des axes après l'importation.

ymirsson
la source
Je pense que le problème est dans scikit-image. Lorsque je l'exécute, scikit passe automatiquement aux coordonnées de l'image.
João Paulo Pereira
0

Veuillez essayer avec le morceau de code suivant. Cela peut être utilisé pour lire les données d'image du raster et écrire les données traitées dans le raster (fichier .geotiff).

from PIL import Image,ImageOps
import numpy as np
from osgeo import gdal
#from osgeo import gdal_array
#from osgeo import osr
#from osgeo.gdalconst import *
#import matplotlib.pylab as plt

#from PIL import Image, ImageOps
#import gdal
#from PIL import Image
gdal.AllRegister()

################## Read Raster #################
inRaster='C:\python\Results\Database\Risat1CRS\CRS_LEVEL2_GEOTIFF\scene_HH\imagery_HH.tif'

inDS=gdal.Open(inRaster,1)
geoTransform = inDS.GetGeoTransform()
band=inDS.GetRasterBand(1)
datatype=band.DataType
proj = inDS.GetProjection()
rows = inDS.RasterYSize
cols=inDS.RasterXSize
data=band.ReadAsArray(0,0,cols,rows)#extraction of data to be processed#
############write raster##########
driver=inDS.GetDriver()
outRaster='C:\\python\\Results\\Database\\Temporary data base\\clipped_26July2017\\demo11.tif'
outDS = driver.Create(outRaster, cols,rows, 1,datatype)
geoTransform = inDS.GetGeoTransform()
outDS.SetGeoTransform(geoTransform)
proj = inDS.GetProjection()
outDS.SetProjection(proj)
outBand = outDS.GetRasterBand(1)
outBand.WriteArray(data1,0,0)
#data is the output array to written in tiff file
outDS=None 
im2=Image.open('C:\\python\\Results\\Database\\Temporary data base\\clipped_26July2017\\demo11.tif');
im2.show()
sckulkarni
la source