使用python从栅格获取纬度/经度?


10

我想知道是否有人在不使用ArcGIS的情况下从栅格中获取高程数据,而是以python list或dict?

我以元组列表的形式获取XY数据:

xy34 =[perp_obj[j].CalcPnts(float(i.dist), orientation) for j in range (len(perp_obj))]

我想遍历列表或将其传递给函数或类方法,以获取xy对的相应高度。

我对该主题进行了一些研究,gdal API听起来很有前途。谁能建议我如何处理事情,陷阱和示例代码?


不能选择GDAL,因为我无法在正在使用的计算机上编辑系统路径变量!

有人知道其他方法吗?


2
不幸的是,您确实需要在系统上运行GDAL才能使用Python进行栅格处理。使用“无法在机器上编辑系统路径变量”时,您是否在参考这些说明?我发现此安装方法非常差,我既不使用也不推荐使用。如果您使用的是Windows,则以简单方式安装GDAL / Python 。
— Mike T

是的,我确实是。我现在不在工作,但我会检查您发布的链接。看起来很有希望!感谢您回到我的问题!
— LarsVegas 2012年

我已经在许多工作计算机上使用了Christoph Gohlke的安装程序(上面已链接),它真的很简单。您只需要确保与Python版本以及32位或64位Windows匹配即可。在使用它时,您还应该从同一个地方获取NumPy,因为GDAL需要这样做,如以下答案所示。
— Mike T

Answers:


15

与@Aragon的答案相比,这是使用GDAL的更具编程性的方式。我尚未对其进行测试,但是过去对我有用的大部分都是样板代码。它依赖于Numpy和GDAL绑定,仅此而已。

import osgeo.gdal as gdal
import osgeo.osr as osr
import numpy as np
from numpy import ma

def maFromGDAL(filename):
    dataset = gdal.Open(filename, gdal.GA_ReadOnly)

    if dataset is None:
        raise Exception()

    # Get the georeferencing metadata.
    # We don't need to know the CRS unless we want to specify coordinates
    # in a different CRS.
    #projection = dataset.GetProjection()
    geotransform = dataset.GetGeoTransform()

    # We need to know the geographic bounds and resolution of our dataset.
    if geotransform is None:
        dataset = None
        raise Exception()

    # Get the first band.
    band = dataset.GetRasterBand(1)
    # We need to nodata value for our MaskedArray later.
    nodata = band.GetNoDataValue()
    # Load the entire dataset into one numpy array.
    image = band.ReadAsArray(0, 0, band.XSize, band.YSize)
    # Close the dataset.
    dataset = None

    # Create a numpy MaskedArray from our regular numpy array.
    # If we want to be really clever, we could subclass MaskedArray to hold
    # our georeference metadata as well.
    # see here: http://docs.scipy.org/doc/numpy/user/basics.subclassing.html
    # For details.
    masked_image = ma.masked_values(image, nodata, copy=False)
    masked_image.fill_value = nodata

    return masked_image, geotransform

def pixelToMap(gt, pos):
    return (gt[0] + pos[0] * gt[1] + pos[1] * gt[2],
            gt[3] + pos[0] * gt[4] + pos[1] * gt[5])

# Reverses the operation of pixelToMap(), according to:
# https://en.wikipedia.org/wiki/World_file because GDAL's Affine GeoTransform
# uses the same values in the same order as an ESRI world file.
# See: http://www.gdal.org/gdal_datamodel.html
def mapToPixel(gt, pos):
    s = gt[0] * gt[4] - gt[3] * gt[1]
    x = (gt[4] * pos[0] - gt[1] * pos[1] + gt[1] * gt[5] - gt[4] * gt[2]) / s
    y = (-gt[3] * pos[0] + gt[0] * pos[1] + gt[3] * gt[2] - gt[0] * gt[5]) / s
    return (x, y)

def valueAtMapPos(image, gt, pos):
    pp = mapToPixel(gt, pos)
    x = int(pp[0])
    y = int(pp[1])

    if x < 0 or y < 0 or x >= image.shape[1] or y >= image.shape[0]:
        raise Exception()

    # Note how we reference the y column first. This is the way numpy arrays
    # work by default. But GDAL assumes x first.
    return image[y, x]

try:
    image, geotransform = maFromGDAL('myimage.tif')
    val = valueAtMapPos(image, geotransform, (434323.0, 2984745.0))
    print val
except:
    print('Something went wrong.')

1
看到对我的问题的编辑...无论如何都要发帖!我赞成。
— LarsVegas

1
啊,该死!好吧,至少在这里是为了后代。TBH,在数学mapToPixel()和pixelToMap()是最重要的一点,只要你可以创建一个numpy的阵列(或常规的Python之一,但他们一般是效率不高,对这样的事情),并获得阵列的地理边界框。
— MerseyViking

1
对于将参数反转为numpy数组的注释(和代码),+ 1。我到处都在寻找代码中的错误,而这次交换解决了它!
— aldo 2015年

1
然后,我建议您的矩阵(gt在示例中)是错误的。CGAL中使用的仿射矩阵(请参阅:gdal.org/gdal_datamodel.html)通常是可逆的(否则,您将需要一些时髦的缩放值)。因此,只要有g = p.A我们可以做的,p = g.A^-1Numpy.linalg就我们的目的而言是个重量级人物-我们可以将所有内容简化为两个简单的方程式。
— MerseyViking

1
我已经重新编辑了代码以使用简单的代数而不是numpy linalg。如果数学错误,请修复Wikipedia页面。
— MerseyViking

3

在这里查看我的答案...并在此处阅读一些信息。以下信息来自Geotips:

使用gdallocationinfo,我们可以查询某个点的海拔:

$ gdallocationinfo gmted/all075.vrt -geoloc 87360 19679

上面命令的输出格式为:

Report:
   Location: (87360P,19679L)
Band 1:
   Value: 1418

这意味着在提供的地理位置上的高程值为1418。


刚刚发现我无法使用GDAL,因为我无法在正在使用的计算机上编辑系统变量。感谢您的输入。
— LarsVegas


-1

提供的python代码基于给定的x,y坐标提取栅格像元的值数据。它是从此出色来源中摘录的一个示例的略微改动版本。它基于,GDAL而numpy不是标准python发行版的一部分。感谢@Mike Toews指出了适用于Python扩展软件包的非官方Windows二进制文件,以使安装和使用变得快速简便。

import os, sys, time, gdal
from gdalconst import *


# coordinates to get pixel values for
xValues = [122588.008]
yValues = [484475.146]

# set directory
os.chdir(r'D:\\temp\\AHN2_060')

# register all of the drivers
gdal.AllRegister()
# open the image
ds = gdal.Open('i25gn1_131.img', GA_ReadOnly)

if ds is None:
    print 'Could not open image'
    sys.exit(1)

# get image size
rows = ds.RasterYSize
cols = ds.RasterXSize
bands = ds.RasterCount

# get georeference info
transform = ds.GetGeoTransform()
xOrigin = transform[0]
yOrigin = transform[3]
pixelWidth = transform[1]
pixelHeight = transform[5]

# loop through the coordinates
for xValue,yValue in zip(xValues,yValues):
    # get x,y
    x = xValue
    y = yValue

    # compute pixel offset
    xOffset = int((x - xOrigin) / pixelWidth)
    yOffset = int((y - yOrigin) / pixelHeight)
    # create a string to print out
    s = "%s %s %s %s " % (x, y, xOffset, yOffset)

    # loop through the bands
    for i in xrange(1,bands):
        band = ds.GetRasterBand(i) # 1-based index
        # read data and add the value to the string
        data = band.ReadAsArray(xOffset, yOffset, 1, 1)
        value = data[0,0]
        s = "%s%s " % (s, value) 
    # print out the data string
    print s
    # figure out how long the script took to run

看来这只是MerseyViking上面提供的功能的通用性,灵活性较低的版本?
— WileyB
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.