Mendapatkan nilai piksel raster GDAL di bawah titik OGR tanpa NumPy?


45

Saya sedang mengerjakan model komputasi dari banyaknya penyerbuk liar di seluruh lanskap. Model itu sendiri selesai, dan saya sekarang berjuang dengan langkah post-processing.

Saya memiliki raster pasokan penyerbuk GDAL saya yang terlihat seperti ini (warna yang lebih terang berarti kunjungan penyerbuk yang lebih tinggi ke satu piksel):

Raster skala abu-abu mewakili pasokan penyerbuk pada suatu lanskap

Dan saya memiliki OGR shapefile poin yang mewakili lokasi sampel di lanskap:

masukkan deskripsi gambar di sini

Saya mencoba menjalankan beberapa analisis pada piksel di bawah titik-titik ini, tetapi untuk melakukannya, saya harus dapat mengekstraksi nilai piksel di bawah satu titik.

Apakah mungkin untuk mengekstraksi nilai piksel di bawah satu titik menggunakan hanya OGR dan GDAL melalui Python? Saya lebih suka menghindari membaca seluruh raster ke dalam memori ReadAsArray(), karena raster output saya sangat, sangat besar (terlalu besar untuk masuk ke dalam memori).

Saya perhatikan posting ini , yang mirip, tetapi membutuhkan panggilan baris perintah.


2
Bagaimana dengan ReadAsArray () dan hanya membaca pada intinya? Jadi hanya baca sel tunggal yang Anda minati? Anda perlu mengonversi dari titik koordinat ke ruang piksel dan mengekstrak sel yang diperlukan.
Jay Laura

1
Lihatlah kode untuk gdalsrsinfo, ini menunjukkan kepada Anda cara menggunakan GDALInvertGeoTransform () dan beralih antara ruang geografis dan ruang piksel: trac.osgeo.org/gdal/browser/trunk/gdal/apps/gdalsrsinfo.cpp

Jika Anda tidak keberatan menggunakan PostGIS, lihat ini . Ini sangat cepat dan hanya 1 baris SQL.
mlt

Saya akan mengingatnya jika saya menemukan masalah ini dan memiliki akses ke database PostGIS! Saya tidak melakukannya untuk masalah khusus ini, jadi solusi GDAL di bawah ini berhasil. Terimakasih Meskipun!
James

@ Kyle Saya tidak tahu apakah hal-hal telah berubah tapi sepertinya itu GDALInvGeoTransform tidak invert dan ini adalah contoh .
mlt

Jawaban:


61

Anda dapat menggunakan metode ReadRaster gdal.Dataset atau gdal.Band . Lihat tutorial GDAL dan OGR API dan contoh di bawah ini. ReadRaster tidak menggunakan / membutuhkan numpy, nilai kembali adalah data biner mentah dan perlu dibongkar menggunakan modul struct python standar .

Sebuah contoh:

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

Atau, karena alasan yang Anda berikan untuk tidak menggunakan numpyadalah untuk menghindari membaca seluruh array yang digunakan ReadAsArray(), di bawah ini adalah contoh yang menggunakan numpydan tidak membaca seluruh raster di.

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

Dan bagaimana Anda bisa menyimpan sebagai csv, tabel atau objek lain? Sebuah objek dengan panjang koordinat yang sama objetct
gonzalez.ivan90

Inilah pertanyaannya, Luke. Terima kasih! gis.stackexchange.com/questions/269603/…
gonzalez.ivan90

baris yang menetapkan px/ pysalah dalam hal mx / my terletak di luar batas rb, karena int(-0.5) == 0. Anda perlu floor(...), dan kemudian Anda perlu memeriksa bahwa tak satu pun dari px/ pykurang dari nol (atau melakukannya sebelum memanggil int()), karena indeks negatif berfungsi (mereka mendapatkan sisi lain dari array). Saya ingin tahu apakah ada cara yang lebih rapi untuk mengatasi masalah ini. Juga, bagaimana Anda menulis ulang baris-baris itu sehingga mereka berurusan dengan rotasi dengan benar?
naught101
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.