Cómo normalizar valores de un raster en R para comparar diferentes fechas

Divulgación: esta página tiene enlaces de afiliado. Si compras algo a través de ellos, puedo recibir una comisión, sin que a ti te cueste nada extra.

¿Por qué dos fotos satelitales del mismo pedazo de bosque pueden mostrarte números completamente distintos en R, aunque ahí abajo no se haya movido ni una hoja? La lluvia caía contra un vidrio ya empañado y la barra de carga de RStudio llevaba un buen rato sin avanzar, mientras yo miraba dos imágenes del mismo borde de bosque en Corral, frente a la bahía de Valdivia, una de hace un par de veranos y otra más reciente, preguntándome si estaba viendo mal o si el bosque de verdad se había vuelto otra cosa de un año para el siguiente.

La respuesta corta, antes de entrar en detalle: casi nunca es el bosque el que cambió tanto. Casi siempre es que las dos imágenes no están habladas en el mismo idioma numérico, y mientras eso no se arregle, cualquier comparación que hagas entre fechas te va a mentir. Esto es parte de las mañas que tiene la teledetección cuando se trabaja con más de una fecha: no basta con tener dos imágenes del mismo raster, hay que dejar los valores en condiciones comparables antes de restar una imagen de la otra, que es al final la base de casi todo el procesamiento de imágenes satelitales cuando se comparan fechas.

Antes de seguir: esta bitácora tiene enlaces de afiliado, y si alguna vez compras algo a través de uno de ellos me llega una comisión chica, sin que a ti te cueste un peso más. Solo menciono cursos o herramientas que de verdad he probado tratando de entender esto del raster y las fechas; si algo no lo he usado, no va a aparecer aquí, y si un enlace no es de afiliado te lo voy a aclarar en el momento.

¿Por qué el mismo bosque no da los mismos números en dos fechas distintas en R?

El sol no pega igual un enero que el enero siguiente, y la atmósfera tampoco está en las mismas condiciones de una pasada del satélite a otra. Yo trabajaba con un par de imágenes Landsat, que tienen una resolución espacial de 30 metros — para mí una maravilla, porque se distinguen hasta los parches de árboles más chicos —, y al compararlas los valores de reflectancia eran un enredo. El ángulo del sol cambia, la humedad en el aire cambia, y si no se corrige eso antes, uno termina comparando cosas que no se pueden comparar directamente, aunque el sensor haya apuntado exactamente al mismo pedazo de bosque las dos veces.

Un raster, para el que recién llega a esto, no es más que una grilla de números con un color pegado encima, y ahí está la trampa: esos números suelen venir en una profundidad de 16 bits, con miles de niveles posibles, que para un satélite tiene sentido pero para alguien que solo quiere ver si el verde está más verde o no, es un dolor de cabeza si las dos fechas no están en la misma escala. Me tomó un buen rato de ensayo y error entender que el tablero de ajedrez loco que me salía en el mapa de cambio no era el bosque moviéndose, era pura diferencia de escala entre una imagen y otra.

Histograma de valores de un raster en RStudio durante el proceso de normalización radiométrica para teledetección

No caigas en el error de normalizar cada raster por su cuenta

Antes de llegar a algo que de verdad funcionara, pasé horas viendo videos de YouTube sobre sistemas de información geográfica, pensando que ahí iba a encontrar la solución, pero casi todos usaban un programa distinto al que yo tenía instalado, así que ni los menús coincidían y terminé más perdida que al principio. Ese fue el primer callejón sin salida.

Lo que sí probé con mis propias manos fue el escalado manual, esa fórmula de restar el mínimo y dividir por el rango que encontré en un blog medio perdido. Lo único que logré fue un raster completamente negro o lleno de esos 'NaN' que ahora me persiguen hasta en sueños. También pensé que quizás algún resto de nube se me había escapado y me estaba arruinando los cálculos, así que volví a revisar lo que aprendí al quitar nubes de imágenes Landsat en RStudio, pero no era eso: el problema estaba en que yo estaba normalizando cada fecha por separado, estirando cada imagen a su propio máximo para que se viera bien sola.

Ahí está la trampa de principiante en la que caí redondita: si estiras cada fecha según su propio mínimo y máximo, borras la diferencia real que estabas buscando. Es como medir la estatura de dos personas con reglas que tienen centímetros de tamaño distinto — las dos van a terminar midiendo '100 unidades', pero jamás vas a saber quién es más alta. Le conté esto a una amiga que hace cerámica en un taller del centro, y se rió: me dijo que a ella le pasa algo parecido con los esmaltes, que el mismo tono de greda no sale igual de un horno a otro si no controla bien la temperatura cada vez. El problema de comparar 'lo mismo' bajo condiciones distintas no es solo mío, por lo visto.

¿Cómo se hace bien la normalización entre dos fechas?

La idea central, y esto es lo que de verdad cambia todo, es que el rango teórico de lo que estás midiendo tenga sentido igual en las dos fechas, no que cada imagen se vea bonita por separado. Si trabajas con un índice como el NDVI, que tiene un rango teórico fijo entre -1 y 1, ese rango debería mantenerse consistente en ambas fechas; si una imagen quedó con valores de 1500 y la otra entre 0 y 1, algo en el script se rompió antes de llegar ahí, normalmente un paréntesis mal puesto. Seguir las clases del curso Teledetección Satelital con R y R-Studio fue lo que me ayudó a ordenar justamente esta parte: cómo ajustar los valores de reflectancia usando zonas que no cambian de una fecha a otra, como caminos o rocas, en vez de estirar cada imagen por su cuenta.

Antes de aceptar cualquier normalización como buena, me hago una pregunta simple: ¿el rango se mantiene igual en las dos fechas, o cada imagen terminó con su propio máximo? Si cada una tiene su propio máximo, no sirve, por bonito que se vea el mapa. Y para que quede claro: esto no tiene nada que ver con cambiarle la resolución a un raster, que es un ajuste completamente distinto, ni con el lío de que la proyección de un mapa quede torcida, que es otro error que se nota y se arregla de otra forma.

Fórmulas de normalización de raster en R anotadas a mano para comparar fechas de imágenes satelitales

Normalizar mal es peor que no normalizar nada

Algo que de verdad me sorprendió es que normalizar mal sale peor que no tocar nada. Si fuerzas a que el valor más bajo de una imagen sea 0 y el más alto sea 1 para cada fecha por separado, estás borrando la variabilidad real del clima. Imagínate un año seco, con el bosque más café de lo normal: si normalizas esa imagen sola, R va a buscar el verde más intenso que encuentre ahí y le va a poner un 1, aunque ese verde sea pálido comparado con un año lluvioso. Al final tu comparación entre fechas queda mintiendo, porque forzaste a que los dos años se vieran igual de 'al máximo'.

Esto lo aprendí viendo mapas que decían que el bosque estaba perfecto cuando yo sabía que esa temporada la sequía había pegado fuerte por acá. Por eso conviene usar normalización radiométrica relativa entre fechas y, de paso, asegurarse de que los sensores estén bien calibrados antes de ponerse a jugar con índices. Si además de los árboles te llama la atención dónde podrían estar viviendo ciertos animales en ese mismo bosque, de reojo he mirado el curso de Modelado de Nicho Ecológico con Maxent en R, aunque todavía me da respeto meterme en ese terreno sin tener los rasters bien dominados primero.

¿Cómo sé si la normalización realmente funcionó?

La señal más simple es mirar el histograma de la imagen normalizada: si debería ir de 0 a 1 y te aparece hasta 1500, ahí quedó algo a medio hacer. La otra señal, más de ojo, es fijarte en zonas que sabes que no cambian — un camino, una roca grande, un techo — y ver si esas zonas dan valores parecidos en las dos fechas; si un camino de cemento aparece con reflectancia distinta en cada imagen, la normalización no cuajó.

Sé que algo cambió de verdad en mi manera de trabajar esto cuando empecé a poder abrir las bandas de Sentinel-2 directo en RStudio y seguir trabajando sin que el programa se cerrara solo ni tuviera que reiniciar nada a medio camino — antes eso me pasaba seguido y ahora casi nunca. Si la imagen es pesada, R todavía se puede quedar pegado antes de llegar a este punto, pero ese es un problema de memoria, aparte de la normalización, y si te faltan pedazos de imagen por nubes o error del sensor en alguna fecha, eso es un hoyo que hay que rellenar antes, no algo que la normalización arregle sola.

El alivio de ver el cambio real, no solo ruido

Cuando las dos fechas por fin quedaron en la misma escala, pude restar un raster del otro sin miedo. Y ahí estaba: no era ruido de luz, no eran nubes, era el cambio real. Se veían pedazos chicos donde el bosque nativo se notaba distinto, tal vez por estrés hídrico o por algún desprendimiento de tierra, algo bastante común por acá cuando llueve fuerte y seguido. Da gusto cuando un par de líneas de código bien puestas te limpian la vista, parecido a cuando para la lluvia en Valdivia y el aire queda tan despejado que da la sensación de poder tocar los cerros.

Mapa de cambio forestal en R tras normalizar los valores de raster entre dos fechas distintas

No vengo de la programación ni de la geografía — esto lo fui entendiendo sola, de a poco, los fines de semana, a puro ensayo y error. Si estás recién empezando, te recomiendo revisar cómo mejorar mis mapas de bosque usando teledetección satelital con R, porque uno se obsesiona tanto con los números que se olvida de la parte visual, que también ayuda a pescar errores gruesos a simple vista. Y si el suelo desnudo te está arruinando el NDVI, ahí entra cómo calcular el índice de vigor de la vegetación SAVI usando RStudio.

En R hay paquetes pensados justo para este tipo de ajuste entre fechas, aunque cuál te acomode más depende de cómo tengas armado tu flujo de trabajo, y de dónde sacaste las imágenes en primer lugar — no es lo mismo bajar una escena ya corregida que una cruda, pero eso da para otra conversación. Esto que conté aquí es apenas la base para comparar dos fechas; si más adelante quieres seguir varias fechas seguidas y ver una tendencia en el tiempo, ese es ya un paso distinto.

Aprender esto se parece bastante al clima de por acá: un rato estás en medio de la tormenta sin saber para dónde tirar, y al rato siguiente sale un sol que de repente te explica todo. Cada tarde de fin de semana que me tomó entender una sola función valió la pena con tal de ver ese mapa final cuadrando. Si quieres ahorrarte varios de los callejones sin salida que yo recorrí, dale una mirada al curso de Teledetección Satelital con R y R-Studio; a mí me cambió la forma de mirar esos píxeles, y sobre todo me enseñó que ahí, en la normalización, está el truco para no terminar engañándote a ti mismo con tus propios mapas.

Artículos relacionados