Lấy giá trị pixel của raster GDAL dưới điểm OGR mà không có NumPy?


45

Tôi đang làm việc trên một mô hình tính toán về sự phong phú của các loài thụ phấn hoang dã trên toàn cảnh. Bản thân mô hình đã hoàn tất và tôi hiện đang vật lộn với một bước xử lý hậu kỳ.

Tôi có raster cung cấp trình thụ phấn GDAL của tôi trông giống như thế này (màu nhạt hơn có nghĩa là lượt truy cập của người thụ phấn cao hơn đến một pixel):

Rasterale raster đại diện cho cung cấp thụ phấn trên một cảnh quan

Và tôi có một shapefile các điểm đại diện cho các vị trí mẫu trên phong cảnh:

nhập mô tả hình ảnh ở đây

Tôi đang cố gắng chạy một số phân tích về các pixel theo các điểm này, nhưng để làm như vậy, tôi cần có thể trích xuất giá trị của một pixel dưới một điểm.

Có thể trích xuất giá trị của pixel dưới một điểm chỉ bằng OGR và GDAL thông qua Python không? Tôi muốn tránh đọc toàn bộ raster vào bộ nhớ ReadAsArray(), vì các raster đầu ra của tôi rất, rất lớn (quá lớn để vừa với bộ nhớ).

Tôi nhận thấy bài đăng này , tương tự, nhưng yêu cầu một cuộc gọi dòng lệnh.


2
Điều gì về ReadAsArray () và chỉ đọc trong điểm? Vì vậy, chỉ đọc các tế bào duy nhất mà bạn quan tâm? Bạn sẽ cần phải chuyển đổi từ điểm coords sang không gian pixel và trích xuất ô cần thiết.
Jay Laura

1
Nhìn vào mã cho gdalsrsinfo, nó cho bạn thấy làm thế nào để sử dụng GDALInvertGeoTransform () và chuyển đổi giữa các không gian địa lý và không gian điểm ảnh: trac.osgeo.org/gdal/browser/trunk/gdal/apps/gdalsrsinfo.cpp

Nếu bạn không phiền khi sử dụng PostGIS, hãy xem cái này . Nó cực kỳ nhanh và chỉ là 1 dòng SQL.
mlt

Tôi sẽ ghi nhớ điều đó nếu tôi gặp phải vấn đề này và có quyền truy cập vào cơ sở dữ liệu PostGIS! Tôi đã không giải quyết vấn đề đặc biệt này, vì vậy giải pháp GDAL dưới đây đã thực hiện được mẹo này. Cảm ơn, mặc dù!
James

@kyle Tôi không biết liệu mọi thứ đã thay đổi nhưng có vẻ như đó là GDALInvGeoTransform không đảo ngượcđây là một ví dụ .
mlt

Câu trả lời:


60

Bạn có thể sử dụng phương thức gdal.Dataset hoặc gdal.Band ReadRaster. Xem hướng dẫn API GDALOGR và ví dụ bên dưới. ReadRaster không sử dụng / yêu cầu numpy, giá trị trả về là dữ liệu nhị phân thô và cần được giải nén bằng mô-đun cấu trúc python tiêu chuẩn .

Một ví dụ:

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

Ngoài ra, vì lý do bạn đưa ra không sử dụng numpylà để tránh đọc toàn bộ mảng khi sử dụng ReadAsArray(), dưới đây là một ví dụ sử dụng numpyvà không đọc toàn bộ raster trong.

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

Và làm thế nào bạn có thể lưu dưới dạng csv, bảng hoặc đối tượng khác? Một vật thể có cùng độ dài tọa độ objetct
gonzalez.ivan90

Đây là câu hỏi, Luke. Cảm ơn! gis.stackexchange.com/questions/269603/ Từ
gonzalez.ivan90

các dòng gán px/ pysai trong trường hợp mx / my nằm ngoài giới hạn của rb, bởi vì int(-0.5) == 0. Bạn cần floor(...), và sau đó bạn cần kiểm tra xem không có px/ pynào nhỏ hơn 0 (hoặc thực hiện trước khi gọi int()), bởi vì các chỉ số phủ định hoạt động (chúng có mặt khác của mảng). Tôi rất muốn biết nếu có một cách gọn gàng hơn để giải quyết vấn đề này. Ngoài ra, làm thế nào để bạn viết lại những dòng đó để chúng xử lý các phép quay một cách chính xác?
hư vô
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.