Python GDAL: Schreiben Sie ein neues Raster mit der Projektion von einem alten

8

Wenn ich ein Rasterbild als Array einlese und dann einige Änderungen an den Werten im Array vornehme, wie speichere ich das Array dann als Raster mit denselben Projektionsinformationen wie das ursprüngliche Array?

Insbesondere bearbeite ich einige ISIS3-Würfel vom Mars. Diese werden in keiner der netten SetWellKnownGeogCS-Optionen projiziert. Vielleicht macht dies mein Problem etwas ungewöhnlich, aber ich fand es trotzdem wert, meine Lösung zu dokumentieren.

EddyTheB
quelle

Antworten:

16

Dies ist die Routine, die ich entwickelt habe, um ISIS3-Cubes in GTiffs zu konvertieren. Ich gehe davon aus, dass ein ähnlicher Ansatz zwischen allen Treibertypen funktionieren sollte (obwohl ich denke, dass die driver.Create () -Methode die Auswahl der Ausgabedatei einschränken könnte).

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)

Und das ist es. Ich kann beide Bilder in QGIS öffnen. Und gdalinfo in beiden Dateien zeigt, dass ich die gleichen Projektionsinformationen und Georeferenzierungen habe.

EddyTheB
quelle
1
Es sieht so aus, als ob PyGDAL nicht mehr nur Zeichenfolgen für Datentypen und keine für Werte ohne Daten verwendet. Musste hier einige Dinge optimieren.
Ahmed Fasih