使用python gdal从GeoTiff获取坐标和相应的像素值,并将其另存为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)
...

关于从tiff(从GeoTIFF文件获取纬度和经度)获取纬度/经度坐标,这里存在类似的问题,答案显示了如何仅获取左上角的x和y像素坐标。我需要获取所有投影的像素坐标,以及获取像素值并将其保存在numpy数组中。我该怎么做?


您想要10366×7273 =超过7千5百万点吗?
Mike T

@MikeT我想是的,我真的不知道如何解决我要解决的问题的更好的解决方案:我需要从该数据集中找到最接近的像素坐标到US块的每个质心,然后分配通过搜索,我意识到cKDTree查询将帮助我进行最近邻居搜索。该算法的Python函数要求以“ numpy”数组的形式查询“树”。以生成“树”在此数据集中所有像素坐标中,我需要以某种方式存储所有像素坐标。如果您有更好的解决方案,请告诉我!
irakhman 2015年

Answers:


7

会添加为注释,但会有点长-如果您想在python中使用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
使用此方法时,对于行“ T0 = r.affine”,我得到消息“ AttributeError:'DatasetReader'对象没有属性'affine'”
mitchus

@mitchus显然affine只是的别名transform,并且该别名已从最新版本的rasterio中删除。我编辑了答案,但由于我是新来的,因此似乎需要同行评审。:)
Autumnsault '19

1
看起来索引也有误A.shape,它只有两个维度。
Autumnsault '19
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.