在没有NumPy的情况下获取OGR点下的GDAL栅格的像素值?


45

我正在研究整个景观中大量野生传粉媒介的计算模型。该模型本身已经完成,现在我正在努力进行后处理步骤。

我的GDAL授粉媒介供应栅格看起来像这样(较浅的颜色表示授粉媒介对像素的访问量较高):

代表景观上授粉媒介供应的灰度栅格

我有一个OGR形状文件,该文件的点代表景观上的样本位置:

在此处输入图片说明

我正在尝试对这些点下的像素进行一些分析,但是要这样做,我需要能够提取一个点下的像素的值。

是否可以通过Python仅使用OGR和GDAL提取点下的像素值?我宁愿避免通过读取整个栅格到内存中ReadAsArray(),因为我的输出栅格非常大(太大而无法容纳到内存中)。

我注意到这篇文章,这很相似,但是需要命令行调用。


2
那么ReadAsArray()只读一点呢?因此,仅读取您感兴趣的单个单元格?您将需要从点坐标转换为像素空间并提取必要的像元。
杰伊·劳拉

1
查看gdalsrsinfo的代码,它向您展示如何使用GDALInvertGeoTransform()以及如何在地理空间和像素空间之间切换: trac.osgeo.org/gdal/browser/trunk/gdal/apps/gdalsrsinfo.cpp

如果您不介意使用PostGIS,请参阅this。它非常快,只有1条SQL行。
2013年

如果遇到此问题并可以访问PostGIS数据库,请记住这一点!我没有解决这个特定的问题,因此下面的GDAL解决方案可以解决问题。不过谢谢!
詹姆斯,

@kyle我不知道事情是否已经改变,但是看起来它是GDALInvGeoTransform不能反转的这是一个例子
mlt

Answers:


60

您可以使用gdal.Datasetgdal.Band ReadRaster方法。请参阅GDALOGR 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是为了避免在using中读取整个数组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,表格或其他对象?坐标对象长度相同的对象
gonzalez.ivan90


在mx / my超出的范围的情况下,分配px/ 的行py是错误的rb,因为int(-0.5) == 0。您需要floor(...),然后需要检查px/ py都不小于零(或在调用之前执行int()),因为负索引有效(它们获取数组的另一侧)。我很想知道是否有一种更整洁的方法来解决这个问题。另外,如何重新编写这些行,以便它们正确处理旋转?
结束了naught101
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.