Vea este enlace para más detalles.
El problema:
Quiero recorrer un ráster continuo (uno que no tiene tabla de atributos), celda por celda, y obtener el valor de la celda. Quiero tomar esos valores y ejecutar condicionales sobre ellos, emulando los pasos de álgebra de mapas detallados a continuación sin usar la calculadora ráster.
Por solicitud de comentarios a continuación, he agregado detalles que brindan antecedentes sobre el problema y justifican la necesidad de implementar un método como tal en la sección a continuación llamada "El análisis necesario:".
El análisis propuesto a continuación, aunque es relevante para mi problema al proporcionar antecedentes, no necesita implementarse en una respuesta. El alcance de la pregunta solo se refiere a iterar a través de un ráster continuo para obtener / establecer los valores de las celdas.
El análisis necesitaba:
Si se cumple CUALQUIERA de las siguientes condiciones, asigne a la celda de salida un valor de 1. Solo asigne a la celda de salida un valor de 0 si ninguna de las condiciones se cumple.
Condición 1: si el valor de la celda es mayor que las celdas superior e inferior, proporcione el valor de 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Donde el archivo kernel se ve así:
3 3
0 1 0
0 0 0
0 1 0
Condición 2: si el valor de la celda es mayor que las celdas izquierda y derecha, proporcione el valor de 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Donde el archivo kernel se ve así:
3 3
0 0 0
1 0 1
0 0 0
Condición 3: si el valor de la celda es mayor que las celdas superior e inferior derecha, dé el valor de 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Donde el archivo kernel se ve así:
3 3
1 0 0
0 0 0
0 0 1
Condición 4: si el valor de la celda es mayor que las celdas de abajo a la izquierda y hacia arriba, dé el valor de 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Donde el archivo kernel se ve así:
3 3
0 0 1
0 0 0
1 0 0
Condición 5: si cualquiera de las celdas adyacentes tiene un valor IGUAL a la celda central, asigne al ráster de salida un valor de 1 ( utilizando variedad focal con dos cálculos de vecindad más cercanos )
¿Por qué no usar álgebra de mapas?
A continuación se ha señalado que mi problema podría resolverse utilizando el álgebra de mapas, pero como se ve arriba, se trata de un total de seis cálculos ráster, más uno para combinar todos los rásteres creados juntos. Me parece que es mucho más eficiente ir celda por celda y hacer todas las comparaciones a la vez en cada celda en lugar de recorrer cada una individualmente siete veces y utilizar un poco de memoria para crear siete rásteres.
¿Cómo se debe atacar el problema?
El enlace anterior aconseja utilizar la interfaz IPixelBlock, sin embargo, de la documentación de ESRI no está claro si realmente está accediendo a un solo valor de celda a través de IPixelBlock, o si está accediendo a múltiples valores de celda desde el tamaño del IPixelBlock que configuró. Una buena respuesta debería sugerir un método para acceder a los valores de celda de un ráster continuo y proporcionar una explicación de la metodología detrás del código, si no es aparentemente obvio.
En resumen:
¿Cuál es el mejor método para recorrer cada celda en un ráster CONTINUO (que no tiene una tabla de atributos ) para acceder a sus valores de celda?
Una buena respuesta no necesita implementar los pasos de análisis descritos anteriormente, solo necesita proporcionar una metodología para acceder a los valores de celda de un ráster.
Respuestas:
Veo que esto ya ha sido resuelto por el Cartel original (OP), pero publicaré una solución simple en python en caso de que alguien en el futuro esté interesado en diferentes formas de resolver este problema. Soy partidario del software de código abierto, así que aquí hay una solución que usa GDAL en python:
Implemente la función de esta manera:
Luego, repita sus datos con un bucle anidado:
O tal vez desee aplanar su matriz 2-D con una comprensión de la lista:
De todos modos, mientras se itera a través de los datos celda por celda, es posible lanzar algunos condicionales en su ciclo para cambiar / editar valores. Consulte este script que escribí para conocer las diferentes formas de acceder a los datos: https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py .
fuente
¡Actualizar! La solución numpy:
Por lo tanto, hacer que la matriz terminada vuelva a la trama usando arcpy es problemático. arcpy.NumPyArrayToRaster es ardilla y tiende a redefinir extensiones incluso si lo alimenta a sus coordenadas LL.
Prefiero guardar como texto.
Estoy ejecutando Python como velocidad de 64 bits; en este momento, esto significa que no puedo alimentar numpy.savetxt un encabezado. Entonces tengo que abrir la salida y agregar el encabezado ASCII que Arc quiere antes de convertir ASCII a Ráster
La versión numpy ejecuta mi ráster de turno, multiplicaciones y sumas mucho más rápido (1000 iteraciones en 2 minutos) que la versión arcpy (1000 iteraciones en 15 min)
VERSIÓN ANTERIOR Puedo eliminar esto más tarde, acabo de escribir un script similar. Intenté convertir a puntos y usar el cursor de búsqueda. Obtuve solo 5000 iteraciones en 12 horas. Entonces, busqué otra forma.
Mi forma de hacer esto es iterar a través de las coordenadas del centro celular de cada celda. Comienzo en la esquina superior izquierda y me muevo de derecha a izquierda. Al final de la fila, me muevo hacia abajo y empiezo de nuevo a la izquierda. Tengo un ráster de 240 m con 2603 columnas y 2438 filas, por lo que un total de 6111844 celdas totales. Yo uso una variable iteradora y un bucle while. Vea abajo
Algunas notas: 1 - necesita saber las coordenadas de la extensión
2: ejecutar con coordenadas de punto para el centro de la celda: mover 1/2 del tamaño de la celda desde los valores de extensión
3 - Mi script está usando el valor de celda para extraer un ráster específico de valor, luego desplazar este ráster para centrarlo en la celda original. Esto se agrega a un ráster cero para expandir la extensión antes de agregarlo a un ráster final. Esto es solo un ejemplo. Puede poner sus declaraciones condicionales aquí (segunda declaración if dentro del ciclo while).
4: este script supone que todos los valores ráster se pueden convertir como enteros. Esto significa que primero debe deshacerse de la ausencia de datos. Con IsNull.
6 - Todavía no estoy contento con esto y estoy trabajando para sacarlo de Arcpy por completo. Prefiero lanzar como matrices numpy y hacer los cálculos allí y luego llevarlo de vuelta a Arc.
fuente
Intente usar IGridTable, ICursor, IRow. Este fragmento de código es para actualizar valores de celdas ráster, sin embargo, muestra los conceptos básicos de iteración:
¿Cómo puedo agregar un nuevo campo en una tabla de atributos ráster y recorrerlo?
Una vez que esté atravesando la tabla, puede obtener el valor de fila de campo específico mediante el uso
row.get_Value(yourfieldIndex)
. Si usted googledeberías poder obtener muchos ejemplos que lo demuestren.
Espero que ayude.
fuente
¿Qué tal esto como una idea radical? Te requeriría programar en Python o ArcObjects.
fuente
Una solución:
Resolví esto más temprano hoy. El código es una adaptación de este método . El concepto detrás de esto no fue terriblemente difícil una vez que descubrí lo que realmente hacen los objetos para interactuar con la trama. El siguiente método toma dos conjuntos de datos de entrada (inRasterDS y outRasterDS). Ambos son el mismo conjunto de datos, acabo de hacer una copia de inRasterDS y la pasé al método como outRasterDS. De esta manera, ambos tienen la misma extensión, referencia espacial, etc. El método lee los valores de inRasterDS, celda por celda, y hace las comparaciones de vecinos más cercanos en ellos. Utiliza los resultados de esas comparaciones como valores almacenados en outRasterDS.
El proceso:
Utilicé IRasterCursor -> IPixelBlock -> SafeArray para obtener los valores de píxel e IRasterEdit para escribir nuevos en el ráster. Cuando crea IPixelBlock, le indica a la máquina el tamaño y la ubicación del área en la que desea leer / escribir. Si solo desea editar la mitad inferior de un ráster, configúrelo como sus parámetros IPixelBlock. Si desea recorrer todo el ráster, debe configurar IPixelBlock igual al tamaño de todo el ráster. Hago esto en el siguiente método pasando el tamaño a IRasterCursor (pSize) y luego obteniendo el PixelBlock del cursor ráster.
La otra clave es que debe usar SafeArray para interactuar con los valores de este método. Obtiene IPixelBlock de IRasterCursor, luego SafeArray de IPixelBlock. Luego lees y escribes en SafeArray. Cuando termine de leer / escribir en SafeArray, escriba todo su SafeArray de nuevo en IPixelBlock, luego escriba su IPixelBlock en IRasterCursor, y finalmente use IRasterCursor para establecer la ubicación para comenzar a escribir e IRasterEdit para hacer la escritura. Este último paso es donde realmente edita los valores del conjunto de datos.
fuente
Los datos ráster AFAIK se pueden leer de tres maneras:
Sin reinventar la rueda, sugiero leer estas diapositivas esclarecedoras de Chris Garrard.
Entonces, el método más eficiente es leer los datos por bloque, sin embargo, esto causaría una pérdida de datos en la correspondencia de píxeles ubicados sobre los límites del bloque al aplicar el filtro. Por lo tanto, una forma alternativa segura debería consistir en leer la imagen completa de una vez y usar el enfoque numpy.
En el lado computacional, en cambio, debería usar gdalfilter.py e implícitamente el enfoque VRT KernelFilteredSource para aplicar los filtros necesarios y, sobre todo, evitar cálculos pesados.
fuente