파이썬을 사용하여 래스터에서 위도 / 경도를 높이시겠습니까?


10

누군가 ArcGIS를 사용하지 않고 래스터에서 고도 데이터를 얻는 경험이 있는지 궁금 하지만 오히려 정보를 파이썬 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

Christoph Gohlke (위 링크)의 설치 프로그램을 많은 업무용 컴퓨터에서 사용했는데 정말 간단합니다. Python 버전과 32 비트 또는 64 비트 Windows와 일치해야합니다. 아래 답변에 표시된 것처럼 GDAL이 필요하기 때문에 NumPy를 동일한 위치에서 가져와야합니다.
Mike 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
내 질문에 대한 수정 사항을 참조하십시오 ... 어쨌든 게시 주셔서 감사합니다! 나는 그것을 upvoted.
LarsVegas

1
아 젠장! 적어도 후손을 위해 여기에 있습니다. numpy 배열 (또는 일반적인 파이썬 배열을 만들 수 있지만 일반적으로 이러한 종류의 작업에는 효율적이지 않음)과 배열의 지리적 경계 상자를 얻는 한, TBH, 수학 mapToPixel()pixelToMap()중요한 비트입니다.
MerseyViking

1
numpy 배열로 매개 변수를 되 돌리는 것에 대한 주석 (및 코드)은 +1입니다. 나는 어디에서나 내 코드의 버그를 찾고 있었고이 스왑은 그것을 고쳤다!
aldo

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

0

예를 들어 GDAL을 기반으로하는이 코드 (및 Python, 숫자가 필요 없음)를 참조하십시오 : https://github.com/geometalab/retrieve-height-service


불행히도 코드가 오픈 소스 라이센스가 아닌 것 같습니다.
벤 크로 웰

이제 :-)가 있습니다.
Stefan

-1

제공된 파이썬 코드는 주어진 x, y 좌표를 기반으로 래스터 셀의 값 데이터를 추출합니다. 이 훌륭한 소스 에서 예제의 약간 변경된 버전입니다 . 그것은 표준 파이썬 배포판 에 기반 GDAL하고 numpy있지 않습니다. Python Extension Packages비공식 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.