รับค่าพิกเซลของแรสเตอร์ GDAL ภายใต้จุด OGR โดยไม่ต้อง NumPy?


45

ฉันกำลังทำงานกับแบบจำลองการคำนวณของความหลากหลายของเรณูป่าในภูมิประเทศ ตัวแบบเสร็จสมบูรณ์แล้วและตอนนี้ฉันกำลังดิ้นรนกับขั้นตอนหลังการประมวลผล

ฉันมีเรณูซัพพลาย GDAL ของฉันที่มีลักษณะคล้ายนี้ (สีที่เบากว่าหมายถึงการเยี่ยมชมของเรณูที่พิกเซล):

Greyscale raster เป็นตัวแทนของการถ่ายละอองเรณูในภูมิประเทศ

และฉันมี OGR รูปร่างไฟล์ของจุดที่เป็นตัวแทนของตัวอย่างสถานที่ในแนวนอน:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันกำลังพยายามวิเคราะห์จุดพิกเซลภายใต้จุดเหล่านี้ แต่ต้องทำเช่นนั้นฉันต้องสามารถแยกค่าของพิกเซลที่อยู่ใต้จุดใดจุดหนึ่งได้

เป็นไปได้หรือไม่ที่จะแยกค่าของพิกเซลภายใต้จุดโดยใช้ OGR และ GDAL ผ่าน Python เท่านั้น ฉันต้องการหลีกเลี่ยงการอ่านแรสเตอร์ทั้งหมดลงในหน่วยความจำReadAsArray()เพราะเอาท์พุทแรสเตอร์ของฉันมีขนาดใหญ่มาก (ใหญ่เกินไปที่จะใส่ลงในหน่วยความจำ)

ฉันสังเกตเห็นโพสต์นี้ซึ่งคล้ายกัน แต่ต้องมีการเรียกบรรทัดคำสั่ง


2
ReadAsArray () และอ่านเฉพาะจุดเท่านั้น ดังนั้นควรอ่านเซลล์เดียวที่คุณสนใจ? คุณจะต้องแปลงจากจุดประสานไปยังพื้นที่พิกเซลและแยกเซลล์ที่จำเป็น
Jay Laura

1
ดูรหัสสำหรับ gdalsrsinfo จะแสดงวิธีใช้ GDALInvertGeoTransform () และสลับระหว่างพื้นที่ทางภูมิศาสตร์และพื้นที่พิกเซล: trac.osgeo.org/gdal/browser/trunk/gdal/apps/gdalsrsinfo.cpp

หากคุณไม่ทราบใช้ PostGIS ดูนี้ มันเร็วมากและเป็นเพียง 1 บรรทัด SQL
mlt

ฉันจะจำไว้ว่าถ้าฉันเจอปัญหานี้และเข้าถึงฐานข้อมูล PostGIS! ฉันไม่ได้มีปัญหาเฉพาะนี้ดังนั้นโซลูชันของ GDAL ด้านล่างจึงใช้เคล็ดลับ ขอบคุณ แต่!
James

@kyle ผมไม่ทราบว่าสิ่งที่มีการเปลี่ยนแปลง แต่ดูเหมือนว่ามันเป็นGDALInvGeoTransformไม่คว่ำและนี้เป็นตัวอย่าง
mlt

คำตอบ:


60

คุณสามารถใช้วิธีgdal.Datasetหรือgdal.Band ReadRaster ดูบทช่วยสอนของGDALและOGR API และตัวอย่างด้านล่าง ReadRaster ไม่ได้ใช้ / ต้องการ numpy ค่าส่งคืนเป็นข้อมูลไบนารีดิบและจำเป็นต้องคลายแพ็กเก็ตโดยใช้โมดูลpython structมาตรฐาน

ตัวอย่าง:

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

อีกวิธีหนึ่งเนื่องจากเหตุผลที่คุณไม่ได้ใช้numpyคือหลีกเลี่ยงการอ่านอาเรย์ทั้งหมดในการใช้ReadAsArray()ด้านล่างเป็นตัวอย่างที่ใช้numpyและไม่อ่านแรสเตอร์ทั้งหมด

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

และคุณจะบันทึกเป็น csv, table หรือวัตถุอื่นได้อย่างไร? วัตถุที่มีความยาวเท่ากันของพิกัด objetct
gonzalez.ivan90

นี่คือคำถามลุค ขอบคุณ! gis.stackexchange.com/questions/269603/…
gonzalez.ivan90

บรรทัดที่กำหนดpx/ pyมีความผิดในกรณีที่ MX / โกหกฉันอยู่นอกขอบเขตของการเพราะrb int(-0.5) == 0คุณต้องการfloor(...)และจากนั้นคุณต้องตรวจสอบว่าไม่มีpx/ pyน้อยกว่าศูนย์ (หรือทำก่อนโทรint()) เพราะดัชนีลบทำงาน (พวกเขาจะได้รับด้านอื่น ๆ ของอาร์เรย์) ฉันชอบที่จะรู้ว่าหากมีวิธีการจัดการกับปัญหานี้หรือไม่ นอกจากนี้คุณจะเขียนบรรทัดเหล่านั้นอย่างไรเพื่อให้พวกเขาจัดการกับการหมุนได้อย่างถูกต้อง?
naught101
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.