পাইথন জিডিএল বাইন্ডিংগুলি ব্যবহার করে রাস্টার কর্নার সমন্বয়গুলি কীভাবে পাবেন?


30

জিডালের পাইথন বাইন্ডিং ব্যবহার করে কোনও রাস্টার ফাইল থেকে কর্নার স্থানাঙ্কগুলি (ডিগ্রি ল্যাট / লম্বায়) পাওয়ার কোনও উপায় আছে কি?

অনলাইনে কয়েকটি অনুসন্ধান আমাকে নিশ্চিত করেছে যে সেখানে নেই, তাই আমি জিডালিনফো আউটপুটকে বিশ্লেষণ করে একটি কাজ গড়ে তুলেছি, এটি কিছুটা মৌলিক তবে আমি ভেবেছিলাম যে এটি অজগর নিয়ে কম আরামদায়ক লোকদের জন্য কিছুটা সময় সাশ্রয় করতে পারে। এটি কেবল তখনই কাজ করে যদি জিডালিনফোতে কোণার স্থানাঙ্কের সাথে ভৌগলিক স্থানাঙ্ক থাকে, যা আমি বিশ্বাস করি না যে সবসময় এটি হয়।

এখানে আমার কর্মসংস্থান, কারও কি আরও ভাল সমাধান আছে?

একটি উপযুক্ত রাস্টার উপর 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]

সম্পর্কিত হতে পারে: gis.stackexchange.com/questions/33330/…
AndreJ

উত্তর:


29

একটি বাহ্যিক প্রোগ্রাম না কল করে এটি করার এখানে আরও একটি উপায়'s

এটি যা করে তা হ'ল জিওট্রান্সফর্ম থেকে চারটি কোণার স্থানাঙ্কগুলি পেতে এবং ওএসআরকর্ডিন্ট ট্রান্সফর্মেশন ব্যবহার করে দীর্ঘ / ল্যাটে পুনরায় প্রজেক্ট করা।

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.CordordTransformation ধারণা


অান্তরিক ধন্যবাদ. Gdalinfo আউটপুটে উপযুক্ত লাইন বিদ্যমান কিনা তা নির্বিশেষে এটি কাজ করে।
এডি থিবি

আমি মনে করি tgt_srs = src_srs.CloneGeogCS () এর মাধ্যমে এটি আরও ভাল হবে। আমার প্রাথমিক রাস্টাররা মঙ্গল গ্রহের চিত্র, সুতরাং ইপিএসজি (4326) ব্যবহার করা আদর্শ নয়, তবে ক্লোনজিওগসিএস () কেবলমাত্র ভৌগলিক স্থানাঙ্কের পরিবর্তিত বলে মনে হচ্ছে।
এডি থিবি

অবশ্যই। আমি ক্লোনজিগসিএস ব্যবহারের উত্তর আপডেট করেছি। যাইহোক, আমি কেবল getExant এবং ReprojectCoords ফাংশনগুলির ব্যবহারটি প্রদর্শন করার চেষ্টা করছিলাম। আপনি টার্গেট এসআরএস হিসাবে আপনার যে কোনও কিছু ব্যবহার করতে পারেন।
ব্যবহারকারী2856

হ্যাঁ, আপনাকে ধন্যবাদ, আমি এগুলি অন্যথায় কখনও পাইনি।
এডি থিবি

আপনার যদি এমন কোনও ডেটাসেট থাকে যার কোনও প্রক্ষেপণ না থাকে এবং আরপিসি নির্দিষ্ট করে দেয়? 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নীচের ডান কোণে হয়

Osr গ্রন্থাগার (gdal এর অংশ) কোনও স্থানাঙ্ক ব্যবস্থায় পয়েন্টগুলি রূপান্তর করতে ব্যবহার করা যেতে পারে। একক দফার জন্য:

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)

একটি সম্পূর্ণ রাস্টার ইমেজ reproject জন্য দূর আরো জটিল ব্যাপার হতে পারে, কিন্তু GDAL> = 2.0 অফার একটি সহজ এই জন্য খুব সমাধান: gdal.Warp


এই পরিমাণ জন্য Pythonic উত্তর - reprojection জন্য সমান-Pythonic সমাধান সন্ত্রস্ত হয়ে যেত, তাই বলা হয় - আমি PostGIS ফলাফল ব্যবহার, তাই আমি ঠিক আন-রুপান্তরিত মাত্রা এবং পাস ST_Transform(ST_SetSRID(ST_MakeBox2D([ফলাফল] ),28355),4283)করুন। (একটি কোয়েবল - 'টি' ইন src.GetGeoTransform()মূলধন করা উচিত)
জিটি

@GT। একটি উদাহরণ যুক্ত করা হয়েছে
জেমস

1

আমি এইভাবে করেছি ... এটি সামান্য হার্ড কোডেড তবে জিডালিনফোর সাথে যদি কিছু পরিবর্তন না হয় তবে এটি ইউটিএম প্রজেক্টযুক্ত চিত্রগুলির জন্য কাজ করবে!

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ব্যবহারকারীর পথে (সর্বদা ক্ষেত্রে হয় না, বিশেষত উইন্ডোজগুলিতে) উভয়ই নির্ভর করে এবং একটি প্রিন্টড আউটপুট পার্স করে যার কোনও কঠোর ইন্টারফেস নেই - যেমন সঠিক ব্যবধানের জন্য সেই 'যাদু সংখ্যার' উপর নির্ভর করে। এটি যখন অপ্রয়োজনীয় তখন যখন gdal ব্যাপক পাইথন বাইন্ডিং সরবরাহ করে যা আরও স্পষ্ট এবং দৃ manner়ভাবে এটি করতে পারে
জেমস

1

যদি আপনার রাস্টারটি ঘোরানো হয়, তবে গণিতটি আরও জটিল হয়ে উঠবে, কারণ আপনাকে ছয়টি অ্যাফাইন ট্রান্সফর্মেশন সহগের প্রতিটি বিবেচনা করতে হবে। ব্যবহার করার কথা বিবেচনা অ্যাফিন একটি আবর্তিত অ্যাফিন রূপান্তর / geotransform রুপান্তর:

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

এবং আপনার যদি গ্রিড-ভিত্তিক সীমানা (এক্সমিন, ইয়ামিন, এক্সম্যাক্স, ইয়াম্যাক্স) প্রয়োজন হয়:

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

0

আমি পাইথনের জন্য ওএসজিইও / জিডিএল মডিউলের আরও সাম্প্রতিক সংস্করণগুলিতে বিশ্বাস করি যে সিস্টেম কলগুলিতে জড়িত না হয়ে যে কেউ সরাসরি কোড থেকে জিডিএল ইউটিলিটিগুলি কল করতে পারে। উদাহরণস্বরূপ কল করতে সাবপ্রসেস ব্যবহার করার পরিবর্তে:

gdalinfo কেও gdal কল করতে পারেন met ফাইলটি মেটাডেটা / টীকা প্রকাশের জন্য ইনফো (the_name_of_the_file)

বা পরিবর্তে কল করতে সাবপ্রসেস ব্যবহার করার পরিবর্তে: জিডালওয়ার্প একটি জিড্ডার উপর ওয়ার্পিং করতে gdal.Warp করতে পারেন।

অভ্যন্তরীণ ফাংশন হিসাবে বর্তমানে উপলব্ধ জিডিএল ইউটিলিটিগুলির তালিকা: http://erouault.blogspot.com/2015/10/gdal-and-ogr-utilities-as-library.html

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.