Python kullanarak rasterden lat / uzunta yükseklik mi alıyorsunuz?


10

Herkes ArcGIS kullanmadan bir raster yükseklik verileri alma konusunda biraz deneyim olup olmadığını merak , ama yerine bir python listveya bilgi almak dict?

XY verilerimi tuples listesi olarak alıyorum:

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

Listede döngü veya xy-çiftleri için karşılık gelen yükseklik elde etmek için bir işlev veya sınıf yöntemine geçmek istiyorum.

Konu hakkında biraz araştırma yaptım ve gdal API kulağa umut verici geliyor. Herkes bana nasıl şeyler, tuzaklar, örnek kod hakkında gitmek için tavsiye verebilir misiniz?


Üzerinde çalıştığım makinede sistem yolu değişkenini düzenleyemediğim için GDAL bir seçenek değil!

Farklı bir yaklaşım bilen var mı?


2
ne yazık ki, Python'da bir rasterle herhangi bir şey yapmak için GDAL'ı sisteminizde çalıştırmanız gerekiyor. "Makinede sistem yolu değişkenini düzenleyemiyorum" ile bu talimatlarabaşvuruyorsunuz ? Bu kurulum yöntemini çok zayıf buluyorum ve kullanmıyorum ya da tavsiye etmiyorum. Windows kullanıyorsanız, GDAL / Python'u basit bir şekilde yükleyin .
Mike T

Evet, gerçekten öyleydim. Şu anda işte değilim, ancak gönderdiğiniz bağlantıya göz atacağım. Umut verici görünüyor! Soruma geri geldiğin için teşekkürler!
LarsVegas

Yükleyiciyi Christoph Gohlke (yukarıda bağlantılı) tarafından birçok iş bilgisayarında kullandım ve gerçekten basit. Yalnızca Python ve 32 veya 64 bit Windows sürümleriyle eşleştiğinizden emin olmanız gerekir. Siz oradayken, aşağıdaki cevaplarda gösterildiği gibi, GDAL tarafından ihtiyaç duyulduğu için aynı yerden NumPy'yi de almalısınız.
Mike T

Yanıtlar:


15

GDAL kullanmanın @ Aragon'un cevabından daha programlı bir yolu. Test etmedim, ama çoğunlukla geçmişte benim için çalışan kazan plakası kodu. Numpy ve GDAL bağlarına dayanıyor, ama hepsi bu.

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
sorumun düzenlemesine bakın ... yine de gönderdiğiniz için teşekkürler! Onu iptal ettim.
LarsVegas

1
Kahretsin! En azından gelecek nesiller için burada. TBH, matematiksel bir dizi (veya normal bir Python dizisi oluşturabildiğiniz sürece mapToPixel()ve içindeki matematiği ve pixelToMap()önemli bitidir, ancak genellikle bu tür şeyler için verimli değildir) ve dizinin coğrafi sınırlayıcı kutusunu alırsınız.
MerseyViking

1
Parametreleri numpy dizisine geri döndürme hakkındaki yorum (ve kod) için +1. Her yerde kodumda bir hata arıyordum ve bu takas sorunu çözdü!
aldo

1
Sonra matrisinizin ( gtörnekte) yanlış olduğunu öneririm . CGAL'de kullanılan bir afin matris (bkz: gdal.org/gdal_datamodel.html ) genellikle ters çevrilebilir (aksi halde devam eden bazı korkak ölçekleme değerleriniz vardır). Yani sahip g = p.Aolduğumuz yerde p = g.A^-1Numpy.linalg bizim amacımız için biraz ağırdır - her şeyi iki basit denkleme indirebiliriz.
MerseyViking

1
Numpy linalg yerine basit cebiri kullanmak için kodu yeniden düzenledim. Matematik yanlışsa Wikipedia sayfasını düzeltin.
MerseyViking

3

Cevabımı buradan kontrol edin ... ve bazı bilgiler için burayı okuyun . Geotips'ten aşağıdaki bilgiler alınmıştır:

İle gdallocationinfo , bir noktada yüksekliği sorgulayabilir:

$ gdallocationinfo gmted/all075.vrt -geoloc 87360 19679

Yukarıdaki komutun çıktısı şu şekildedir:

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

Bu, sağlanan coğrafi konumdaki yükseklik değerinin 1418 olduğu anlamına gelir.


Az önce üzerinde çalıştığım makinede sistem değişkenimi düzenleyemediğim için GDAL kullanamayacağımı öğrendim. Yine de giriş için teşekkürler.
LarsVegas

0

Örneğin, GDAL (ve Python, numpy gerekmez) tabanlı bu koda bakın: https://github.com/geometalab/retrieve-height-service


Kodun açık kaynak lisanslı görünmemesi talihsiz bir durumdur.
Ben Crowell

Şimdi :-) var.
Stefan

-1

Sağlanan python kodu, verilen x, y koordinatlarına dayalı olarak bir raster hücresinin değer verilerini çıkarır. Bu mükemmel kaynaktan bir örneğin biraz değiştirilmiş bir versiyonudur . Standart python dağılımına dayanır GDALve numpybunlar bir parçası değildir. Hızlı ve kolay kurulum ve kullanım için Python Uzatma Paketleri için Resmi Olmayan Windows İkilileri işaret @Mike Toews sayesinde.

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

Bu, MerseyViking'in yukarıda sunduklarının daha az genel, daha az esnek bir sürümü gibi görünüyor?
WileyB
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.