Mantenere il riferimento spaziale usando arcpy.RasterToNumPyArray?


13

Sto usando ArcGIS 10.1 e desidero creare un nuovo raster basato su due raster preesistenti. Il RasterToNumPyArray ha un buon esempio che voglio adattarsi.

import arcpy
import numpy 
myArray = arcpy.RasterToNumPyArray('C:/data/inRaster')
myArraySum = myArray.sum(1)
myArraySum.shape = (myArray.shape[0],1)
myArrayPerc = (myArray * 1.0)/ myArraySum
newRaster = arcpy.NumPyArrayToRaster(myArrayPerc)
newRaster.save("C:/output/fgdb.gdb/PercentRaster")

Il problema è che rimuove il riferimento spaziale e anche la dimensione della cella. Ho pensato che dovesse fare arcpy.env, ma come posso impostarli in base all'input raster? Io non riesco a capire.


Prendendo la risposta di Luke, questa è la mia soluzione provvisoria.

Entrambe le soluzioni di Luke hanno impostato correttamente il riferimento spaziale, l'estensione e la dimensione della cellula. Ma il primo metodo non trasportava correttamente i dati nell'array e l'output raster è pieno di nodati ovunque. Il suo secondo metodo funziona principalmente, ma dove ho una grande regione di nodati, si riempie di zeri a blocchi e 255s. Questo potrebbe avere a che fare con il modo in cui ho gestito le celle di nodati e non sono sicuro di come lo stavo facendo (dovrebbe essere un altro Q però). Ho incluso le immagini di ciò di cui sto parlando.

#Setting the raster properties directly 
import arcpy 
import numpy 

inRaster0='C:/workspace/test0.tif' 
inRaster1='C:/workspace/test1.tif' 
outRaster='C:/workspace/test2.tif' 

dsc=arcpy.Describe(inRaster0) 
sr=dsc.SpatialReference 
ext=dsc.Extent 
ll=arcpy.Point(ext.XMin,ext.YMin) 

# sorry that i modify calculation from my original Q.  
# This is what I really wanted to do, taking two uint8 rasters, calculate 
# the ratio, express the results as percentage and then save it as uint8 raster.
tmp = [ np.ma.masked_greater(arcpy.RasterToNumPyArray(_), 100) for _ in inRaster0, inRaster1]
tmp = [ np.ma.masked_array(_, dtype=np.float32) for _ in tmp]
tmp = ((tmp[1] ) / tmp[0] ) * 100
tmp = np.ma.array(tmp, dtype=np.uint8)
# i actually am not sure how to properly carry the nodata back to raster...  
# but that's another Q
tmp = np.ma.filled(tmp, 255)

# without this, nodata cell may be filled with zero or 255?
arcpy.env.outCoordinateSystem = sr

newRaster = arcpy.NumPyArrayToRaster(myArrayPerc,ll,dsc.meanCellWidth,dsc.meanCellHeight) 

newRaster.save(outRaster) 

Immagine che mostra i risultati. In entrambi i casi le celle di nodati sono visualizzate in giallo.

Il secondo metodo di Luke Il secondo metodo di Luke

Il mio metodo provvisorio Il mio metodo provvisorio

Risposte:


15

Dai un'occhiata al metodo Describe .

Qualcosa di simile al seguente dovrebbe funzionare.

#Using arcpy.env
import arcpy
import numpy

inRaster='C:/workspace/test1.tif'
outRaster='C:/workspace/test2.tif'

dsc=arcpy.Describe(inRaster)
arcpy.env.extent=dsc.Extent
arcpy.env.outputCoordinateSystem=dsc.SpatialReference
arcpy.env.cellSize=dsc.meanCellWidth

myArray = arcpy.RasterToNumPyArray(r)
myArraySum = myArray.sum(1)
myArraySum.shape = (myArray.shape[0],1)
myArrayPerc = (myArray * 1.0)/ myArraySum

newRaster = arcpy.NumPyArrayToRaster(myArrayPerc)
newRaster.save(outRaster)

O

#Setting the raster properties directly
import arcpy
import numpy

inRaster='C:/workspace/test1.tif'
outRaster='C:/workspace/test2.tif'

dsc=arcpy.Describe(inRaster)
sr=dsc.SpatialReference
ext=dsc.Extent
ll=arcpy.Point(ext.XMin,ext.YMin)

myArray = arcpy.RasterToNumPyArray(inRaster)
myArraySum = myArray.sum(1)
myArraySum.shape = (myArray.shape[0],1)
myArrayPerc = (myArray * 1.0)/ myArraySum

newRaster = arcpy.NumPyArrayToRaster(myArrayPerc,ll,dsc.meanCellWidth,dsc.meanCellHeight)
arcpy.DefineProjection_management(newRaster, sr)

newRaster.save(outRaster)

EDIT: il metodo The arcpy.NumPyArrayToRaster accetta un parametro value_to_nodata. Usalo così:

try:
    noDataValue=dsc.noDataValue
    arcpy.NumPyArrayToRaster(myArrayPerc,ll,dsc.meanCellWidth,dsc.meanCellHeight,noDataValue)
except AttributeError: #no data is not defined
    arcpy.NumPyArrayToRaster(myArrayPerc,ll,dsc.meanCellWidth,dsc.meanCellHeight)

Luke, grazie per la risposta. Mi sembra che devo fare qualcosa di ibrido tra i tuoi due metodi? Entrambi i metodi impostano l'estensione, lo spref ecc. Corretti, ma non riescono a mettere correttamente in ordine i dati ... Il primo metodo rende tutte le celle nodate. Il secondo metodo funziona meglio, ma sembra che non gestiscano correttamente le celle di nodati in myArray (mi dispiace di non aver detto alla mia cella alcuni nodati e voglio mantenerli intatti). Alcuni tentativi ed errori mi hanno fatto pensare di dover adottare un secondo approccio, ma arcpy.env.outCoordinateSystem rende l'output ragionevole. non molta comprensione di come così però.
yosukesabai,

1
Non hai chiesto informazioni su NoData, hai chiesto informazioni sul riferimento spaziale e sulla dimensione delle celle. Il metodo arcpy.NumPyArrayToRaster accetta un parametro value_to_nodata.
user2856

Luke, grazie per la modifica. Ho provato il tuo metodo per fornire il 5 ° argomento (value_to_nodata), ma ho comunque prodotto la cifra in alto (cella di nodata riempita con 0 o 255 e nodata_value non è impostato per il raster di output). l'unica soluzione che ho trovato è stata impostare env.outputCoordinateSystem prima di NumPyArrayToRaster, anziché utilizzare DefineProjection_management in seguito. Non ha senso il motivo per cui funziona, ma vado solo con la mia soluzione. grazie per tutto l'aiuto.
yosukesabai,

1

Ho avuto dei problemi a far sì che ArcGIS gestisse correttamente i valori NoData con gli esempi mostrati qui. Ho esteso l'esempio dal blog reomtesensing.io (che è più o meno simile alle soluzioni mostrate qui) per gestire meglio NoData.

Apparentemente ad ArcGIS (10.1) piace il valore -3.40282347e + 38 come NoData. Quindi converto avanti e indietro tra NaN intorpidito e -3.40282347e + 38. Il codice è qui:

import arcpy
import numpy as np

infile  = r'C:\data.gdb\test_in'
outfile = r'C:\data.gdb\test_out'

# read raster with No Data as numpy NaN
in_arr  = arcpy.RasterToNumPyArray(infile,nodata_to_value = np.nan)

# processing
out_arr = in_arr * 10

# convert numpy NaN to -3.40282347e+38
out_arr[np.isnan(out_arr)] = -3.40282347e+38

# information on input raster
spatialref = arcpy.Describe(infile).spatialReference
cellsize1  = arcpy.Describe(infile).meanCellHeight
cellsize2  = arcpy.Describe(infile).meanCellWidth
extent     = arcpy.Describe(infile).Extent
pnt        = arcpy.Point(extent.XMin,extent.YMin)

# save raster
out_ras = arcpy.NumPyArrayToRaster(out_arr,pnt,cellsize1,cellsize2, -3.40282347e+38)
out_ras.save(outfile)
arcpy.DefineProjection_management(outfile, spatialref)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.