¿Crear ráster eligiendo aleatoriamente el valor de celda de múltiples rásteres superpuestos?


10

Estoy usando ArcGIS Desktop 10 con su extensión Spatial Analyst.

¿Cómo combino múltiples rásteres en uno, siempre eligiendo aleatoriamente los valores de las celdas superpuestas?

Tengo una imagen que puede explicar esto mejor:

ejemplo

Respuestas:


7

Pick fue creado para problemas como este. Piense en ello como la versión "switch" (o "case") de "con", que es la implementación de álgebra de mapas de "if ... else".

Si hay 3 rásteres superpuestos, por ejemplo, la sintaxis (Python) se vería así

inPositionRaster = 1 + int(3 * CreateRandomRaster())
Pick(inPositionRaster, [inRas01, inRas02, inRas03])

Tenga en cuenta que pickcomienza a indexar en 1, no en 0.


Editar

(ver el hilo de comentarios)

Para hacer frente a los valores de NoData, primero debe desactivar el manejo de NoData de ArcGIS. Haga esto creando cuadrículas que tengan un valor especial (pero válido) en lugar de NoData, como 99999 (o lo que sea: pero asegúrese de elegir un valor que sea mayor que cualquier número válido que pueda aparecer: esto será útil más adelante) . Esto requiere el uso de la solicitud IsNull, como en

p01 = Con(IsNull(inRas01), 99999, inRas01)
p02 = Con(IsNull(inRas02), 99999, inRas01)
p03 = Con(IsNull(inRas03), 99999, inRas01)

Por ejemplo, considere el caso de estas cuadrículas de una fila (NoData se muestra como "*"):

inRas01:  1  2 19  4  *  *  *  *
inRas02:  9  2  *  * 13 14  *  *
inRas03: 17  *  3  * 21  * 23  *

El resultado es poner un 99999 en lugar de cada "*".

A continuación, imagine todos estos rásteres como matrices planas de bloques de madera con NoData correspondiente a bloques faltantes (agujeros). Cuando apilas verticalmente estos rásteres, los bloques caerán en cualquier agujero debajo de ellos. Necesitamos ese comportamiento para evitar elegir valores NoData: no queremos espacios verticales en las pilas de bloques. El orden de los bloques en cada torre realmente no importa. Para este fin, podemos obtener cada torre clasificando los datos :

q01 = Rank(1, [p01, p02, p03])
q02 = Rank(2, [p01, p02, p03])
q03 = Rank(3, [p01, p02, p03])

En el ejemplo, obtenemos

q01:      1     2     3     4    13    14    23 99999
q02:      9     2    19 99999    21 99999 99999 99999
q03:     17 99999 99999 99999 99999 99999 99999 99999

Tenga en cuenta que los rangos son de menor a mayor, de modo que q01 contiene los valores más bajos en cada ubicación, q02 contiene el segundo más bajo, etc. Los códigos NoData no comienzan a aparecer hasta que se recopilan todos los números válidos, porque esos códigos son más grandes que cualquier número válido.

Para evitar elegir estos códigos NoData durante la selección aleatoria, debe saber cuántos bloques se apilan en cada ubicación: esto nos dice cuántos valores válidos ocurren. Una forma de manejar esto es contar el número de códigos NoData y restarlo del número total de cuadrículas de selección:

n0 = 3 - EqualToFrequency(99999, [q01, q02, q03])

Esto produce

n0:       3 2 2 1 2 1 1 0

Para manejar los casos donde n = 0 (por lo que no hay nada disponible para seleccionar), configúrelos en NoData:

n = SetNull(n0 == 0, n0)

Ahora

n:        3 2 2 1 2 1 1 *

Esto también garantizará que sus códigos NoData (temporales) desaparezcan en el cálculo final. Genere valores aleatorios entre 1 yn:

inPositionRaster = 1 + int(n * CreateRandomRaster())

Por ejemplo, este ráster podría verse así

inPositionRaster: 3 2 1 1 2 1 1 *

Todos sus valores se encuentran entre 1 y el valor correspondiente en [n].

Seleccione valores exactamente como antes:

selection = Pick(inPositionRaster, [q01, q02, q03])

Esto resultaría en

selection:       17  2  3  4 21 14 23  *

Para verificar que todo esté bien, intente seleccionar todas las celdas de salida que tengan el código NoData (99999 en este ejemplo): no debería haber ninguna.

Aunque este ejemplo en ejecución usa solo tres cuadrículas para seleccionar, lo he escrito de una manera que se generaliza fácilmente a cualquier número de cuadrículas. Con muchas cuadrículas, escribir un script (para recorrer las operaciones repetidas) será invaluable.


¿Sabes cómo podría ignorar los valores NoData de los cálculos (con Raster Calculator y Python)?
Sam

Sam, "Ignorar" ¿cómo, precisamente? Creo que el comportamiento predeterminado es generar NoData siempre que uno o más rásteres de entrada sean NoData (pero no estoy completamente seguro de eso en el caso de pick: si inPositionRaster y el ráster seleccionado tienen valores válidos en una celda, entonces el resultado es plausiblemente para esa celda debe ser el valor del ráster seleccionado, independientemente de lo que pueda contener cualquiera de los otros rásteres). ¿En qué comportamiento alternativo estás pensando?
whuber

Necesito que solo seleccione entre los valores de números enteros. Digamos que tengo tres rásteres. Para una celda, sus valores son los siguientes: 4,5, NoData. Quiero que el exterior tenga un 4 o 5 en esa celda, pero nunca el NoData.
Sam

Tengo problemas para que este 1 + Int (n * CreateRandomRaster ()) funcione.
Sam

"Problemas" en qué sentido? ¡Por favor sea especifico!
whuber

4

Usando python y ArcGIS 10 y usando la función con que tiene la siguiente sintaxis:

Con (in_conditional_raster, in_true_raster_or_constant, {in_false_raster_or_constant}, {where_clause})

La idea aquí es ver si el valor en el ráster aleatorio es menor que 0.5, si es elegir raster1, de lo contrario, elija raster2. NoData+ datos = NoDataasí que primero establezca estos reclasifique cualquier valor con NoData0:

import arcpy
from arcpy import env
from arcpy.sa import *
env.workspace = "C:/sapyexamples/data"

ras1_NoNull = Con(IsNull("elevation1"),0, "elevation1")  # remove NoData
ras2_NoNull = Con(IsNull("elevation2"),0, "elevation2")  # remove NoData
randRaster = CreateRandomRaster(100, 2, Extent(0, 0, 150, 150)) # raster generated between 0 and 1; 100 is seed value

outCon = Con(randRaster < 0.5, ras1_NoNull,  ras2_NoNull)  

outCon.save("C:/outcon.img")   # save raster

EDITAR: Acabo de darme cuenta de que no estás agregando los NoDatavalores para que esa pieza se pueda omitir.


Todavía estoy trabajando en mis habilidades de Python. ¿Hay alguna forma de ingresar esto en la Calculadora ráster que también excluiría los valores NoData del proceso? Tengo 10 rásteres y algunos tienen NoData donde otros tienen valores.
Sam

Creo que puedes crear condiciones usando algo como esto en la calculadora rásterCon(IsNull(ras1), 0, ras2)
djq

Desafortunadamente, esto no excluye los valores NoData: simplemente los reemplaza con ceros. En algunos casos eso podría ser apropiado, ¡pero probablemente no aquí!
whuber

hmm, buen punto @whuber. Entonces, ¿qué significa excluir NoData? ¿Es solo para asegurarse de que no se elijan al elegir al azar?
DJ

Así es como lo he interpretado (vea mi respuesta editada en este hilo), pero sigue siendo una buena pregunta. Ignorar los valores ND de esta manera hace que las cuadrículas restantes se seleccionen con mayor probabilidad, lo que podría ser un efecto secundario indeseable. Todo depende del propósito del cálculo.
whuber

1

Simplemente crearía un ráster aleatorio ( ayuda ) de la misma extensión y tamaño de celda. Luego, usando CON ( ayuda ) configúrelo para elegir el valor del primer ráster si la celda del ráster aleatorio tiene un valor <128 (si un ráster aleatorio sería 0-255), de lo contrario, elija un valor del segundo ráster.

Espero que tenga sentido :)


¿Sabes cómo seleccionar solo de los rásteres con valores? Por ejemplo, en mi figura hay cuatro 2 y dos 3 que se superponen con NoData. Quiero asegurarme de que solo seleccione de esos rásteres con valores en una celda y no de NoData.
Sam

Perdón por no responder ¿Todavía estás luchando con el problema NoData?
jareks
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.