Detección de agua con Sentinel-2 en Google Earth Engine
Calcula NDWI, MNDWI y AWEInsh con Sentinel-2 para detectar agua con 10 m de resolución.
Introducción #
El agua refleja poca luz en general. Devuelve algo en el azul y el verde, pero en el infrarrojo cercano y en el de onda corta absorbe casi todo. El suelo y la vegetación hacen lo contrario y reflejan mucho más en el infrarrojo. Si comparamos el verde con una banda infrarroja obtenemos un número que tiende a ser positivo sobre el agua y negativo sobre todo lo demás, y en esa idea se basan los índices espectrales para detectar agua.
En esta lección calcularemos tres de estos índices, NDWI, MNDWI y AWEInsh, con Sentinel-2. Con 10 m de resolución se detectan ríos, canales y caños mucho más estrechos que con Landsat.
Objetivos #
- Comprender en qué bandas se diferencia el agua del resto de coberturas.
- Calcular NDWI, MNDWI y AWEInsh en Earth Engine.
- Visualizar los índices con una paleta que resalte el agua.
- Exportar los tres índices a Google Drive.
Recursos #
- NDWI y MNDWI en Sentinel Hub
- Feyisa et al. (2014), Automated Water Extraction Index
- Sentinel-2 Surface Reflectance (COPERNICUS/S2_SR_HARMONIZED)
Los índices #
| Índice | Fórmula | Sentinel-2 |
|---|---|---|
| NDWI | (Verde − NIR) / (Verde + NIR) | (B3 − B8) / (B3 + B8) |
| MNDWI | (Verde − SWIR1) / (Verde + SWIR1) | (B3 − B11) / (B3 + B11) |
| AWEInsh | 4(Verde − SWIR1) − (0,25 NIR + 2,75 SWIR2) | B3, B11, B8, B12 |
- NDWI es el más sencillo y funciona muy bien en lagos y embalses.
- MNDWI cambia el NIR por el SWIR1 y separa mejor el agua de las zonas urbanas.
- AWEInsh combina cuatro bandas con coeficientes calculados para que el umbral 0 separe bien el agua, incluso frente a superficies oscuras como techos o asfalto.
De dónde viene cada índice #
- NDWI. McFeeters (1996) lo propuso para delimitar cuerpos de agua abiertos con Landsat, comparando el verde con el infrarrojo cercano. Ese mismo año, Gao publicó otro índice también llamado NDWI, pero pensado para medir el agua dentro de las hojas y calculado con dos bandas infrarrojas. Cuando encuentres "NDWI" en un artículo, revisa qué bandas usa.
- MNDWI. Xu (2006) observó que con el NDWI las zonas urbanas también daban valores positivos y se confundían con agua. Reemplazó el infrarrojo cercano por el SWIR1, donde el agua sigue absorbiendo casi todo pero las superficies construidas reflejan mucho más.
- AWEI. Feyisa, Meilby, Fensholt y Proud (2014) buscaban extraer agua de forma automática con un umbral fijo de 0. Propusieron dos versiones, AWEInsh para zonas sin sombras importantes y AWEIsh para paisajes con sombras de montañas o edificios. En el curso usamos AWEInsh.
Paso 1: Preparar la imagen #
Aplicamos la máscara de nubes y tomamos la primera escena con poca nubosidad sobre el AOI.
El script usa una geometría llamada AOI. Dibújala con las herramientas de geometría del mapa en el Code Editor y renómbrala como AOI en el panel de importaciones.
// Máscara de nubes con la banda SCL y paso a reflectancia (0 a 1) function maskS2clouds(img) { var scl = img.select('SCL'); var mask = scl.neq(3) // sombra de nubes .and(scl.neq(8)) // nubes, probabilidad media .and(scl.neq(9)) // nubes, probabilidad alta .and(scl.neq(10)); // cirros return img.updateMask(mask).select('B.*').divide(10000); }
// Primera imagen de Sentinel-2 con poca nubosidad sobre el AOI var s2_image = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") .filterDate("2023-01-01", "2023-12-01") .filter(ee.Filter.lte('CLOUDY_PIXEL_PERCENTAGE', 10)) .filterBounds(AOI) .map(maskS2clouds) .first() .clip(AOI); print(s2_image);
// Imagen en color verdadero Map.addLayer(s2_image, {bands: "B4,B3,B2", min: 0, max: 0.3, gamma: 1}, "Sentinel-2"); Map.centerObject(AOI, 11);
Paso 2: Calcular los índices para detectar agua #
NDWI y MNDWI son diferencias normalizadas entre dos bandas, así que basta con normalizedDifference(), que recibe primero la banda verde y después la infrarroja. AWEInsh combina cuatro bandas con coeficientes fijos, de modo que lo escribimos con expression() y asignamos un nombre a cada banda dentro de la fórmula.
// Índices para detectar agua con las bandas de Sentinel-2 var NDWI = s2_image.normalizedDifference(['B3', 'B8']).rename('NDWI'); var MNDWI = s2_image.normalizedDifference(['B3', 'B11']).rename('MNDWI'); var AWEInsh = s2_image.expression('4 * (GREEN - SWIR1) - (0.25 * NIR + 2.75 * SWIR2)', { 'GREEN': s2_image.select('B3'), 'SWIR1': s2_image.select('B11'), 'SWIR2': s2_image.select('B12'), 'NIR': s2_image.select('B8') }).rename('AWEInsh');
Paso 3: Visualizar los índices #
Usamos una paleta de −1 a 1 que va del rojo al azul. Los cuerpos de agua quedan en tonos cian y azul, y el suelo y la vegetación en rojo, amarillo o verde. NDWI y MNDWI siempre caen entre −1 y 1. AWEInsh no está acotado a ese rango, pero su umbral también es 0, así que la misma paleta separa bien el agua de lo demás.
// Simbología: rojo para lo seco, azul para el agua var waterPalette = {min: -1, max: 1, palette: ['red', 'yellow', 'green', 'cyan', 'blue']}; Map.addLayer(NDWI, waterPalette, 'NDWI'); Map.addLayer(MNDWI, waterPalette, 'MNDWI'); Map.addLayer(AWEInsh, waterPalette, 'AWEInsh');
Paso 4: Exportar los índices #
Unimos los tres índices con addBands() para que el GeoTIFF tenga una banda por índice, en el mismo orden en que aparecen en el mapa, y lo enviamos a Google Drive desde la pestaña Tasks.
// Unir los índices y exportarlos var index = NDWI.addBands([MNDWI, AWEInsh]).toFloat(); Export.image.toDrive({ image: index, description: "sentinel_2_water_index", folder: "index", region: AOI, scale: 10, maxPixels: 1e13, fileFormat: "TIFF", formatOptions: {cloudOptimized: true} });
Código completo #
Este es el script completo. Cópialo, pégalo en el Code Editor, dibuja tu AOI y presiona Run.
// Máscara de nubes con la banda SCL y paso a reflectancia (0 a 1) function maskS2clouds(img) { var scl = img.select('SCL'); var mask = scl.neq(3) // sombra de nubes .and(scl.neq(8)) // nubes, probabilidad media .and(scl.neq(9)) // nubes, probabilidad alta .and(scl.neq(10)); // cirros return img.updateMask(mask).select('B.*').divide(10000); } // Primera imagen de Sentinel-2 con poca nubosidad sobre el AOI var s2_image = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED") .filterDate("2023-01-01", "2023-12-01") .filter(ee.Filter.lte('CLOUDY_PIXEL_PERCENTAGE', 10)) .filterBounds(AOI) .map(maskS2clouds) .first() .clip(AOI); print(s2_image); // Imagen en color verdadero Map.addLayer(s2_image, {bands: "B4,B3,B2", min: 0, max: 0.3, gamma: 1}, "Sentinel-2"); Map.centerObject(AOI, 11); // Índices para detectar agua con las bandas de Sentinel-2 var NDWI = s2_image.normalizedDifference(['B3', 'B8']).rename('NDWI'); var MNDWI = s2_image.normalizedDifference(['B3', 'B11']).rename('MNDWI'); var AWEInsh = s2_image.expression('4 * (GREEN - SWIR1) - (0.25 * NIR + 2.75 * SWIR2)', { 'GREEN': s2_image.select('B3'), 'SWIR1': s2_image.select('B11'), 'SWIR2': s2_image.select('B12'), 'NIR': s2_image.select('B8') }).rename('AWEInsh'); // Simbología: rojo para lo seco, azul para el agua var waterPalette = {min: -1, max: 1, palette: ['red', 'yellow', 'green', 'cyan', 'blue']}; Map.addLayer(NDWI, waterPalette, 'NDWI'); Map.addLayer(MNDWI, waterPalette, 'MNDWI'); Map.addLayer(AWEInsh, waterPalette, 'AWEInsh'); // Unir los índices y exportarlos var index = NDWI.addBands([MNDWI, AWEInsh]).toFloat(); Export.image.toDrive({ image: index, description: "sentinel_2_water_index", folder: "index", region: AOI, scale: 10, maxPixels: 1e13, fileFormat: "TIFF", formatOptions: {cloudOptimized: true} });
Conclusiones #
Con Sentinel-2 los contornos del agua salen mucho más definidos. Ten en cuenta que MNDWI y AWEInsh usan bandas SWIR de 20 m, por lo que en los bordes verás algo menos de detalle que con NDWI.
Referencias #
- McFeeters, S. K. (1996). The use of the Normalized Difference Water Index (NDWI) in the delineation of open water features. International Journal of Remote Sensing, 17(7), 1425–1432.
- Gao, B.-C. (1996). NDWI—A normalized difference water index for remote sensing of vegetation liquid water from space. Remote Sensing of Environment, 58(3), 257–266.
- Xu, H. (2006). Modification of normalised difference water index (NDWI) to enhance open water features in remotely sensed imagery. International Journal of Remote Sensing, 27(14), 3025–3033.
- Feyisa, G. L., Meilby, H., Fensholt, R. y Proud, S. R. (2014). Automated Water Extraction Index: A new technique for surface water mapping using Landsat imagery. Remote Sensing of Environment, 140, 23–35.
