Python gdal kullanarak GeoTiff'ten koordinatları ve karşılık gelen piksel değerlerini alın ve bunları numpy dizisi olarak kaydedin


10

GeoTiff dosyasından yansıtılan koordinatları ve bu koordinatlardaki gerçek piksel değerlerini nasıl elde edebilirim ve sonra bunları numpy dizisine nasıl kaydedebilirim? Arsenci020l.tif dosyam var ve koordinatları metre cinsindendir. Aşağıda üzerinde koştu gdalinfo kısaltılmış çıktı.

~$ 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)
...

Burada tiff'ten (GeoTIFF Dosyasından Enlem ve Boylam Al) enlem / boylam koordinatlarını alma konusunda benzer bir soru vardı ve cevap sadece sol üst x ve y piksel koordinatlarının nasıl elde edileceğini gösterdi. TÜM yansıtılan piksel koordinatları elde yanı sıra piksel değerleri almak ve bir numpy dizide kaydetmek gerekir. Nasıl yapabilirim?


10366 × 7273 = 75 milyondan fazla puan mı istiyorsunuz?
Mike T

@MikeT Sanırım, çözmeye çalıştığım soruna nasıl yaklaşacağım konusunda daha iyi bir çözüm bilmiyorum: Bu veri kümesinden ABD bloğunun her bir sentroidine en yakın piksel koordinatını bulmam ve Bu bloğa karşılık gelen piksel değeri. Etrafında arama yaparken cKDTree sorgusu bana en yakın komşu arama ile yardımcı olacağını fark etti. Algoritma için Python işlevi numpy dizi olarak sorgulamak için bir "ağaç" sorar. Bu veri kümesindeki tüm piksel koordinatlarından hepsini bir şekilde saklamam gerekiyor. daha iyi bir çözümünüz varsa, lütfen bana bildirin!
irakhman

Yanıtlar:


7

yorum olarak eklemek istiyorum, ama biraz uzun - python içinde gdal / ogr kullanmak istemeniz durumunda - böyle bir şey işe yarayabilir (ben vardı başka bir kod birlikte hack - test değil!) Bu da en yakın bulmak yerine varsayar raster piksel bir çokgen centroid, basitçe centroid xy raster sorgulamak. hız dengesinin ne olabileceği hakkında hiçbir fikrim yok ...

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)

14

Bu seni harekete geçirmeli. Raster değerleri rasterio kullanılarak okunur ve piksel merkez koordinatları afin kullanılarak Eastings / Northings'e dönüştürülür ve daha sonra pyproj kullanılarak Enlem / Boylam'a dönüştürülür . Dizilerin çoğu giriş rasteriyle aynı şekle sahiptir.

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
Bunu kullanırken, "AttributeError: 'DatasetReader' nesnesinin" T0 = r.affine "satırı için 'affine' özelliği yok
mitchus

@mitchus Görünüşe göre affinesadece bir takma addır transformve takma ad rasterio'nun en son sürümünden kaldırılmıştır. Cevabı düzenledim, ancak burada yeni olduğumdan beri hakem değerlendirmesi yapılması gerekiyor gibi görünüyor. :)
Autumnsault

1
Ayrıca A.shape, sadece iki boyutu olan dizinler için yanlış gibi görünüyor .
Autumnsault
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.