पायथन जीडीएएल बाइंडिंग का उपयोग करके रैस्टर कॉर्नर निर्देशांक कैसे प्राप्त करें?


30

क्या गर्ड के पायथन बाइंडिंग का उपयोग करके एक रेखापुंज फ़ाइल से कोने निर्देशांक (डिग्री अक्षांश / लंबे समय में) प्राप्त करने का एक तरीका है?

ऑनलाइन कुछ खोजों ने मुझे आश्वस्त किया है कि ऐसा नहीं है, इसलिए मैंने gdalinfo आउटपुट को पार्स करके चारों ओर एक काम विकसित किया है, यह कुछ हद तक बुनियादी है लेकिन मैंने सोचा कि यह उन लोगों के लिए कुछ समय बचा सकता है जो अजगर के साथ कम आरामदायक हो सकते हैं। यह केवल तभी काम करता है यदि gdalinfo में कोने निर्देशांक के साथ भौगोलिक निर्देशांक शामिल हैं, जो मुझे नहीं लगता कि हमेशा मामला है।

यहाँ मेरा समाधान है, क्या किसी के पास कोई बेहतर उपाय है?

एक उचित रेखापुंज पर gdalinfo इस उत्पादन के माध्यम से इस तरह से कुछ के रूप में परिणाम:

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)

यह कोड उन फाइलों पर काम करेगा जो गदलिनफो की तरह दिखती हैं। मेरा मानना ​​है कि कभी-कभी निर्देशांक डिग्री और मिनट के बजाय डिग्री और दशमलव में होंगे; यह उस स्थिति के लिए कोड को समायोजित करने के लिए तुच्छ होना चाहिए।

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

और वह मुझे देता है:

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

जवाबों:


29

यहां बाहरी कार्यक्रम को कॉल किए बिना इसे करने का एक और तरीका है।

यह जो करता है उसे जियोट्रांसफ़ॉर्म से चार कोनों के निर्देशांक मिलते हैं और उन्हें osr.CoordinateTransformation का उपयोग करके लोन / लेट के लिए फिर से प्रस्तुत करते हैं।

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)

इस जवाब से मेटागेटा परियोजना के कुछ कोड , osr.CoordinateTransformation विचार


बहुत अच्छे धन्यवाद। और यह इस बात की परवाह किए बिना काम करता है कि क्या गाल्डिनफो आउटपुट में उपयुक्त लाइनें मौजूद हैं।
ईडीबीबीबी

मुझे लगता है कि यह tgt_srs = src_srs.CloneGeogCS () के साथ बेहतर होगा। मेरी प्रारंभिक आपदाएं मंगल ग्रह की छवियां हैं, इसलिए EPSG (4326) का उपयोग करना आदर्श नहीं है, लेकिन CloneGeogCS () केवल अनुमानित निर्देशांक से भौगोलिक परिवर्तन के लिए प्रकट होता है।
एड्डीबीबी

पक्का। मैंने CloneGeogCS का उपयोग करने के लिए उत्तर अपडेट किया है। हालाँकि, मैं सिर्फ गेटएक्स्टेंट और रिप्रोजेक्ट कार्ड्स कार्यों के उपयोग को प्रदर्शित करने की कोशिश कर रहा था। आप लक्ष्य srs के रूप में आप चाहते हैं कुछ भी उपयोग कर सकते हैं।
user2856

हां, धन्यवाद, मैंने उन लोगों को कभी नहीं पाया।
एडी। 2

यदि आपके पास कोई डेटासेट है जिसका कोई प्रक्षेपण नहीं है और RPC निर्दिष्ट करता है? Wkt फ़ंक्शन से आयात विफल हो जाता है। ट्रांसफार्मर का उपयोग करके सीमा की गणना करना संभव है लेकिन मैं सोच रहा था कि क्या ऊपर की विधि के साथ एक तरीका था?
थॉमस

41

यह कोड की बहुत कम लाइनों में किया जा सकता है

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, ulyऊपरी बाएँ कोने में है,lrx , lryनिचले दाएं कोने है

ऑस् लाइब्रेरी (गदल का हिस्सा) का उपयोग किसी भी समन्वय प्रणाली में अंक को बदलने के लिए किया जा सकता है। एक बिंदु के लिए:

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)

एक पूरी रेखापुंज छवि को पुन: पेश करने के लिए एक अधिक जटिल मामला होगा, लेकिन GDAL> = 2.0 इसके लिए एक आसान समाधान भी प्रदान करता है gdal.Warp:।


यह सीमा के लिए पायथनिक उत्तर है - पुनरावृत्ति के लिए एक समान-पायथन समाधान भयानक होगा, जिसमें कहा गया था - मैं पोस्टजीआईएस में परिणामों का उपयोग करता हूं, इसलिए मैं सिर्फ अन-ट्रांसफ़ॉर्म सीमा और ST_Transform(ST_SetSRID(ST_MakeBox2D([परिणाम] पास करता हूं ),28355),4283)। (एक वक्रोक्ति - 'टी' को src.GetGeoTransform()पूंजीकृत किया जाना चाहिए)।
जी.टी.

@GT। एक उदाहरण जोड़ा
जेम्स

1

मैंने इस तरह से किया है ... यह थोड़ा हार्ड-कोडेड है लेकिन अगर गालडिनोफ के साथ कुछ भी नहीं बदलता है, तो यह UTM प्रोजेक्ट छवियों के लिए काम करेगा!

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
यह काफी नाजुक है क्योंकि यह दोनों gdalinfoउपयोगकर्ताओं के पथ पर उपलब्ध होने पर निर्भर करता है (हमेशा मामला नहीं, विशेष रूप से खिड़कियों पर) और एक मुद्रित आउटपुट को पार्स करता है जिसका कोई सख्त इंटरफ़ेस नहीं है - यानी सही रिक्ति के लिए उन 'मैजिक नंबरों' पर निर्भर है। यह अनावश्यक है जब गाल्ड व्यापक अजगर बाइंडिंग प्रदान करता है जो इसे अधिक स्पष्ट और मजबूत तरीके से कर सकता है
जेम्स

1

यदि आपके रेखापुंज को घुमाया जाता है, तो गणित थोड़ा और अधिक जटिल हो जाता है, जैसा कि आपको छह आइन परिवर्तन परिवर्तनों में से प्रत्येक पर विचार करने की आवश्यकता है। एक चक्करदार चक्कर रूपांतरण / जियोट्रांसफॉर्म बदलने के लिए एफाइन का उपयोग करने पर विचार करें :

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|

अब आप चार कोनों के समन्वित जोड़े उत्पन्न कर सकते हैं:

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

और अगर आपको ग्रिड-आधारित सीमा (xmin, ymin, xmax, ymax) की आवश्यकता है:

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

0

मेरा मानना ​​है कि अजगर के लिए OSGEO / GDAL मॉड्यूल के हाल के संस्करणों में सिस्टम कॉल को शामिल किए बिना सीधे कोड से GDAL उपयोगिताओं को कॉल किया जा सकता है। उदाहरण के लिए कॉल करने के लिए उपप्रकार का उपयोग करने के बजाय:

gdalinfo एक को gdal.Info (the_name_of_the_file) फ़ाइल मेटाडेटा / एनोटेशन के संपर्क में लाने के लिए कह सकता है

या कॉल करने के लिए उपप्रकार का उपयोग करने के बजाय: gdalwarp एक gald.Warp को एक रेखापुंज पर वार करने के लिए शांत कर सकता है।

GDAL उपयोगिताओं की सूची वर्तमान में एक आंतरिक कार्य के रूप में उपलब्ध है: http://erouault.blogspot.com/2015/10/gdal-and-ogr-utilities-as-library.html

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.