Existe uma maneira de obter as coordenadas dos cantos (em graus lat / long) de um arquivo rasterizado usando as ligações Python do gdal?
Algumas pesquisas on-line me convenceram de que não há, então desenvolvi uma solução alternativa analisando a saída do gdalinfo, é um pouco básico, mas achei que poderia economizar algum tempo para as pessoas que poderiam se sentir menos à vontade com o python. Também funciona apenas se o gdalinfo contiver as coordenadas geográficas juntamente com as coordenadas dos cantos, o que não acredito que seja sempre o caso.
Aqui está minha solução alternativa: alguém tem alguma solução melhor?
O gdalinfo em uma varredura apropriada resulta em algo assim no meio da saída:
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)
Esse código funcionará em arquivos com aparência semelhante à do gdalinfo. Acredito que algumas vezes as coordenadas serão em graus e decimais, em vez de graus, minutos e segundos; deve ser trivial ajustar o código para essa situação.
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
E isso me dá:
[-4.33429444 -5.82895833 -4.33429444 -5.82895833 -5.081625 ]
[ 137.12275833 137.12203333 137.74633889 137.74706111 137.43454722]
Respostas:
Aqui está outra maneira de fazer isso sem chamar um programa externo.
O que isso faz é obter as coordenadas dos quatro cantos da geotransformação e reprojetá-las para lon / lat usando osr.CoordinateTransformation.
Algum código do metageta projeto, ideia osr.CoordinateTransformation de esta resposta
fonte
Isso pode ser feito em muito menos linhas de código
ulx
,uly
É o canto superior esquerdo,lrx
,lry
é o canto inferior direitoA biblioteca osr (parte do gdal) pode ser usada para transformar os pontos em qualquer sistema de coordenadas. Para um único ponto:
Reprojetar uma imagem raster inteiro seria uma questão muito mais complicada, mas GDAL> = 2.0 oferece uma solução fácil para isso também:
gdal.Warp
.fonte
ST_Transform(ST_SetSRID(ST_MakeBox2D(
[os resultados]),28355),4283)
. (Uma queixa - o 'T' insrc.GetGeoTransform()
deve ser maiúsculo).Eu fiz dessa maneira ... é um pouco codificado, mas se nada mudar com o gdalinfo, ele funcionará para imagens projetadas em UTM!
fonte
gdalinfo
estar disponível no caminho do usuário (nem sempre, especialmente no Windows) e de analisar uma saída impressa que não possui interface rígida - ou seja, confiar nesses 'números mágicos' para o espaçamento correto. É desnecessário quando gdal fornece vínculos python abrangentes que pode fazer isso de uma forma mais explícita e robustoSe sua varredura é rotacionada, a matemática fica um pouco mais complicada, pois você precisa considerar cada um dos seis coeficientes de transformação afins. Considere usar affine para transformar uma transformação / geotransformação afim girada:
Agora você pode gerar os quatro pares de coordenadas de canto:
E se você também precisar dos limites baseados na grade (xmin, ymin, xmax, ymax):
fonte
Acredito que em versões mais recentes do módulo OSGEO / GDAL para python, é possível chamar diretamente os utilitários GDAL a partir do código sem envolver chamadas do sistema. por exemplo, em vez de usar o subprocesso para chamar:
gdalinfo pode-se chamar gdal.Info (nome_do_arquivo) para ter uma exposição dos metadados / anotações do arquivo
ou em vez de usar o subprocesso para chamar: gdalwarp, pode-se chamar gdal.Warp para fazer a distorção em uma varredura.
A lista de utilitários GDAL atualmente disponíveis como uma função interna: http://erouault.blogspot.com/2015/10/gdal-and-ogr-utilities-as-library.html
fonte