Pixelwert des GDAL-Rasters unter OGR-Punkt ohne NumPy erhalten?


45

Ich arbeite an einem Rechenmodell für die Häufigkeit von Wildbestäubern in einer Landschaft. Das Modell selbst ist vollständig, und ich habe jetzt mit einem Nachbearbeitungsschritt zu kämpfen.

Ich habe mein GDAL-Bestäuberversorgungs-Raster, das ungefähr so ​​aussieht (hellere Farben bedeuten einen höheren Bestäuberaufruf pro Pixel):

Graustufenraster, das Bestäuberversorgung auf einer Landschaft darstellt

Und ich habe ein OGR-Shapefile mit Punkten, die Beispielpositionen in der Landschaft darstellen:

Bildbeschreibung hier eingeben

Ich versuche, einige Analysen an den Pixeln unter diesen Punkten durchzuführen, aber dazu muss ich in der Lage sein, den Wert eines Pixels unter einem Punkt zu extrahieren.

Ist es möglich, den Wert eines Pixels unter einem Punkt nur mit OGR und GDAL über Python zu extrahieren? Ich würde es vorziehen, das Lesen des gesamten Rasters in den Speicher zu vermeiden ReadAsArray(), da meine Ausgabe-Raster sehr, sehr groß sind (zu groß, um in den Speicher zu passen).

Mir ist dieser Beitrag aufgefallen , der ähnlich ist, aber einen Befehlszeilenaufruf erfordert.


2
Was ist mit ReadAsArray () und nur im Punkt lesen? Lesen Sie also nur die einzelne Zelle, die Sie interessiert? Sie müssten von den Punktkoordinaten in den Pixelraum konvertieren und die erforderliche Zelle extrahieren.
Jay Laura

1
Schauen Sie sich den Code für gdalsrsinfo an und erfahren Sie, wie Sie GDALInvertGeoTransform () verwenden und zwischen dem geografischen Raum und dem Pixelraum

Wenn es Ihnen nichts ausmacht, PostGIS zu verwenden, lesen Sie dies . Es ist extrem schnell und ist nur 1 SQL-Zeile.
mlt

Ich werde das im Hinterkopf behalten, wenn ich auf dieses Problem stoße und Zugriff auf eine PostGIS-Datenbank habe! Ich war nicht für dieses spezielle Problem verantwortlich, daher hat die unten stehende GDAL-Lösung den Trick getan. Trotzdem danke!
James

@kyle Ich weiß nicht, ob sich die Dinge geändert haben, aber es sieht so aus, als wäre GDALInvGeoTransform nicht invertiert und dies ist ein Beispiel .
mlt

Antworten:


60

Sie können die Methode gdal.Dataset oder gdal.Band ReadRaster verwenden. Weitere Informationen finden Sie in den Tutorials zur GDAL- und OGR- API sowie im folgenden Beispiel. ReadRaster verwendet / erfordert kein numpy, der Rückgabewert besteht aus rohen Binärdaten und muss mit dem Standard-Python- Strukturmodul entpackt werden .

Ein Beispiel:

from osgeo import gdal,ogr
import struct

src_filename = '/tmp/test.tif'
shp_filename = '/tmp/test.shp'

src_ds=gdal.Open(src_filename) 
gt=src_ds.GetGeoTransform()
rb=src_ds.GetRasterBand(1)

ds=ogr.Open(shp_filename)
lyr=ds.GetLayer()
for feat in lyr:
    geom = feat.GetGeometryRef()
    mx,my=geom.GetX(), geom.GetY()  #coord in map units

    #Convert from map to pixel coordinates.
    #Only works for geotransforms with no rotation.
    px = int((mx - gt[0]) / gt[1]) #x pixel
    py = int((my - gt[3]) / gt[5]) #y pixel

    structval=rb.ReadRaster(px,py,1,1,buf_type=gdal.GDT_UInt16) #Assumes 16 bit int aka 'short'
    intval = struct.unpack('h' , structval) #use the 'short' format code (2 bytes) not int (4 bytes)

    print intval[0] #intval is a tuple, length=1 as we only asked for 1 pixel value

Da Sie als Grund für die Nichtverwendung angegeben haben, dass nicht numpydas gesamte Array in using gelesen werden soll ReadAsArray(), finden Sie im Folgenden ein Beispiel, das numpydas gesamte Raster verwendet und nicht einliest.

from osgeo import gdal,ogr
import struct

src_filename = '/tmp/test.tif'
shp_filename = '/tmp/test.shp'

src_ds=gdal.Open(src_filename) 
gt=src_ds.GetGeoTransform()
rb=src_ds.GetRasterBand(1)

ds=ogr.Open(shp_filename)
lyr=ds.GetLayer()
for feat in lyr:
    geom = feat.GetGeometryRef()
    mx,my=geom.GetX(), geom.GetY()  #coord in map units

    #Convert from map to pixel coordinates.
    #Only works for geotransforms with no rotation.
    px = int((mx - gt[0]) / gt[1]) #x pixel
    py = int((my - gt[3]) / gt[5]) #y pixel

    intval=rb.ReadAsArray(px,py,1,1)
    print intval[0] #intval is a numpy array, length=1 as we only asked for 1 pixel value

Und wie können Sie als CSV, Tabelle oder anderes Objekt speichern? Ein Objekt mit der gleichen Länge der Koordinaten objetct
gonzalez.ivan90

Hier ist die Frage, Luke. Vielen Dank! gis.stackexchange.com/questions/269603/…
gonzalez.ivan90

Die Linien , die assign px/ pysind falsch in dem Fall , dass mx / mein liegt außerhalb der Grenzen rb, da int(-0.5) == 0. Sie müssen floor(...)überprüfen, ob keines von px/ pykleiner als Null ist (oder dies vor dem Aufruf tun int()), da negative Indizes funktionieren (sie erhalten die andere Seite des Arrays). Ich würde gerne wissen, ob es eine bessere Möglichkeit gibt, mit diesem Problem umzugehen. Wie schreibt man diese Zeilen neu, damit sie korrekt mit Rotationen umgehen?
naught101
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.