13 votos

Obtener las coordenadas y los valores de los píxeles correspondientes de GeoTiff usando python gdal y guardarlos como array numpy

¿Cómo puedo obtener las coordenadas proyectadas así como los valores reales de los píxeles en esas coordenadas desde un archivo GeoTiff y luego guardarlos en una matriz numpy? Tengo el archivo arsenci020l.tif, y sus coordenadas están en metros. Abajo está la salida abreviada de gdalinfo que ejecuté en él.

~$ gdalinfo arsenci020l.tif 
Driver: GTiff/GeoTIFF
Files: arsenci020l.tif
       arsenci020l.tfw
Size is 10366, 7273
Coordinate System is:
PROJCS["Lambert Azimuthal Equal Area projection with arbitrary plane grid; projection center 100.0 degrees W, 45.0 degrees N",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0],
        UNIT["degree",0.0174532925199433],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Lambert_Azimuthal_Equal_Area"],
    PARAMETER["latitude_of_center",45],
    PARAMETER["longitude_of_center",-100],
    PARAMETER["false_easting",0],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]]]
Origin = (-6086629.000000000000000,4488761.000000000000000)
Pixel Size = (1000.000000000000000,-1000.000000000000000)
...

Hubo una pregunta similar aquí sobre la obtención de coordenadas de latitud y longitud de tiff (Obtener latitud y longitud de un archivo GeoTIFF) y la respuesta mostró cómo obtener sólo las coordenadas de píxeles de la parte superior izquierda x e y. Necesito obtener TODAS las coordenadas de los píxeles proyectados, así como obtener los valores de los píxeles y guardarlos en un array de numpy. ¿Cómo puedo hacerlo?

0 votos

¿Quieres 10366 × 7273 = más de 75 millones de puntos?

0 votos

@MikeT Creo que sí, no conozco una solución mejor de cómo enfocar el problema que estoy tratando de resolver: necesito encontrar la coordenada de píxel más cercana de este conjunto de datos a cada centroide del bloque de EE.UU. y luego asignar el valor de píxel correspondiente a ese bloque. Buscando por ahí me he dado cuenta de que la consulta cKDTree me va a ayudar con la búsqueda del vecino más cercano.La función de Python para el algoritmo pide un "árbol" para consultar como matriz numpy.Para hacer un "árbol" con todas las coordenadas de píxeles de este conjunto de datos,necesito almacenarlas todas de alguna manera.Si tienes una solución mejor,por favor, házmelo saber.

0 votos

No puedo entender por qué este procedimiento requiere tanto código en Python.

21voto

hernan43 Puntos 566

Esto debería ponerte en marcha. Los valores de la trama se leen con rasterio y las coordenadas de los centros de los píxeles se convierten en orientaciones/nortes mediante afín que luego se convierten en Latitud/Longitud mediante pyproj . La mayoría de las matrices tienen la misma forma que la trama de entrada.

import rasterio
import numpy as np
from affine import Affine
from pyproj import Proj, transform

fname = '/path/to/your/raster.tif'

# Read raster
with rasterio.open(fname) as r:
    T0 = r.transform  # upper-left pixel corner affine transform
    p1 = Proj(r.crs)
    A = r.read()  # pixel values

# All rows and columns
cols, rows = np.meshgrid(np.arange(A.shape[2]), np.arange(A.shape[1]))

# Get affine transform for pixel centres
T1 = T0 * Affine.translation(0.5, 0.5)
# Function to convert pixel row/column index (from 0) to easting/northing at centre
rc2en = lambda r, c: (c, r) * T1

# All eastings and northings (there is probably a faster way to do this)
eastings, northings = np.vectorize(rc2en, otypes=[np.float, np.float])(rows, cols)

# Project all longitudes, latitudes
p2 = Proj(proj='latlong',datum='WGS84')
longs, lats = transform(p1, p2, eastings, northings)

1 votos

Al utilizarlo, recibo el mensaje "AttributeError: 'DatasetReader' object has no attribute 'affine'" para la línea "T0 = r.affine"

0 votos

@mitchus Aparentemente affine es sólo un alias de transform y el alias ha sido eliminado de la versión más reciente de rasterio. He editado la respuesta pero parece que necesita ser revisada por los compañeros ya que soy nuevo aquí. :)

1 votos

También parece que los índices son erróneos para A.shape que sólo tiene dos dimensiones.

7voto

znq Puntos 143

añadiría como comentario, pero un poco largo - en caso de que quieras usar gdal/ogr dentro de python - algo como esto podría funcionar (pirateado a partir de otro código que tenía - ¡no probado!) Esto también asume que en lugar de encontrar el píxel raster más cercano a un centroide del polígono, usted simplemente consulta el raster en el xy del centroide. no tengo idea de cuál podría ser la compensación de velocidad...

from osgeo import gdal,ogr

fc='PathtoYourVector'
rast='pathToYourRaster'

def GetCentroidValue(fc,rast):
    #open vector layer
    drv=ogr.GetDriverByName('ESRI Shapefile') #assuming shapefile?
    ds=drv.Open(fc,True) #open for editing
    lyr=ds.GetLayer(0)

    #open raster layer
    src_ds=gdal.Open(rast) 
    gt=src_ds.GetGeoTransform()
    rb=src_ds.GetRasterBand(1)
    gdal.UseExceptions() #so it doesn't print to screen everytime point is outside grid

    for feat in lyr:
        geom=feat.GetGeometryRef()
        mx=geom.Centroid().GetX()
        my=geom.Centroid().GetY()

        px = int((mx - gt[0]) / gt[1]) #x pixel
        py = int((my - gt[3]) / gt[5]) #y pixel
        try: #in case raster isnt full extent
            structval=rb.ReadRaster(px,py,1,1,buf_type=gdal.GDT_Float32) #Assumes 32 bit int- 'float'
            intval = struct.unpack('f' , structval) #assume float
            val=intval[0]
        except:
            val=-9999 #or some value to indicate a fail

       feat.SetField('YOURFIELD',val)
       lyr.SetFeature(feat)

    src_ds=None
    ds=None

GetCentroidValue(fc,rast)

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X