Сохранение пространственной привязки с использованием arcpy.RasterToNumPyArray?

13

Я использую ArcGIS 10.1 и хочу создать новый растр на основе двух ранее существующих растров. RasterToNumPyArray имеет хороший пример , который я хочу , чтобы адаптироваться.

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")

Проблема в том, что он лишает пространственной привязки, а также размера ячейки. Я подумал, что это должно делать arcpy.env, но как мне установить их на основе входного растра? Я не могу разобраться.


Принимая ответ Люка, это мое предварительное решение.

Оба решения Люка правильно установили пространственную привязку, экстент и размер ячейки. Но первый метод не правильно переносил данные в массив, и выходной растр всюду заполняется ноданными. Его второй метод работает в основном, но там, где у меня большая область nodata, он заполняется блочными нулями и 255. Это может иметь отношение к тому, как я обрабатывал ячейки нодаты, и я не совсем уверен, как я это делал (хотя должен быть еще один вопрос). Я включил изображения того, о чем я говорю.

#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) 

Изображение показывает результаты. В обоих случаях ноданные клетки показаны желтым цветом.

Второй метод Люка Второй метод Люка

Мой предварительный метод Мой предварительный метод

yosukesabai
источник

Ответы:

15

Проверьте метод Describe .

Что-то вроде следующего должно работать.

#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)

ИЛИ

#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)

РЕДАКТИРОВАТЬ: метод arcpy.NumPyArrayToRaster принимает параметр value_to_nodata. Используйте это так:

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)
user2856
источник
Люк, спасибо за ответ. Мне кажется, что мне нужно сделать что-то гибридное из ваших двух методов? Оба метода устанавливают корректность экстента, spref и т. Д., Но не могут правильно распределить данные ... Первый метод делает все ячейки ноданными. Второй метод работает лучше, но, похоже, они неправильно обрабатывают ячейки нодаты в myArray (извините, я не сказал, что в моей ячейке есть нодаты, и я хочу сохранить их нетронутыми). Некоторые пробы и ошибки заставили меня подумать, что я должен выбрать второй подход, но arcpy.env.outCoordinateSystem делает вывод выглядит разумным. не так много понимания того, как это так.
yosukesabai
1
Вы не спрашивали о NoData, вы спрашивали о пространственной привязке и размере ячейки. Метод arcpy.NumPyArrayToRaster принимает параметр value_to_nodata.
user2856
Люк, спасибо за редактирование. Я попробовал ваш метод предоставления 5-го аргумента (value_to_nodata), но я все же вывел цифру сверху (ячейка nodata заполнена 0 или 255, а nodata_value не задано для выходного растра). Единственный обходной путь, который я нашел, состоял в том, чтобы установить env.outputCoordinateSystem перед NumPyArrayToRaster вместо использования DefineProjection_management впоследствии. Не имеет смысла, почему это работает, но я просто иду с моим решением. спасибо за помощь
yosukesabai
1

У меня были некоторые проблемы с получением ArcGIS для правильной обработки значений NoData с примерами, показанными здесь. Я расширил пример из блога reomtesensing.io (который более или менее похож на решения, показанные здесь), чтобы лучше обрабатывать NoData.

Очевидно, ArcGIS (10.1) нравится значение -3.40282347e + 38 как NoData. Так что я конвертирую туда и обратно между NumPy NaN и -3.40282347e + 38. Код здесь:

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)
Mathiaskopo
источник