2. Modelos Digitales de Elevaciones Sistemas de Información Geográfica (SIG) aplicados a la gestión de recursos hídricos TAyGA Curso 2009 10 Índice 1 Introducción 1 2 Generación de MDE y capas derivadas 1 3 Análisis de los diferentes MDE 2 3.1 Inspección visual............................................... 2 3.2 Análisis estadístico.............................................. 2 3.3 Consistencia hidrológica........................................... 2 3.4 Comparación por pares de los modelos.................................... 4 3.5 Filtrado del MDE proporcionado por LIDAR para eliminar ruido...................... 5 3.6 Eliminación de sombreados mediante integración de MDE-LIDAR y MDE-splines............ 6 1 Introducción En esta práctica se va a comparar un MDE obtenido con tecnología LIDAR con los obtenidos a partir de curvas de nivel (interpolación lineal y de splines). Para ello lo primero, tras cargar el fichero de funciones, es utilizar una región de trabajo ya almacenada y que coincide aproximadamente con la Rambla de Valdelentisco para visualizar el MDE obtenido con LIDAR: source("/usr/local/etc/saga_grass.r") g.region("valdelentisco") d.mon("x0") d.rast("mde_lidar") 2 Generación de MDE y capas derivadas Aunque los resultados de este paso ya están en PERMANENT, puesto que sería lento hacerlo en clase, vamos a asumir que tenemos que generar un MDE con un modelo lineal a partir de curvas de nivel. Para ello es necesario rasterizar las curvas de nivel v.to.rast, puesto que el módulo que se va a utilizar para interpolar (r.surf.contour) sólo maneja números enteros, se hace necesario multiplicar por cien las curvas de nivel rasterizadas para permitir obtener un MDE con decimales y que las pendientes que se obtengan en zonas llanas sean razonables. v.to.rast(" --o BCN25curvas use=attr column=color output=curvas") r.mapcalc("curvas_cm=if(curvas==0,1,100*curvas)") r.surf.contour(" --o curvas_cm output=temp") r.mapcalc("mde_lineal=temp/100.0") En segundo lugar obtenemos capas de pendiente y orientación con r.slope.aspect, este módulo puede además generar capas de otras variables como curvaturas, etc. que se verán con más detalle en la siguiente práctica. r.slope.aspect(" --o elev=mde_lineal slope=slo_lineal aspect=asp_lineal") lo que nos permite visualizar el relieve con un sombreado: d.his("i_map=asp_lineal h_map=mde_lineal") 1
A continuación se interpola mediante splines otro MDE de la misma zona utilizando 40 como parámetro de tensión y sin suavizado: ATENCION: Esta orden tardaría bastante tiempo en ejecutarse, por lo que ya tienes las capas creadas en el mapset PERMANENT. v.surf.rst(" --o input=bcn25curvas elev=mde_splines slope=slo_splines aspect=asp_splines zcolumn=color tension=40") Como puedes ver, el mismo módulo que realiza la interpolación por splines se encarga de calcular pendientes y orientaciones, sólo queda calcular pendientes y orientaciones para el MDE del LIDAR y ya tenemos las tres capas básicas para cada uno de los modelos: r.slope.aspect(" --o elev=mde_lidar slope=slo_lidar aspect=asp_lidar") 3 Análisis de los diferentes MDE 3.1 Inspección visual Para comparar adecuadamente los modelos de elevaciones conviene que las paletas sean las mismas: r.colors("mde_lidar color=elevation") r.colors("mde_lineal rast=mde_lidar") r.colors("mde_splines rast=mde_lidar") Si hacemos para MDE_lidar y MDE_splines la misma combinación de color que hemos hecho antes podremos tener una primera evaluación cualitativa de los diferentes modelos: d.mon("x1") d.his("i_map=asp_splines h_map=mde_splines") d.mon("x2") d.his("i_map=asp_lidar h_map=mde_lidar") Un análisis visual de las capas derivadas puede ofrecer información acerca de como se reproducen las formas de relieve en los diferentes MDE. Ejercicio: 1. Visualiza elevaciones, pendientes y orientaciones y saca conclusiones acerca de los diferentes modelos. (a) Cuál te parece más preciso? A qué crees que se debe? (b) Qué tipos de artefactos pueden apreciarse a partir de las diferentes capas de información? 3.2 Análisis estadístico Puesto que no disponemos de valores reales con los que comparar los resultados, vamos a visualizar los histogramas de los MDE en búsqueda de anomalías. : mde=readrast6(c("mde_lidar","mde_lineal","mde_splines")) par(mfrow=c(3,1)) hist(mde$mde_lidar,breaks=1000) hist(mde$mde_splines,breaks=1000) hist(mde$mde_lineal,breaks=1000) par(mfrow=c(1,1)) summary(mde) 2
Ejercicio: 2. Son los comportamientos estadísticos de los tres modelos semejantes? 3. Cómo pueden comparse la variables considerando la componente espacial? 4. Hay algún otro mapa, estadístico o representación de datos que pudiese ayudar? 5. A qué conclusiones sobre los diferentes modelos podemos llegar? 3.3 Consistencia hidrológica Independientemente de la exactitud absoluta en la codificación de la elevación, para las aplicaciones hidrológicas es más importante que las relaciones de flujo entre las diferentes partes del terreno queden bien reflejadas en el MDE, es decir la escorrentía superficial debe dirigirse en el el modelo en las mismas direcciones que se dirigiría en la realidad. Para evaluar esta consistencia hidrológica vamos a aplicar el algoritmo D8 que dirige el flujo hacia aquella de las 8 celdillas vecinas que se sitúa en una cota inferior y con mayor pendiente. EL módulo r.watershed de GRASS aplica este algoritmo pudiendo generar diversas capas de información hidrológica. En este momento la que más nos va a interesar es la de drenaje acumulado en la que se asigna a cada celdilla el número de celdillas situadas aguas arriba: r.watershed(" --o MDE_lidar accum=mde_lidar_acc") r.watershed(" --o MDE_splines accum=mde_splines_acc") r.watershed(" --o MDE_lineal accum=mde_lineal_acc") Estas capas no son muy adecuadas para su visualización con una paleta de colores lineal y suele visualizarse su logaritmo: r.mapcalc("mde_lidar_lacc=log(abs(mde_lidar_acc))") r.mapcalc("mde_splines_lacc=log(abs(mde_splines_acc))") r.mapcalc("mde_lineal_lacc=log(abs(mde_lineal_acc))") Para evitar tener que repetir varias veces un conjunto de órdenes de visualización vamos a crear una función: d.mostrar=function(monitor,raster){ d.mon(monitor) d.erase() d.rast(raster) d.legend(paste(raster,"at=40,90,1,5")) } A continuación basta con escribir: d.mostrar("x1","mde_lidar_lacc") d.mostrar("x2","mde_lineal_lacc") d.mostrar("x3","mde_splines_lacc") Al visualizar el logaritmo del drenaje acumulado tenemos una primera estimación e la ubicación de la red de drenaje, esta será lógicamente, diferente para diferentes modelos. En zonas con pendiente alta (barrancos, arroyos) no habrá demasiada diferencia entre los diferentes métodos y con la realidad, pero en zonas bajas las diferencias pueden ser importantes. Visualizar esta capa junto a las curvas de nivel permite detectar donde pueden estar los problemas. A partir del drenaje acumulado podemos obtener estimaciones de la red de drenaje estableciendo un valor umbral. Vamos a generar una red de drenaje para cada uno de los modelos y comparar los resultados: r.mapcalc("red_lidar=if(abs(mde_lidar_acc)>500,1,null())") r.mapcalc("red_splines=if(abs(mde_splines_acc)>500,1,null())") r.mapcalc("red_lineal=if(abs(mde_lineal_acc)>500,1,null())") A continuación visualiza las diferentes redes de drenaje: d.mon("select=x0"); d.rast("red_lidar") d.mon("select=x1"); d.rast("red_lineal") d.mon("select=x2"); d.rast("red_splines") 3
Ejercicio: 6. Visualiza las diferentes redes de drenaje y anota tus impresiones. Utiliza la función d.zoom() para ver mejor zonas concretas. Si has hecho zoom en el monitor x0 por ejemplo, para utilizar el mismo zoom en los otros utiliza las órdenes: d.mon("select=x1");d.redraw() Dónde se producen las principales diferencias? Qué conclusiones acerca de la consistencia hidrológica de los diferentes modelos podemos extraer? Para volver a la región original ejecuta g.region("valdelentisco") d.mon("select=x0");d.redraw() d.mon("select=x1");d.redraw() d.mon("select=x2");d.redraw() 3.4 Comparación por pares de los modelos Hasta ahora todas las pruebas realizadas parecen indicar que el MDE extraído del LIDAR es el mejor posible, vamos a hacer una comprobación más generando capas con la diferencia entre pares de modelos y representándolas con la ayuda de las curvas de nivel para poder extraer conclusiones: 1. En primer lugar calculamos capas con las diferencias: r.mapcalc("dif_lidar_lineal=mde_lidar-mde_lineal") r.mapcalc("dif_lidar_splines=mde_lidar-mde_splines") r.mapcalc("dif_lineal_splines=mde_lineal-mde_splines") 2. Les asignamos a todas la misma paleta. Los valores 0 se visualizarán en blanco, los valores positivos en azul y los negativos en rojo: pon_paleta("dif_lidar_lineal",val=c(-50,0,30),red=c(255,255,0), blue=c(0,255,255),green=c(0,255,0)) pon_paleta("dif_lidar_splines",val=c(-50,0,30),red=c(255,255,0), blue=c(0,255,255),green=c(0,255,0)) pon_paleta("dif_lineal_splines",val=c(-50,0,30),red=c(255,255,0), blue=c(0,255,255),green=c(0,255,0)) 3. Visualizamos los mapas: d.mostrar("x1","dif_lidar_lineal") d.mostrar("x2","dif_lidar_splines") d.mostrar("x3","dif_lineal_splines") 4. Los cargamos en R: dif.mde = readrast6(c("dif_lidar_lineal", "dif_lidar_splines","dif_lineal_splines")) 5. Finalmente los visualizamos y obtenemos un resumen: summary(dif.mde) par(mfrow=c(3,1)) hist(dif.mde$dif_lidar_lineal,breaks=200) hist(dif.mde$dif_lidar_splines,breaks=200) hist(dif.mde$dif_lineal_splines,breaks=200) 4
Como era de esperar las diferencias entre los dos MDE extraídos de curvas de nivel son menores que las diferencias respecto al MDE del lidar. Llama la atención como los mapas de la diferencia entre el MDE LIDAR y los extraídos de curvas de nivel presentan una distribución de diferencias no aleatoria de manera que se distribuyen los valores positivos a un lado y los negativos al otro de algunas elevaciones. Se trata del conocido problema del efecto de sombra que presenta cualquier dispositivo de teledetección. Si consultas los valores que alcanzan estas diferencias verás que son importantes: d.what.rast("dif_lidar_lineal") Puesto que la equidistancia en las curvas de nivel es de 10 m, cabe esperar que los errores absolutos de un MDE obtenido a partir de estas no sea superior a los 10 m y en raras ocasiones superior a los 5 metros. Esto significa que si aparecen diferencias superiores a 10 metros se trata de errores atribuibles al LIDAR y específicamente al efecto del sombreado. En definitiva nos encontramos con el siguiente dilema: El MDE derivado de curvas de nivel es más exacto que el del LIDAR en zonas de relieve debido al efecto de sombreado de este El MDE LIDAR parece tener menos artefactos que los extraídos de curvas de nivel especialmente en zonas llanas El MDE LIDAR es más preciso en la reconstrucción de las formas El MDE LIDAR es más consistente desde un punto de vista hidrológico La solución podría ser intentar fusionar los dos MDE para obtener uno que tuviera las ventajas de ambos. 3.5 Filtrado del MDE proporcionado por LIDAR para eliminar ruido Para ello empezaremos por detectar en el MDE LIDAR celdillas sospechosas de contener ruido aleatorio, para ello haremos una estimación del valor en las celdillas a partir de un filtrado con las celdillas de alrededor aplicando la siguiente matriz de filtrado: -6-15 -25-15 -6-15 50 260 50-15 -25 260 0 260-25 -15 50 260 50-15 -6-15 -25-15 -6 este filtro está preprogramado en una función de SAGA_GRASS por lo que basta con escribir: filtro_lidar("mde_lidar","mde_lidar_est") posteriormente utilizaremos la ecuación: t = z ẑ z sd (1) para obtener un estadístico que, en caso de que las diferencias sean las esperables al azar, es decir no sean erróneas, y se distribuiría como una distribución t de Student con 23 grados de libertad (los 24 valores utilizados para la estimación menos 1). Para el cálculo de t necesitamos primero calcular la desviación típica en un entorno de la celdilla central. En este caso utilizaremos un entorno de 5x5. r.neighbors("--o MDE_lidar output=mde_lidar_sd method=stddev size=5") r.mapcalc("mde_lidar_t=abs((mde_lidar-mde_lidar_est)/mde_lidar_sd)") Si obtenemos valores altamente improbables en alguna celdilla podemos considerar que se trata de una celdilla errónea. Puesto que en la región de trabajo que se está utilizando hay 2324052 celdillas, debemos considerar un valor de probabilidad muy bajo, del orden de 1/2324052: p = 1/2324052 u1 = qt(1-p,df=23) Otra forma de determinar el valor crítico es es cálculo empírico. Podemos asumir, por ejemplo, que el 1 % más elevado de los valores son celdillas erróneas: 5
mde.lt = readrast6("mde_lidar_t") p=0.01 u2 = quantile(abs(mde.lt$mde_lidar_t),1-p,na.rm=t) Obviamente los valores obtenidos por los dos métodos no coincidirán, la elección debe hacerse mediante el criterio de exigencia: cuanto mayor sea el valor crítico considerado, menos celdillas serán consideradas erróneas. Haremos a continuación una nueva capa para ver que celdillas superan el umbral ( u=u1 o u=u2?): orden=paste("mde_lidar_tu=if(mde_lidar_t>",u2,",1,null())",sep="") r.mapcalc(orden) d.rast("mde_lidar_tu") Ejercicio: 9. En que tipo de topografía aparecen los valores anómalos? 10. A que crees que puede deberse y finalmente se crea un mapa filtrado en el que estos valores extremos se sustituyen por la estimación realizada a partir de los valores situados en el entorno: r.mapcalc("mde_lidar_f=if(isnull(mde_lidar_tu),mde_lidar,mde_lidar_est)") d.rast("mde_lidar_f") 3.6 Eliminación de sombreados mediante integración de MDE-LIDAR y MDE-splines Un simple análisis visual de la capa dif_lidar_plines pone en evidencia que los sombreados empiezan a aparecer cuando la pendiente es mayor de 5 grados una solución rápida podría ser utilizar MDE LIDAR cuando la pendiente fuese inferior y splines cuando sea superior. Aparte de la posibilidad de tener efectos de frontera entre ambas zonas, hay que recordar que MDE LIDAR representa mejor las formas y tiene mayor consistencia hidrológica a todas las pendientes, por tanto lo que se va a hacer es aproximar el valor de elevación al de MDE_splines pero preservando las diferencias entre celdillas vecinas que aparecen en MDE_lidar. Para ello se comienza con un filtrado de media de las diferencias entre ambos MDE con tamaño de ventana de 11 metros: r.mapcalc( dif_lidar_splines=mde_lidar_f-mde_lineal ) r.neighbors("--o input=dif_lidar_lineal output=filtro method=average size=11") generando a continuación una capa con las diferencias entre el MDE_lidar y esta capa suavizada, de este modo se le resta a cada celdilla del MDE_lidar su diferencia respecto al valor medio de MDE_lineal, consiguiéndose ajustar ambas capas pero preservando las relaciones entre celdillas contiguas de MDE_lidar r.mapcalc("mde_lidar_f1=mde_lidar_f-filtro") Finalmente utilizamos este nuevo modelo sólo en los casos en que la pendiente sea mayor que 10 grados ya que el efecto de sombreado aparece sólo en las zonas de pendiente elevada: r.mapcalc("mde_lidar_ff=if(slo_lidar<10,mde_lidar_f,mde_lidar_f1)") Conclusión Un simple análisis visual muestra como se ha mejorado la exactitud en la elevación (la diferencia entre el MDE_lidar doblemente filtrado y el MDE de splines es mucho menor y los errores aparecen distribuidos al azar) preservando al consistencia hidrológica a costa de introducir pequeños artefactos, visibles en los mapas de orientación y pendientes. 6