Cómo utilizar las imágenes Sentinel en OpenLayers

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.

Cómo utilizar las imágenes Sentinel en OpenLayers

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:

Cómo utilizar las imágenes Sentinel en OpenLayers - Imagen verdadera

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:

Cómo utilizar las imágenes Sentinel en OpenLayers - Falso color

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.

NDVI en OpenLayers

Y hasta aquí, si quieres continuar trabajando con imágenes satélite Sentinel en OpenLayers.