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
残念ながら、Pythonでラスターを使用して何かを実行するには、システムでGDALを実行する必要があります。「マシンのシステムパス変数を編集できません」で、これらの指示を参照していますか?このインストール方法は非常に貧弱であり、使用も推奨もしていません。Windowsを使用している場合は、GDAL / Pythonを簡単な方法でインストールします。
マイクT

はい、確かにそうでした。今は仕事をしていませんが、あなたが投稿したリンクをチェックします。有望に見えます!私の質問に戻ってくれてありがとう!
LarsVegas

私は多くの仕事用コンピューターでChristoph Gohlke(上記にリンク)のインストーラーを使用しましたが、それは本当に簡単です。Pythonのバージョンと32ビットまたは64ビットのWindowsのいずれかに一致していることを確認するだけで済みます。以下の回答に示すように、GDALはNumPyを必要とするため、同じ場所からNumPyも取得する必要があります。
マイクT

回答:


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()は重要です。派手な配列(または通常のPythonの配列ですが、一般にこの種のものでは効率的ではありません)を作成し、配列の地理的な境界ボックスを取得できる限り、重要です。
MerseyViking 2012

1
numpy配列へのパラメーターの反転に関するコメント(およびコード)の+1。私はコードのバグをどこでも探していましたが、このスワップで修正されました!
アルド2015

1
次に、マトリックス(gt例)が間違っていることをお勧めします。CGALで使用されているアフィンマトリックス(gdal.org/gdal_datamodel.htmlを参照)は、通常、反転可能です(そうでない場合、いくつかのファンキーなスケーリング値が発生します)。だから我々は持っているg = p.A私たちも行うことができますp = g.A^-1Numpy.linalgは、我々の目的のためにビットのヘビー級である-我々は2つの単純な方程式にすべてを減らすことができます。
MerseyViking 2017年

1
numpy linalgではなく単純な代数を使用するようにコードを再編集しました。数学が間違っている場合は、ウィキペディアのページを修正してください。
MerseyViking 2017年

3

ここで私の答えをチェックしてください ...そして、いくつかの情報についてはここを読んください。次の情報は、Geotipsから取得されました。

gdallocationinfo、我々はポイントに標高を照会できます。

$ gdallocationinfo gmted/all075.vrt -geoloc 87360 19679

上記のコマンドの出力は次の形式になります。

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

つまり、提供されたジオロケーションの標高値は1418です。


作業中のマシンでシステム変数を編集できないため、GDALを使用できないことがわかりました。入力ありがとうございます。
LarsVegas

0

たとえば、GDAL(およびPython、numpyは不要)に基づくこのコードを参照してください:https : //github.com/geometalab/retrieve-height-service


コードがオープンソースのライセンスを受けていないように見えるのは残念です。
Ben Crowell

今では:-)があります。
Stefan

-1

提供されているpythonコードは、指定されたx、y座標に基づいてラスターセルの値データを抽出します。これは、この優れたソースからの例を少し変更したバージョンです。これはに基づいてGDALおりnumpy、標準のPythonディストリビューションの一部ではありません。インストールと使用をすばやく簡単に行えるようにするPython拡張パッケージの非公式Windowsバイナリを指摘してくれた@Mike Toewsに感謝します。

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 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.