Збереження просторової довідки за допомогою 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, але як їх встановити на основі вхідного растру? Я не можу це зрозуміти.


Отримавши відповідь Луки, це моє попереднє рішення.

Обидва рішення Луки правильно встановили просторову орієнтир, міру та розмір комірок. Але перший метод неправильно переніс дані в масиві, і виведення растрових файлів скрізь заповнено. Його другий метод працює здебільшого, але там, де у мене є велика область нодатів, він заповнюється блокадними нулями та 255-ю. Це, можливо, пов'язане з тим, як я обробляв клітини нодатів, і я не зовсім впевнений, як я це робив (мав би бути ще один Q). Я включив зображення того, про що я говорю.

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

Зображення, що показують результати. У обох випадках клітинки нодату показані жовтим кольором.

Другий метод Луки Другий метод Луки

Мій попередній метод Мій попередній метод

Відповіді:


15

Ознайомтеся з методом опису .

Щось подібне повинно працювати.

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

EDIT: Метод 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)

Лука, дякую за відповідь. Мені здається, що мені потрібно зробити щось гібридне з ваших двох методів? Обидва способи встановлюють розмір, спрэд і т.д. правильні, але не вдається масивувати дані правильно ... Перший метод робить усі клітинки ноданими. Другий метод працює краще, але вони, здається, не обробляють клітини нодату в myArray правильно (вибачте, що я не сказав, що в моїй клітині є деякі нодатні дані, і я хочу зберегти цілі). Деякі спроби та помилки змусили мене думати, що я повинен використовувати другий підхід, але arcpy.env.outCoordinateSystem робить висновок виглядає розумним. не так багато розуміння, як це все-таки.
yosukesabai

1
Ви не запитували про NoData, ви запитували про просторові орієнтири та розмір комірок. Метод arcpy.NumPyArrayToRaster приймає параметр value_to_nodata.
користувач2856

Лука, дякую за редагування. Я спробував ваш метод надання 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.