Python GDAL: Escreva uma nova varredura usando a projeção de antigos

8

Se eu ler uma imagem rasterizada como uma matriz, faça algumas alterações nos valores da matriz, como salvar a matriz como uma varredura com as mesmas informações de projeção que a matriz original?

Em particular, estou conduzindo o processamento em alguns cubos ISIS3 de Marte. Elas não são projetadas em nenhuma das boas opções do SetWellKnownGeogCS. Talvez isso torne meu problema um tanto incomum, mas achei que vale a pena documentar minha solução da mesma forma.

EddyTheB
fonte

Respostas:

16

Essa é a rotina que desenvolvi para converter cubos ISIS3 em GTiffs. Espero que uma abordagem semelhante funcione entre todos os tipos de drivers (embora eu ache que o método driver.Create () possa limitar a escolha do arquivo de saída).

import numpy as np
import gdal
from gdalconst import *
from osgeo import osr

# Function to read the original file's projection:
def GetGeoInfo(FileName):
    SourceDS = gdal.Open(FileName, GA_ReadOnly)
    NDV = SourceDS.GetRasterBand(1).GetNoDataValue()
    xsize = SourceDS.RasterXSize
    ysize = SourceDS.RasterYSize
    GeoT = SourceDS.GetGeoTransform()
    Projection = osr.SpatialReference()
    Projection.ImportFromWkt(SourceDS.GetProjectionRef())
    DataType = SourceDS.GetRasterBand(1).DataType
    DataType = gdal.GetDataTypeName(DataType)
    return NDV, xsize, ysize, GeoT, Projection, DataType

# Function to write a new file.
def CreateGeoTiff(Name, Array, driver, NDV, 
                  xsize, ysize, GeoT, Projection, DataType):
    if DataType == 'Float32':
        DataType = gdal.GDT_Float32
    NewFileName = Name+'.tif'
    # Set nans to the original No Data Value
    Array[np.isnan(Array)] = NDV
    # Set up the dataset
    DataSet = driver.Create( NewFileName, xsize, ysize, 1, DataType )
            # the '1' is for band 1.
    DataSet.SetGeoTransform(GeoT)
    DataSet.SetProjection( Projection.ExportToWkt() )
    # Write the array
    DataSet.GetRasterBand(1).WriteArray( Array )
    DataSet.GetRasterBand(1).SetNoDataValue(NDV)
    return NewFileName

# Open the original file
FileName = 'I29955002trim.cub'    # This is the ISIS3 cube file
                                  # It's an infra-red photograph
                                  # taken by the 2001 Mars Odyssey orbiter.
DataSet = gdal.Open(FileName, GA_ReadOnly)
# Get the first (and only) band.
Band = DataSet.GetRasterBand(1)
# Open as an array.
Array = Band.ReadAsArray()
# Get the No Data Value
NDV = Band.GetNoDataValue()
# Convert No Data Points to nans
Array[Array == NDV] = np.nan

# Now I do some processing on Array, it's pretty complex 
# but for this example I'll just add 20 to each pixel.
NewArray = Array + 20  # If only it were that easy

# Now I'm ready to save the new file, in the meantime I have 
# closed the original, so I reopen it to get the projection
# information...
NDV, xsize, ysize, GeoT, Projection, DataType = GetGeoInfo(FileName)

# Set up the GTiff driver
driver = gdal.GetDriverByName('GTiff')

# Now turn the array into a GTiff.
NewFileName = CreateGeoTiff('I29955002trim', NewArray, driver, NDV, 
                            xsize, ysize, GeoT, Projection, DataType)

E é isso. Eu posso abrir as duas imagens no QGIS. E o gdalinfo nos dois arquivos mostra que tenho as mesmas informações de projeção e georreferenciamento.

EddyTheB
fonte
1
Parece que o PyGDAL foi além do uso de strings para coisas como tipo de dados e o uso de None para No Data Values. Precisava ajustar algumas coisas aqui.
Ahmed Fasih