NumPy'siz OGR noktası altındaki GDAL rasterinin piksel değeri alınıyor mu?


45

Bir manzaradaki vahşi tozlayıcıların bolluğunun hesaplamalı bir modeli üzerinde çalışıyorum. Modelin kendisi tamamlandı ve şimdi bir işlem sonrası adımla mücadele ediyorum.

Buna benzeyen GDAL tozlayıcı tedarik rasterim var (açık renkler piksellere daha yüksek tozlayıcı ziyareti anlamına gelir):

Bir manzaradaki tozlayıcı arzını temsil eden gri tonlamalı raster

Ve manzaradaki örnek konumları temsil eden bir OGR şekil dosyası var:

görüntü tanımını buraya girin

Bu noktaların altındaki pikseller üzerinde bazı analizler yapmaya çalışıyorum, ancak bunu yapmak için, bir pikselin değerini bir nokta altında çıkarabilmem gerekiyor.

Bir pikselin değerini, yalnızca OGR ve GDAL ile Python kullanarak bir nokta altında çıkarmak mümkün müdür? ReadAsArray()Çıktı rasterlerim çok, çok büyük (belleğe sığmayacak kadar büyük) olduğundan, rasterin tamamını belleğe okumaktan kaçınmayı tercih ederim .

Benzer olan ancak bir komut satırı çağrısı gerektiren bu yazıyı fark ettim .


2
Peki ya ReadAsArray () ve sadece bu noktada okuma? Yani sadece ilgilendiğiniz tek hücreyi mi okuyorsunuz? Nokta kodlayıcılardan piksel uzayına dönüştürmeniz ve gerekli hücreyi çıkarmanız gerekir.
Jay Laura

1
Gdalsrsinfo koduna bakın, GDALInvertGeoTransform () yönteminin nasıl kullanılacağını ve coğrafi alan ile piksel alanı arasında nasıl geçiş yapacağınızı gösterir: trac.osgeo.org/gdal/browser/trunk/gdal/apps/gdalsrsinfo.cpp

Eğer PostGIS kullanarak sakıncası yoksa, bkz bu . Son derece hızlı ve sadece 1 SQL satırı.
mlt

Bu problemle karşılaşırsam ve PostGIS veritabanına erişebilirsem bunu aklımda tutacağım! Bu özel sorun için yapmadım, bu yüzden aşağıdaki GDAL çözümü işe yaradı. Yine de teşekkürler!
James

@kyle Bir şeylerin değişip değişmediğini bilmiyorum ama GDALInvGeoTransform ters değil gibi görünüyor ve bu bir örnek .
mlt

Yanıtlar:


60

Sen kullanabilirsiniz gdal.Dataset veya gdal.Band ReadRaster yöntemi. Bkz GDAL ve OGR API öğreticiler ve aşağıdaki örneğe. ReadRaster numpy kullanmıyor / gerektirmiyor, dönüş değeri ham ikili veridir ve standart python struct modülü kullanılarak açılmalıdır .

Bir örnek:

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

Alternatif olarak, kullanmamanız için verdiğiniz sebep numpy, kullanımdaki tüm diziyi okumaktan kaçınmak ReadAsArray()olduğundan, aşağıda numpyrasterin tamamını kullanan ve okumayan bir örnek verilmiştir .

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

Ve nasıl csv, tablo veya başka bir nesne olarak kaydedebilirsiniz? Aynı uzunlukta koordinatlara sahip bir nesne objetct
gonzalez.ivan90


çizgiler atama olduğunu px/ pyo mx / sınırları dışında benim yalanlar durumda yanlış rb, çünkü int(-0.5) == 0. İhtiyacınız floor(...)ve sonra ki, ne bir kontrol etmeniz gerekir px/ pySıfırdan daha düşük olan (veya çağırmadan önce bunu int()olumsuz endeksleri işi (onlar dizinin diğer tarafını almak), çünkü). Bu sorunla başa çıkmak için daha düzgün bir yol olup olmadığını bilmek isterim. Ayrıca, doğru bir şekilde rotasyonları ele almaları için bu satırları nasıl yeniden yazarsınız?
naught101
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.