รับพิกัดและค่าพิกเซลที่สอดคล้องกันจาก GeoTiff โดยใช้ python gdal และบันทึกเป็นอาร์เรย์แบบ numpy


10

ฉันจะได้รับพิกัดที่ฉายรวมถึงค่าพิกเซลจริงที่พิกัดเหล่านั้นจากไฟล์ GeoTiff จากนั้นบันทึกลงในอาร์เรย์แบบ numpy ได้อย่างไร ฉันมีไฟล์ arsenci020l.tif และพิกัดอยู่ในหน่วยเมตร ด้านล่างคือผลลัพธ์ย่อของ gdalinfo ที่ฉันวิ่งไป

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

มีคำถามที่คล้ายกันที่นี่เกี่ยวกับการรับ lat / long พิกัดจาก TIFF (รับละติจูดและลองจิจูดจากไฟล์ GeoTIFF) และคำตอบแสดงให้เห็นวิธีการได้รับพิกัด x และ y พิกเซลด้านบนซ้ายเท่านั้น ฉันจำเป็นต้องได้รับพิกัดพิกเซลที่คาดการณ์ไว้ทั้งหมดรวมทั้งรับค่าพิกเซลและบันทึกไว้ในอาร์เรย์ที่มีจำนวนมาก ฉันจะทำมันได้อย่างไร


คุณต้องการ 10366 × 7273 = มากกว่า 75 ล้านคะแนน?
Mike T

@ MikeT ฉันคิดว่าอย่างนั้นฉันไม่รู้วิธีแก้ปัญหาที่ดีกว่าของฉันฉันพยายามที่จะแก้ปัญหา: ฉันต้องการค้นหาพิกัดพิกเซลที่ใกล้เคียงที่สุดจากชุดข้อมูลนี้ไปยังแต่ละ centroid ของ US block จากนั้นกำหนด ค่าพิกเซลที่สอดคล้องกับบล็อกนั้นจากการค้นหารอบ ๆ ฉันรู้ว่าการค้นหา cKDTree จะช่วยฉันด้วยการค้นหาเพื่อนบ้านที่ใกล้ที่สุดฟังก์ชั่นงูหลามสำหรับอัลกอริทึมถามหา "ต้นไม้" เพื่อค้นหาเป็นอาร์เรย์ numpy เพื่อสร้าง "ต้นไม้" จากพิกัดพิกเซลทั้งหมดจากชุดข้อมูลนี้ฉันจำเป็นต้องจัดเก็บทั้งหมดของพวกเขาอย่างใดหากคุณมีทางออกที่ดีกว่าโปรดแจ้งให้เราทราบ!
irakhman

คำตอบ:


7

จะเพิ่มเป็นความคิดเห็น แต่ใช้เวลานานหน่อย - ในกรณีที่คุณต้องการใช้ gdal / ogr ภายในไพ ธ อน - สิ่งนี้อาจใช้งานได้ (แฮ็คเข้าด้วยกันจากรหัสอื่น ๆ ที่ฉันมี - ไม่ผ่านการทดสอบ!) พิกเซลแรสเตอร์เป็นรูปหลายเหลี่ยมเซนทรอยด์คุณเพียงแค่ค้นหาแรสเตอร์ที่ xy ของเซนทรอยด์ ฉันไม่รู้ว่าการแลกเปลี่ยนความเร็วอาจจะเป็น ...

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

สิ่งนี้จะทำให้คุณไป ค่าแรสเตอร์จะถูกอ่านโดยใช้rasterioและพิกัดศูนย์พิกเซลจะถูกแปลงเป็น Eastings / Northings ใช้เลียนแบบซึ่งจะถูกแปลงแล้วละติจูด / ลองจิจูดใช้pyproj อาร์เรย์ส่วนใหญ่มีรูปร่างเหมือนกันกับอินพุตแรสเตอร์

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
เมื่อใช้สิ่งนี้ฉันได้รับข้อความ "AttributeError: 'DatasetReader' ไม่มีแอตทริบิวต์ 'affine'" สำหรับบรรทัด "T0 = r.affine"
mitchus

@mitchus เห็นได้ชัดว่าaffineเป็นเพียงนามแฝงtransformและนามแฝงถูกลบออกจาก rasterio รุ่นล่าสุดแล้ว ฉันแก้ไขคำตอบแล้ว แต่ดูเหมือนว่าต้องได้รับการตรวจสอบโดยเพื่อนเนื่องจากฉันใหม่ที่นี่ :)
Autumnsault

1
ดูเหมือนว่าดัชนีจะผิดA.shapeซึ่งมีเพียงสองมิติเท่านั้น
Autumnsault
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.