SIG EDUCA YouTube Tutoriales
Módulo de Google Earth Engine · Índices espectrales · público

LIST_EDUCAINDEX

Módulo de Google Earth Engine con trece índices espectrales para Landsat 4 a 9 (NDVI, EVI, SAVI, MSAVI, NDMI, NBR, NBR2, NDWI, MNDWI, AWEI, AWEsh, MBSRV y MBSRN) y una función que los calcula todos.

Qué hace #

Reúne en un solo lugar los índices que usamos en el curso: de vegetación (NDVI, EVI, SAVI y MSAVI), de humedad y fuego (NDMI, NBR y NBR2) y de agua (NDWI, MNDWI, AWEI, AWEsh, MBSRV y MBSRN). Cada índice es una función que recibe una imagen y devuelve una banda con el nombre del índice en minúsculas. calcAllIndices() devuelve una sola imagen con las trece bandas. Funciona con cualquier Landsat de la Colección 2, nivel 2, siempre que las bandas tengan los nombres comunes.

Cómo cargarlo #

El módulo es público. Pega esta línea al inicio de tu script en el Code Editor y usa sus funciones con x. delante, por ejemplo x.NDVI(image).

var x = require('users/sigeduca/routines:Indexes/LIST_EDUCAINDEX');

Funciones #

FunciónRecibeDevuelve
NDVI(image)Imagen con Nir y Red.Banda ndvi: vigor de la vegetación.
EVI(image)Imagen con Nir, Red y Blue.Banda evi: vigor en vegetación densa.
SAVI(image)Imagen con Nir y Red.Banda savi: vegetación con corrección del suelo.
MSAVI(image)Imagen con Nir y Red.Banda msavi: SAVI sin factor de suelo fijo.
NDMI(image)Imagen con Nir y Swir1.Banda ndmi: humedad de la vegetación.
NBR(image)Imagen con Nir y Swir2.Banda nbr: áreas quemadas.
NBR2(image)Imagen con Swir1 y Swir2.Banda nbr2: severidad del fuego y humedad del suelo.
NDWI(image)Imagen con Green y Nir.Banda ndwi: agua abierta.
MNDWI(image)Imagen con Green y Swir1.Banda mndwi: agua, separada mejor de lo construido.
AWEI(image)Imagen con Green, Nir, Swir1 y Swir2.Banda awei: agua sin sombras (AWEInsh).
AWESH(image)Imagen con Blue, Green, Nir, Swir1 y Swir2.Banda awesh: agua en zonas con sombras.
MBSRV(image)Imagen con Green y Red.Banda mbsrv: suma del visible (verde + rojo), usada por DSWE.
MBSRN(image)Imagen con Nir y Swir1.Banda mbsrn: suma del infrarrojo (NIR + SWIR1), usada por DSWE.
calcAllIndices(image)Imagen con Blue, Green, Red, Nir, Swir1 y Swir2.Imagen con las trece bandas anteriores.

Escala antes de calcular. EVI, SAVI y MSAVI tienen constantes (+1, +0,5) pensadas para reflectancia de 0 a 1. Con los valores digitales de la Colección 2 sin escalar, dan resultados sin sentido. Aplica primero × 0.0000275 − 0.2.

Nombres de bandas. Las funciones buscan las bandas por nombre común. En Landsat 8 y 9 el azul es SR_B2; en Landsat 4, 5 y 7 es SR_B1. Renombra con select() según el satélite, como en el ejemplo.

Ejemplo con una imagen #

Dibuja una geometría llamada AOI en el mapa y ejecuta este script. Toma una imagen de Landsat 9 con menos de 10 % de nubes sobre tu zona, la pasa a reflectancia y le aplica el módulo.

// Cargar el módulo
var x = require('users/sigeduca/routines:Indexes/LIST_EDUCAINDEX');

// Una imagen de Landsat 9 con poca nubosidad sobre el AOI
var img = ee.ImageCollection('LANDSAT/LC09/C02/T1_L2')
  .filterBounds(AOI)
  .filter(ee.Filter.lte('CLOUD_COVER', 10))
  .first();

// Escalar a reflectancia y usar los nombres comunes de las bandas
var bands = img.select('SR_B.').multiply(0.0000275).add(-0.2)
  .select(['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7'],
          ['Blue', 'Green', 'Red', 'Nir', 'Swir1', 'Swir2']);

// Un índice o todos a la vez
var evi = x.EVI(bands);
var indices = x.calcAllIndices(bands);
print('Índices', indices);

Map.centerObject(AOI, 11);
Map.addLayer(evi, {min: 0, max: 0.8, palette: ['DF923D', 'FCD163', '74A901', '056201', '004C00']}, 'EVI');
Map.addLayer(indices.select('mndwi'), {min: -0.5, max: 0.5, palette: ['d7191c', 'ffffbf', '2c7bb6']}, 'MNDWI');

Ejemplo con una colección #

Para aplicar el módulo a muchas imágenes usamos map(): la función recibe cada imagen de la colección y devuelve el resultado. Dos detalles importan. Primero, cada imagen debe llegar escalada, con nombres comunes y sin nubes, y de eso se encarga prepare(). Segundo, las operaciones matemáticas borran las propiedades de la imagen, así que copiamos la fecha (system:time_start) con copyProperties() para poder graficar la serie en el tiempo.

// Cargar el módulo
var x = require('users/sigeduca/routines:Indexes/LIST_EDUCAINDEX');

// Prepara cada imagen: máscara de nubes, reflectancia (0 a 1) y nombres comunes
function prepare(img) {
  var qa = img.select('QA_PIXEL');
  var clear = qa.bitwiseAnd(1 << 3).eq(0)   // bit 3: nubes
    .and(qa.bitwiseAnd(1 << 4).eq(0));       // bit 4: sombras de nubes
  var bands = img.select(['SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B6', 'SR_B7'],
                         ['Blue', 'Green', 'Red', 'Nir', 'Swir1', 'Swir2'])
    .multiply(0.0000275).add(-0.2)
    .updateMask(clear);
  // Las operaciones matemáticas borran las propiedades: recuperamos la fecha
  return ee.Image(bands.copyProperties(img, ['system:time_start']));
}

// Landsat 8 y 9 de dos años sobre el AOI
var collection = ee.ImageCollection('LANDSAT/LC09/C02/T1_L2')
  .merge(ee.ImageCollection('LANDSAT/LC08/C02/T1_L2'))
  .filterBounds(AOI)
  .filterDate('2023-01-01', '2025-01-01')
  .filter(ee.Filter.lte('CLOUD_COVER', 30))
  .map(prepare);
print('Imágenes', collection.size());

// Calcular los índices de cada imagen, conservando la fecha
var indices = collection.map(function(img) {
  return ee.Image(x.calcAllIndices(img).copyProperties(img, ['system:time_start']));
});
print('Índices por fecha', indices);

// Mediana del NDVI en los dos años
Map.centerObject(AOI, 11);
Map.addLayer(indices.select('ndvi').median(), {min: 0, max: 0.9, palette: ['DF923D', 'FCD163', '74A901', '056201', '004C00']}, 'NDVI mediano');

// NDVI y EVI medios del AOI en cada fecha
var chart = ui.Chart.image.series({
  imageCollection: indices.select(['ndvi', 'evi']),
  region: AOI,
  reducer: ee.Reducer.mean(),
  scale: 30
}).setOptions({title: 'NDVI y EVI medios en el AOI', vAxis: {title: 'Valor del índice'}, pointSize: 3});
print(chart);

Código del módulo #

No necesitas copiarlo para usarlo. Si quieres modificarlo, créalo en tu propio repositorio y cambia la ruta de require().

///////////////////////////////////////////////////////////////////////////////////
// MÓDULO UNIVERSAL DE ÍNDICES ESPECTRALES PARA LANDSAT
// Compatible con la reflectancia de superficie de Landsat 4 a 9 (Colección 2, nivel 2)
// Autor: Cristian Carrascal - Canal SIG Educa
///////////////////////////////////////////////////////////////////////////////////

// --- FUNCIONES DE CADA ÍNDICE ---------------------------------------------------

exports.MBSRV = function (image){
  return image.select(['Green']).add(image.select(['Red']))
    .rename('mbsrv').toFloat();
};

exports.MBSRN = function (image){
  return image.select(['Nir']).add(image.select(['Swir1']))
    .rename('mbsrn').toFloat();
};

exports.AWESH = function (image){
  return image.expression(
    'Blue + 2.5 * Green + (-1.5) * mbsrn + (-0.25) * Swir2', {
      'Blue': image.select(['Blue']),
      'Green': image.select(['Green']),
      'mbsrn': exports.MBSRN(image).select(['mbsrn']),
      'Swir2': image.select(['Swir2'])
    }).rename('awesh').toFloat();
};

exports.NDWI = function(image){
  return image.normalizedDifference(['Green', 'Nir'])
    .rename('ndwi').toFloat();
};

exports.MNDWI = function(image){ 
  return image.expression('(Green - Swir1) / (Green + Swir1)', {
    'Green': image.select(['Green']),
    'Swir1': image.select(['Swir1'])
  }).rename('mndwi').toFloat();
};

exports.AWEI = function (image){
  return image.expression(
    '4*(Green - Swir1) - (0.25 * Nir + 2.75 * Swir2)', {
      'Green': image.select(['Green']),
      'Swir1': image.select(['Swir1']),
      'Swir2': image.select(['Swir2']),
      'Nir':   image.select(['Nir'])
  }).rename('awei').toFloat();
}; 

exports.NDVI = function (image){
  return image.normalizedDifference(['Nir', 'Red'])
    .rename('ndvi').toFloat();
};

exports.EVI = function(image){
  return image.expression(
    '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
      'NIR': image.select(['Nir']),
      'RED': image.select(['Red']),
      'BLUE': image.select(['Blue'])
    }).rename('evi').toFloat();
};

exports.SAVI = function(image){
  return image.expression(
    '((NIR - RED) / (NIR + RED + 0.5)) * 1.5', {
      'NIR': image.select(['Nir']),
      'RED': image.select(['Red'])
    }).rename('savi').toFloat();
};

exports.MSAVI = function(image){
  return image.expression(
    '(2 * NIR + 1 - sqrt(pow((2 * NIR + 1), 2) - 8 * (NIR - RED))) / 2', {
      'NIR': image.select(['Nir']),
      'RED': image.select(['Red'])
    }).rename('msavi').toFloat();
};

exports.NDMI = function(image){
  return image.expression('(NIR - SWIR) / (NIR + SWIR)', {
    'NIR': image.select(['Nir']),
    'SWIR': image.select(['Swir1'])
  }).rename('ndmi').toFloat();
};

exports.NBR = function(image){
  return image.expression('(NIR - SWIR) / (NIR + SWIR)', {
    'NIR': image.select(['Nir']),
    'SWIR': image.select(['Swir2'])
  }).rename('nbr').toFloat();
};

exports.NBR2 = function(image){
  return image.expression('(SWIR1 - SWIR2) / (SWIR1 + SWIR2)', {
    'SWIR1': image.select(['Swir1']),
    'SWIR2': image.select(['Swir2'])
  }).rename('nbr2').toFloat();
};

// --- FUNCIÓN PRINCIPAL: TODOS LOS ÍNDICES A LA VEZ ------------------------------

exports.calcAllIndices = function(image){
  var indices = [
    exports.MBSRV(image),
    exports.MBSRN(image),
    exports.AWESH(image),
    exports.NDWI(image),
    exports.MNDWI(image),
    exports.AWEI(image),
    exports.NDVI(image),
    exports.EVI(image),
    exports.SAVI(image),
    exports.MSAVI(image),
    exports.NDMI(image),
    exports.NBR(image),
    exports.NBR2(image)
  ];
  
  return ee.Image.cat(indices).toFloat();
};

///////////////////////////////////////////////////////////////////////////////////
// USO DE EJEMPLO:
// var x = require('users/sigeduca/routines:Indexes/LIST_EDUCAINDEX');
// var img = ee.Image('LANDSAT/LC08/C02/T1_L2/LC08_008058_20210115');
// var bands = img.select('SR_B.').multiply(0.0000275).add(-0.2)   // reflectancia (0 a 1)
//   .select(['SR_B2','SR_B3','SR_B4','SR_B5','SR_B6','SR_B7'],
//           ['Blue','Green','Red','Nir','Swir1','Swir2']);
// var indices = x.calcAllIndices(bands);
// Map.addLayer(indices.select('ndvi'), {min:0, max:1, palette:['white','green']}, 'NDVI');
///////////////////////////////////////////////////////////////////////////////////

Lecciones que lo usan #

Referencias #

© 2026 SIG EDUCA