Python GDAL bağlamalarını kullanarak raster köşe koordinatlarını nasıl alabilirim?


30

Gdal'ın Python bağlarını kullanarak köşe koordinatlarını (enlem / boyunda) raster dosyasından almanın bir yolu var mı?

Çevrimiçi olmayan birkaç arama beni bunun olmadığına ikna etti, bu yüzden gdalinfo çıktısını ayrıştırıp etrafta bir çalışma geliştirdim, biraz basit ama python ile daha az rahat olabilecek insanlar için biraz zaman kazanabileceğini düşündüm. Ayrıca sadece gdalinfo, her zaman böyle olduğuna inanmadığım köşe koordinatlarıyla birlikte coğrafi koordinatları içeriyorsa çalışır.

İşte geçici çözümüm, daha iyi çözümleri olan var mı?

Uygun bir raster üzerinde gdalinfo çıkışın ortasında bu gibi bir şeyle sonuçlanır:

Corner Coordinates:
Upper Left  (  -18449.521, -256913.934) (137d 7'21.93"E,  4d20'3.46"S)
Lower Left  (  -18449.521, -345509.683) (137d 7'19.32"E,  5d49'44.25"S)
Upper Right (   18407.241, -256913.934) (137d44'46.82"E,  4d20'3.46"S)
Lower Right (   18407.241, -345509.683) (137d44'49.42"E,  5d49'44.25"S)
Center      (     -21.140, -301211.809) (137d26'4.37"E,  5d 4'53.85"S)

Bu kod gdalinfo'ya benzeyen dosyalar üzerinde çalışacaktır. Bazen koordinatların derece, dakika ve saniye yerine derece ve ondalık olacağına inanıyorum; Bu durum için kod ayarlamak için önemsiz olması gerekir.

import numpy as np
import subprocess

def GetCornerCoordinates(FileName):
    GdalInfo = subprocess.check_output('gdalinfo {}'.format(FileName), shell=True)
    GdalInfo = GdalInfo.split('/n') # Creates a line by line list.
    CornerLats, CornerLons = np.zeros(5), np.zeros(5)
    GotUL, GotUR, GotLL, GotLR, GotC = False, False, False, False, False
    for line in GdalInfo:
        if line[:10] == 'Upper Left':
            CornerLats[0], CornerLons[0] = GetLatLon(line)
            GotUL = True
        if line[:10] == 'Lower Left':
            CornerLats[1], CornerLons[1] = GetLatLon(line)
            GotLL = True
        if line[:11] == 'Upper Right':
            CornerLats[2], CornerLons[2] = GetLatLon(line)
            GotUR = True
        if line[:11] == 'Lower Right':
            CornerLats[3], CornerLons[3] = GetLatLon(line)
            GotLR = True
        if line[:6] == 'Center':
            CornerLats[4], CornerLons[4] = GetLatLon(line)
            GotC = True
        if GotUL and GotUR and GotLL and GotLR and GotC:
            break
    return CornerLats, CornerLons 

def GetLatLon(line):
    coords = line.split(') (')[1]
    coords = coords[:-1]
    LonStr, LatStr = coords.split(',')
    # Longitude
    LonStr = LonStr.split('d')    # Get the degrees, and the rest
    LonD = int(LonStr[0])
    LonStr = LonStr[1].split('\'')# Get the arc-m, and the rest
    LonM = int(LonStr[0])
    LonStr = LonStr[1].split('"') # Get the arc-s, and the rest
    LonS = float(LonStr[0])
    Lon = LonD + LonM/60. + LonS/3600.
    if LonStr[1] in ['W', 'w']:
        Lon = -1*Lon
    # Same for Latitude
    LatStr = LatStr.split('d')
    LatD = int(LatStr[0])
    LatStr = LatStr[1].split('\'')
    LatM = int(LatStr[0])
    LatStr = LatStr[1].split('"')
    LatS = float(LatStr[0])
    Lat = LatD + LatM/60. + LatS/3600.
    if LatStr[1] in ['S', 's']:
        Lat = -1*Lat
    return Lat, Lon

FileName = Image.cub
# Mine's an ISIS3 cube file.
CornerLats, CornerLons = GetCornerCoordinates(FileName)
# UpperLeft, LowerLeft, UpperRight, LowerRight, Centre
print CornerLats
print CornerLons

Ve bu bana verir:

[-4.33429444 -5.82895833 -4.33429444 -5.82895833 -5.081625  ] 
[ 137.12275833  137.12203333  137.74633889  137.74706111  137.43454722]

Yanıtlar:


29

İşte harici bir program çağırmadan bunu yapmanın başka bir yolu.

Bunun yaptığı, dört köşenin koordinatlarını geotransformdan almak ve osr.CoordinateTransformation kullanarak bunları lon / lat'a dönüştürmektir.

from osgeo import gdal,ogr,osr

def GetExtent(gt,cols,rows):
    ''' Return list of corner coordinates from a geotransform

        @type gt:   C{tuple/list}
        @param gt: geotransform
        @type cols:   C{int}
        @param cols: number of columns in the dataset
        @type rows:   C{int}
        @param rows: number of rows in the dataset
        @rtype:    C{[float,...,float]}
        @return:   coordinates of each corner
    '''
    ext=[]
    xarr=[0,cols]
    yarr=[0,rows]

    for px in xarr:
        for py in yarr:
            x=gt[0]+(px*gt[1])+(py*gt[2])
            y=gt[3]+(px*gt[4])+(py*gt[5])
            ext.append([x,y])
            print x,y
        yarr.reverse()
    return ext

def ReprojectCoords(coords,src_srs,tgt_srs):
    ''' Reproject a list of x,y coordinates.

        @type geom:     C{tuple/list}
        @param geom:    List of [[x,y],...[x,y]] coordinates
        @type src_srs:  C{osr.SpatialReference}
        @param src_srs: OSR SpatialReference object
        @type tgt_srs:  C{osr.SpatialReference}
        @param tgt_srs: OSR SpatialReference object
        @rtype:         C{tuple/list}
        @return:        List of transformed [[x,y],...[x,y]] coordinates
    '''
    trans_coords=[]
    transform = osr.CoordinateTransformation( src_srs, tgt_srs)
    for x,y in coords:
        x,y,z = transform.TransformPoint(x,y)
        trans_coords.append([x,y])
    return trans_coords

raster=r'somerasterfile.tif'
ds=gdal.Open(raster)

gt=ds.GetGeoTransform()
cols = ds.RasterXSize
rows = ds.RasterYSize
ext=GetExtent(gt,cols,rows)

src_srs=osr.SpatialReference()
src_srs.ImportFromWkt(ds.GetProjection())
#tgt_srs=osr.SpatialReference()
#tgt_srs.ImportFromEPSG(4326)
tgt_srs = src_srs.CloneGeogCS()

geo_ext=ReprojectCoords(ext,src_srs,tgt_srs)

Bazı kod metageta projesinden osr.CoordinateTransformation fikri bu cevap


Müthiş, teşekkürler. Ve uygun çizgilerin gdalinfo çıktısında olup olmadığına bakmaksızın çalışır.
EddyTheB

Bunun tgt_srs = src_srs.CloneGeogCS () ile daha iyi olacağını düşünüyorum. İlk rasterlerim Mars'ın görüntüleri, bu yüzden EPSG (4326) kullanmak ideal değil, ancak CloneGeogCS () yansıtılandan coğrafi koordinatlara değişiyor gibi görünüyor.
EddyTheB

Kesinlikle. CloneGeogCS kullanmak için cevabı güncelledik. Ancak, sadece GetExtent ve ReprojectCoords işlevlerinin kullanımını göstermeye çalışıyordum. İstediğiniz her şeyi hedef srs olarak kullanabilirsiniz.
user2856,

Evet, teşekkür ederim, başka türlü bulamazdım.
EddyTheB

Projeksiyonu olmayan ve RPC'leri belirleyen bir veri kümeniz varsa? Wkt işlevinden içe aktarma başarısız olur. Bir transformatör kullanarak ölçüyü hesaplamak mümkündür ancak yukarıdaki yöntemden bir yol olup olmadığını merak ediyordum.
Thomas

41

Bu çok daha az kod satırında yapılabilir

src = gdal.Open(path goes here)
ulx, xres, xskew, uly, yskew, yres  = src.GetGeoTransform()
lrx = ulx + (src.RasterXSize * xres)
lry = uly + (src.RasterYSize * yres)

ulx, ulysol üst köşe lrx,lry sağ alt köşesidir

Osr kütüphanesi (gdal parçası), noktaları herhangi bir koordinat sistemine dönüştürmek için kullanılabilir. Tek bir nokta için:

from osgeo import ogr
from osgeo import osr

# Setup the source projection - you can also import from epsg, proj4...
source = osr.SpatialReference()
source.ImportFromWkt(src.GetProjection())

# The target projection
target = osr.SpatialReference()
target.ImportFromEPSG(4326)

# Create the transform - this can be used repeatedly
transform = osr.CoordinateTransformation(source, target)

# Transform the point. You can also create an ogr geometry and use the more generic `point.Transform()`
transform.TransformPoint(ulx, uly)

Çok daha karmaşık bir mesele olacaktır bir bütün raster görüntü reproject, ama çok bunun için GDAL> = 2.0 teklifler kolay bir çözüm için: gdal.Warp.


Bu, uzlaşma için Pythonic cevabıdır - yeniden projeksiyon için eşit-Pythonic bir çözüm harika olurdu, Dedi ki - PostGIS'deki sonuçları kullandım, bu yüzden sadece dönüştürülmemiş kapsamı ve ST_Transform(ST_SetSRID(ST_MakeBox2D([sonuçları] geçtim ),28355),4283). (Bir kelime oyunu - 'T' girişi src.GetGeoTransform()büyük harfle yazılmalıdır).
GT.

@GT. Bir örnek
James

1

Bu şekilde yaptım ... biraz zor kodlu ama gdalinfo ile hiçbir şey değişmezse, UTM tarafından yansıtılan görüntüler için işe yarar!

imagefile= /pathto/image
p= subprocess.Popen(["gdalinfo", "%s"%imagefile], stdout=subprocess.PIPE)
out,err= p.communicate()
ul= out[out.find("Upper Left")+15:out.find("Upper Left")+38]
lr= out[out.find("Lower Right")+15:out.find("Lower Right")+38]

2
Bu, hem gdalinfokullanıcıların yolunda (her zaman olduğu gibi, hem de özellikle pencerelerde) mevcut olmasına ve katı ara yüzü olmayan basılı bir çıktının ayrıştırılmasına - yani doğru boşluk için bu 'sihirli sayılara' dayanmaya dayandığından oldukça kırılgandır . Gdal, bunu daha açık ve sağlam bir şekilde yapabilen kapsamlı piton bağları sağladığında gereksizdir
James

1

Rasteriniz döndürülürse, altı afin dönüşüm katsayısının her birini göz önünde bulundurmanız gerektiğinden, matematik biraz daha karmaşık hale gelir. Kullanmayı düşünün afin döndürülmüş bir benzeşik transformasyon / coğrafi dönüşümün dönüştürmek için:

from affine import Affine

# E.g., from a GDAL DataSet object:
# gt = ds.GetGeoTransform()
# ncol = ds.RasterXSize
# nrow = ds.RasterYSize

# or to work with a minimal example
gt = (100.0, 17.320508075688775, 5.0, 200.0, 10.0, -8.660254037844387)
ncol = 10
nrow = 15

transform = Affine.from_gdal(*gt)
print(transform)
# | 17.32, 5.00, 100.00|
# | 10.00,-8.66, 200.00|
# | 0.00, 0.00, 1.00|

Şimdi dört köşe koordinat çiftini oluşturabilirsiniz:

c0x, c0y = transform.c, transform.f  # upper left
c1x, c1y = transform * (0, nrow)     # lower left
c2x, c2y = transform * (ncol, nrow)  # lower right
c3x, c3y = transform * (ncol, 0)     # upper right

Ayrıca ızgara temelli sınırlara da ihtiyacınız varsa (xmin, ymin, xmax, ymax):

xs = (c0x, c1x, c2x, c3x)
ys = (c0y, c1y, c2y, c3y)
bounds = min(xs), min(ys), max(xs), max(ys)

0

PyGE için OSGEO / GDAL modülünün daha yeni sürümlerine, sistem çağrılarını gerektirmeden GDAL yardımcı programlarını doğrudan koddan çağırabilirim. örneğin aramak için alt işlemi kullanmak yerine:

gdalinfo one, meta veri / açıklama dosyalarının gösterimini elde etmek için gdal.Info dosyasını (the_name_of_the_file) çağırabilir.

ya da çağırmak için alt işlemi kullanmak yerine: gdalwarp biri cal gdal olabilir.

Halen dahili bir işlev olarak kullanılabilen GDAL yardımcı programlarının listesi: http://erouault.blogspot.com/2015/10/gdal-and-ogr-utilities-as-library.html

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.