Obtendo imagem rasterizada como array em Python com ArcGIS Desktop?

10

Ao começar a trabalhar com Python e ArcGIS 9.3, presumi que haveria uma maneira simples de obter uma imagem rasterizada em uma matriz Python, para que eu possa manipulá-la antes de armazená-la novamente como outra imagem rasterizada. No entanto, não consigo descobrir como fazer isso.

Se é possível, então, como?

robintw
fonte

Respostas:

6

Eu não acho que isso seja possível com o ArcGIS <= 9.3.1

Eu uso a API GDAL de código aberto para tarefas como esta.

fmark
fonte
Ótimo! Eu usei os programas utilitários GDAL no passado, mas nunca pensei em usá-los para fazer isso.
22610 robertw
3
Eu concordo, o módulo gdal Python permite que você leia facilmente uma varredura e despeje os dados em uma matriz Numpy. Chris Garrard tem um curso sobre o uso de OpenSource Python no GIS, abordando este assunto. Você pode encontrá-lo em: gis.usu.edu/~chrisg/python/2008
DavidF
6

O fmark já respondeu à pergunta, mas aqui está um exemplo de código OSGEO Python que escrevi para ler uma varredura (tif) em uma matriz NumPy, reclassificar os dados e gravá-los em um novo arquivo tif. Você pode ler e escrever qualquer formato suportado pelo gdal.

"""
Example of raster reclassification using OpenSource Geo Python

"""
import numpy, sys
from osgeo import gdal
from osgeo.gdalconst import *


# register all of the GDAL drivers
gdal.AllRegister()

# open the image
inDs = gdal.Open("c:/workshop/examples/raster_reclass/data/cropland_40.tif")
if inDs is None:
  print 'Could not open image file'
  sys.exit(1)

# read in the crop data and get info about it
band1 = inDs.GetRasterBand(1)
rows = inDs.RasterYSize
cols = inDs.RasterXSize

cropData = band1.ReadAsArray(0,0,cols,rows)

listAg = [1,5,6,22,23,24,41,42,28,37]
listNotAg = [111,195,141,181,121,122,190,62]

# create the output image
driver = inDs.GetDriver()
#print driver
outDs = driver.Create("c:/workshop/examples/raster_reclass/output/reclass_40.tif", cols, rows, 1, GDT_Int32)
if outDs is None:
  print 'Could not create reclass_40.tif'
  sys.exit(1)

outBand = outDs.GetRasterBand(1)
outData = numpy.zeros((rows,cols), numpy.int16)


for i in range(0, rows):
  for j in range(0, cols):

    if cropData[i,j] in listAg:
        outData[i,j] = 100
    elif cropData[i,j] in listNotAg:
        outData[i,j] = -100
    else:
        outData[i,j] = 0


# write the data
outBand.WriteArray(outData, 0, 0)

# flush data to disk, set the NoData value and calculate stats
outBand.FlushCache()
outBand.SetNoDataValue(-99)

# georeference the image and set the projection
outDs.SetGeoTransform(inDs.GetGeoTransform())
outDs.SetProjection(inDs.GetProjection())

del outData
DavidF
fonte
1

Você pode salvar sua varredura como uma grade ascii ESRI e ler / manipular esse arquivo com numpy.

Isso fornece alguns pontos de partida: http://sites.google.com/site/davidpfinlayson2/esriasciigridformat

Mas cuidado - parece que o formato da grade ASCII nem sempre segue as especificações, portanto, lê-las corretamente sempre pode ser um desafio.

snorris
fonte
1

Não sei se você pode manipular o pixel raster por pixel, mas pode usar os objetos de geoprocessamento em conjunto com a API python.

Você pode usar qualquer caixa de ferramentas para esse tipo de manipulação. Um script de amostra seria:

#import arcgisscripting

gp = arcgisscripting.create(9.3)

gp.AddToolbox("SA") # addint spatial analyst toolbox

rasterA = @"C:\rasterA.tif"
rasterB = @"C:\rasterB.tif"

rasterC = @"C:\rasterC.tif" # this raster does not yet exist
rasterD = @"C:\rasterD.tif" # this raster does not yet exist

gp.Minus_SA(rasterA,rasterB,rasterC)

gp.Times_SA(rasterA,rasterB,rasterD)

# lets try to use more complex functions

# lets build and expression first

expression1 = "slope( " + rasterC + ")"
expression2 = "(" + rasterC " + " rasterD + ") - " + rasterA 

gp.SingleOutputMapAlgebra_SA(expression1,@"C:\result_exp1.tif")
gp.SingleOutputMapAlgebra_SA(expression2,@"C:\result_exp2.tif")

Aqui está um acompanhamento da sua pergunta . Ainda não é possível. Não tenho certeza na versão 10.0.

George Silva
fonte
Obrigado - isso é muito útil. No entanto, idealmente, eu gostaria de poder percorrer a matriz raster fazendo várias coisas. Eu teria pensado que haveria uma maneira no ArcGIS de fazer isso, mas talvez não!
23910 robintw
robintw, pelo que procurei na referência, não há como obter um pixel específico de uma varredura. Não tenho certeza se no ArcPy (disponível na v10) você pode buscar essas células individuais, pois elas estenderam a API python com muita nova funcionalidade.
George Silva
0

A maneira mais fácil seria converter a varredura em netCDF, abri-la e percorrer a grade. Fiz a mesma coisa em um projeto que envolve transformar rasters em dados de recursos com base nos dados atribuídos às células raster. Eu olhei para isso por séculos e cheguei à conclusão de que andar com os dados da grade seria mais fácil com o netCDF.

Peludo
fonte