Las imágenes obtenidas por los satélites encargados de la observación de la tierra nos proporcionan una ingente cantidad de datos con múltiples aplicaciones. Algunas de estas imágenes están disponibles de forma gratuita como es el caso de las imágenes de los satélites Sentinel del programa Copernicus. Podemos utilizar estas imágenes de muchas formas, una de ellas es mediante OpenLayers, que es una librería JavaScript que se emplea para crear y publicar mapas en la web.
En este tutorial explicaremos cómo podemos crear un mapa web con OpenLayers utilizando las imágenes Sentinel.
Índice
Paso 1. Obtención de las imágenes
En un artículo anterior hemos visto algunos métodos para realizar la búsqueda de imágenes de satélite con STAC. La especificación STAC es un lenguaje común para describir información geoespacial, por lo que es más fácil trabajar con ella, indexarla y descubrirla. Utilizando el plugin STAC API Browser de QGIS realizamos una búsqueda de imágenes de los satélites Sentinel en el área geográfica de estrecho de Gibraltar.
Elegimos una imagen con formato TIFF, porque es el que vamos a utilizar en OpenLayers como veremos más adelante.
En QGIS consultamos también las propiedades de la imagen, porque nos va a proporcionar los datos que necesitaremos para crear el mapa con OpenLayers.
Concretamente los datos que nos interesa conocer son la url de la imagen, su SRC y la extensión.
Paso 2. Publicar las imágenes de Sentinel en OpenLayers
Ahora que ya conocemos los datos de la imagen de satélite que vamos a utilizar, comenzamos a trabajar en la aplicación con OpenLayers.
Creamos un nuevo proyecto siguiendo las instrucciones de la documentación de OpenLayers.
Editamos el archivo index.js para que contenga lo siguiente:
- Primero importamos los módulos que necesitamos.
import './style.css'; import GeoTIFFSource from 'ol/source/GeoTIFF.js'; import Map from 'ol/Map.js'; import Projection from 'ol/proj/Projection.js'; import TileLayer from 'ol/layer/WebGLTile.js'; import View from 'ol/View.js'; import {getCenter} from 'ol/extent.js';
- Además de las clases habituales en un mapa de OpenLayers utilizamos:
ol/source/GeoTIFF
que proporciona la fuente para trabajar con datos GeoTIFF.ol/layer/WebGLTile
que lo empleamos para el tratamiento de capas que proporcionan imágenes en mosaico pre-renderizadas en cuadrículas y que estén organizadas por niveles de zoom.- Para manejar las proyecciones de las imágenes utilizamos
ol/proj/Projection
- Ahora tenemos que empezar a definir los datos específicos de la imagen que son los que vimos antes cuando consultamos sus propiedades en QGIS.
Proyección
Definimos la proyección de la imagen, que en este caso es EPSG:3260. También hay que definir las unidades, que como se puede ver, es el metro.
const projection = new Projection({ code: 'EPSG:32630',//Gibraltar units: 'm', });
Extensión
La extensión de la imagen.
const sourceExtent = [199980, 3890220, 309780, 4000020];
Url de la imagen
Para construir la fuente necesitamos proporcionar la url de la imagen.
const source = new GeoTIFFSource({ sources: [ { url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/30/S/TE/2022/12/S2A_30STE_20221229_0_L2A/TCI.tif' }, ], });
El mapa
Una vez que hemos definido los parámetros de la imagen creamos la capa y el mapa.
const layer = new TileLayer({ source: source, }); new Map({ target: 'map', layers: [layer], view: new View({ projection: projection, center: getCenter(sourceExtent), extent: sourceExtent, zoom: 1, }), });
Ahora podremos ver la imagen en el navegador:
Paso 3. Imagen en falso color
En el ejemplo anterior trabajamos con una imagen en color verdadero pero podemos realizar combinaciones de bandas para obtener otras imágenes en las que se destaque alguna característica.
Las imágenes Sentinel-2 tienen las siguientes bandas:
Si queremos resaltar la vegetación podemos mostrar la reflectancia del infrarrojo cercano (B08) en el canal rojo, la reflectancia roja (B04) en el canal verde y la reflectancia verde (B03) en el canal azul. La combinación de bandas 8-4-3 tiene buena sensibilidad a la vegetación verde (la cual aparecerá representada en una tonalidad roja), debido a la alta reflectividad en el infrarrojo y la baja en el visible, y representa de forma clara caminos y masas de agua. Esta combinación de bandas la hacemos modificando el source que habíamos creado antes de la siguiente forma.
const source = new GeoTIFFSource({ sources: [ { // infrarrojo cercano url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/30/S/TE/2022/12/S2A_30STE_20221229_0_L2A/B08.tif', max: 5000, }, { // rojo url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/30/S/TE/2022/12/S2A_30STE_20221229_0_L2A/B04.tif', max: 5000, }, { // verde url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/30/S/TE/2022/12/S2A_30STE_20221229_0_L2A/B03.tif', max: 5000, }, ], });
La imagen que obtenemos es:
Paso 4. Calcular el Índice de Vegetación de Diferencia Normalizada (NDVI) en OpenLayers
El NDVI es un índice de vegetación que se utiliza para estimar la cantidad, calidad y desarrollo de la vegetación con base a la medición de la intensidad de la radiación de ciertas bandas del espectro electromagnético que la vegetación emite o refleja. El NDVI es la relación entre la diferencia entre el infrarrojo cercano (NIR) y el rojo (RED) y la suma de los valores de reflectancia del infrarrojo cercano y el rojo.
NDVI = (NIR – RED) / (NIR + RED)
Por lo tanto las bandas que tenemos que utilizar en el caso de las imágenes Sentinel son la banda 4 (RED) y la banda 8 (NIR):
const source = new GeoTIFFSource({ sources: [ { // RED url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/30/S/TE/2022/12/S2A_30STE_20221229_0_L2A/B04.tif', max: 10000, }, { // NIR url: 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/30/S/TE/2022/12/S2A_30STE_20221229_0_L2A/B08.tif', max: 10000, }, ], });
Ahora es el momento de realizar las operaciones entre las bandas que indicamos antes:
// Infrarrojo cercano es la segunda banda const nir = ['band', 2]; // Rojo es la primera banda const red = ['band', 1]; const diferencia = ['-', nir, red]; const suma = ['+', nir, red]; const ndvi = ['/', diferencia, suma];
La expresión NDVI dará como resultado un valor entre -1 (poca vegetación) y 1 (mucha vegetación). El siguiente paso es asignar estos valores a los colores:
const layer = new TileLayer({ source: source, style: { color: [ 'interpolate', ['linear'], ndvi, -0.2, [191, 191, 191], -0.1, [219, 219, 219], 0, [255, 255, 224], 0.025, [255, 250, 204], 0.05, [237, 232, 181], 0.075, [222, 217, 156], 0.1, [204, 199, 130], 0.125, [189, 184, 107], 0.15, [176, 194, 97], 0.175, [163, 204, 89], 0.2, [145, 191, 82], 0.25, [128, 179, 71], 0.3, [112, 163, 64], 0.35, [97, 150, 54], 0.4, [79, 138, 46], 0.45, [64, 125, 36], 0.5, [48, 110, 28], 0.55, [33, 97, 18], 0.6, [15, 84, 10], 0.65, [0, 69, 0], ], }, });
Utilizamos la propiedad color contenida en style de la clase ol/layer/WebGLTile para definir el color de la imagen. Interpolamos los valores que hemos obtenido antes con la expresión ndvi dando una serie de valores. Utilizamos el operador interpolate para crear una interpolación lineal.
El resultado lo vemos a continuación.
Y hasta aquí, si quieres continuar trabajando con imágenes satélite Sentinel en OpenLayers.
Tutor del curso online de Análisis GeoEspacial con Python y de los cursos online de webmapping. Echa un vistazo a todos nuestros cursos de SIG online.