Veja este link para mais detalhes.
O problema:
Quero fazer um loop através de uma varredura contínua (que não possui tabela de atributos), célula por célula, e obter o valor da célula. Eu quero pegar esses valores e executar condicionais neles, emulando as etapas de álgebra do mapa detalhadas abaixo sem usar a calculadora raster.
Por solicitação dos comentários abaixo, adicionei detalhes fornecendo informações básicas sobre o problema e justificando a necessidade de implementar um método como tal na seção abaixo chamada "A análise necessária:".
A análise proposta abaixo, apesar de ser relevante para o meu problema, fornecendo informações básicas, não precisa ser implementada em uma resposta. O escopo da pergunta refere-se apenas à iteração através de uma varredura contínua para obter / definir os valores da célula.
A análise necessária:
Se QUALQUER uma das seguintes condições for atendida, forneça um valor de 1 a célula de saída. Somente forneça um valor de 0 a célula de saída se nenhuma das condições for atendida.
Condição 1: se o valor da célula for maior que as células superior e inferior, forneça o valor 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Onde o arquivo do kernel se parece com isso:
3 3
0 1 0
0 0 0
0 1 0
Condição 2: se o valor da célula for maior que as células esquerda e direita, forneça o valor 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Onde o arquivo do kernel se parece com isso:
3 3
0 0 0
1 0 1
0 0 0
Condição 3: se o valor da célula for maior que o topleft e as células inferiores, forneça o valor 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Onde o arquivo do kernel se parece com isso:
3 3
1 0 0
0 0 0
0 0 1
Condição 4: se o valor da célula for maior que as células inferior esquerda e superior direita, forneça o valor 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Onde o arquivo do kernel se parece com isso:
3 3
0 0 1
0 0 0
1 0 0
Condição 5: se qualquer uma das células adjacentes tiver um valor igual à célula central, atribua à varredura de saída o valor 1 ( usando variedade focal com os dois cálculos de vizinhança mais próximos )
Por que não usar álgebra de mapa?
Foi observado abaixo que meu problema poderia ser resolvido usando álgebra de mapa, mas, como visto acima, esse é um total geral de seis cálculos de varredura, mais um para combinar todos os rasters criados juntos. Parece-me que é muito mais eficiente ir célula por célula e fazer todas as comparações de uma só vez em cada célula, em vez de repetir cada uma individualmente sete vezes e utilizar bastante memória para criar sete rasters.
Como o problema deve ser atacado?
O link acima aconselha o uso da interface IPixelBlock, mas na documentação da ESRI não está claro se você está realmente acessando um valor de célula única através do IPixelBlock ou se está acessando vários valores de célula do tamanho do IPixelBlock definido. Uma boa resposta deve sugerir um método para acessar os valores das células de uma varredura contínua e fornecer uma explicação da metodologia por trás do código, se não aparentemente óbvio.
Em suma:
Qual é o melhor método para percorrer todas as células em uma varredura CONTÍNUA (que não possui tabela de atributos ) para acessar seus valores de célula?
Uma boa resposta não precisa implementar as etapas de análise descritas acima, mas apenas fornecer uma metodologia para acessar os valores das células de uma varredura.
Respostas:
Vejo que isso já foi resolvido pelo Original Poster (OP), mas publicarei uma solução simples em python, caso alguém no futuro esteja interessado em diferentes maneiras de resolver esse problema. Sou parcial em relação ao software de código aberto, então aqui está uma solução usando GDAL em python:
Implemente a função assim:
Em seguida, repita seus dados com um loop aninhado:
Ou talvez você queira nivelar sua matriz 2-D com uma compreensão da lista:
De qualquer forma, ao iterar os dados célula a célula, é possível lançar alguns condicionais em seu loop para alterar / editar valores. Veja este script que escrevi para diferentes maneiras de acessar os dados: https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py .
fonte
Atualizar! A solução numpy:
Portanto, retornar a matriz finalizada à varredura usando o arcpy é problemático. arcpy.NumPyArrayToRaster é um esquilo e tende a redefinir extensões, mesmo que você as alimente com as coordenadas LL.
Eu prefiro salvar como texto.
Estou executando o Python como velocidade de 64 bits - no momento, isso significa que não posso alimentar o cabeçalho numpy.savetxt. Então eu tenho que abrir a saída e adicionar o cabeçalho ASCII que o Arc deseja antes de converter o ASCII para o Raster
A versão numpy executa minhas varreduras de varredura, multiplicações e acréscimos muito mais rapidamente (1000 iterações em 2 minutos) do que a versão arcpy (1000 iterações em 15 min)
VERSÃO ANTIGA Posso excluir isso mais tarde, acabei de escrever um script semelhante. Tentei converter para pontos e usando o cursor de pesquisa. Eu tenho apenas 5000 iterações em 12 horas. Então, eu procurei por outro caminho.
Minha maneira de fazer isso é iterar pelas coordenadas do centro da célula de cada célula. Começo no canto superior esquerdo e movo da direita para a esquerda. No final da linha, desço uma linha e começo de novo à esquerda. Eu tenho uma varredura de 240 m com 2603 colunas e 2438 linhas, para um total de 6111844 células totais. Eu uso uma variável iteradora e um loop while. Ver abaixo
Algumas notas: 1 - você precisa conhecer as coordenadas da extensão
2 - corra com coordenadas de ponto para o centro da célula - mova 1/2 do tamanho da célula dos valores de extensão
3 - Meu script está usando o valor da célula para extrair uma varredura específica de valor e, em seguida, mude essa varredura para o centro da célula original. Isso adiciona uma varredura zero para expandir a extensão antes de adicionar a uma varredura final. Este é apenas um exemplo. Você pode colocar suas instruções condicionais aqui (segunda instrução if dentro do loop while).
4 - Este script assume que todos os valores de varredura podem ser convertidos como números inteiros. Isso significa que você precisa se livrar primeiro dos dados. Con IsNull.
6 - Ainda não estou feliz com isso e estou trabalhando para tirar isso completamente do arcpy. Eu preferiria criar matrizes numpy e fazer as contas por lá e depois trazê-las de volta ao Arc.
fonte
Tente usar IGridTable, ICursor, IRow. Esse trecho de código é para atualizar os valores das células de varredura, no entanto, mostra o básico da iteração:
Como posso adicionar um novo campo em uma tabela de atributos raster e percorrê-lo?
Depois de percorrer a tabela, você pode obter o valor da linha do campo específico usando
row.get_Value(yourfieldIndex)
. Se você Googlevocê deve conseguir muitos exemplos mostrando isso.
Espero que ajude.
fonte
Que tal isso como uma idéia radical, exigiria que você programa em python ou ArcObjects.
fonte
Uma solução:
Eu resolvi isso hoje cedo. O código é uma adaptação desse método . O conceito por trás disso não foi terrivelmente difícil depois que eu descobri o que os objetos usados para interagir com a varredura realmente fazem. O método abaixo utiliza dois conjuntos de dados de entrada (inRasterDS e outRasterDS). Ambos são o mesmo conjunto de dados, eu apenas fiz uma cópia do inRasterDS e a passei para o método como outRasterDS. Dessa forma, ambos têm a mesma extensão, referência espacial, etc. O método lê os valores do inRasterDS, célula por célula, e faz comparações vizinhas mais próximas. Ele usa os resultados dessas comparações como valores armazenados no outRasterDS.
O processo:
Usei o IRasterCursor -> IPixelBlock -> SafeArray para obter os valores de pixel e o IRasterEdit para escrever novos no raster. Ao criar o IPixelBlock, você está informando à máquina o tamanho e o local da área na qual deseja ler / gravar. Se você deseja editar apenas a metade inferior de uma varredura, defina-a como seus parâmetros IPixelBlock. Se você deseja fazer um loop sobre toda a varredura, defina IPixelBlock igual ao tamanho de toda a varredura. Eu faço isso no método abaixo, passando o tamanho para IRasterCursor (pSize) e obtendo o PixelBlock a partir do cursor raster.
A outra chave é que você precisa usar o SafeArray para fazer interface com os valores desse método. Você obtém o IPixelBlock do IRasterCursor e o SafeArray do IPixelBlock. Então você lê e escreve no SafeArray. Quando você terminar de ler / gravar no SafeArray, grave todo o SafeArray de volta no IPixelBlock, depois grave o IPixelBlock no IRasterCursor e, finalmente, use o IRasterCursor para definir o local para iniciar a gravação e o IRasterEdit faça a gravação. Esta etapa final é onde você realmente edita os valores do conjunto de dados.
fonte
Os dados de varredura do AFAIK podem ser lidos de três maneiras:
Sem reinventar a roda, sugiro ler esses slides esclarecedores de Chris Garrard.
Portanto, o método mais eficiente é ler dados por bloco, no entanto, isso causaria uma perda de dados na correspondência de pixels localizados sobre os limites do bloco durante a aplicação do filtro. Portanto, uma maneira alternativa segura deve consistir na leitura de toda a imagem de uma só vez e na abordagem numpy.
No lado computacional, eu deveria usar o gdalfilter.py e implicitamente a abordagem VRT KernelFilteredSource para aplicar os filtros necessários e, acima de tudo, evitar cálculos pesados.
fonte