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


10

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

我以元组列表的形式获取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坐标提取栅格像元的值数据。它是从此出色来源中摘录的一个示例的略微改动版本。它基于,GDALnumpy不是标准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.