Spectral Indices

Spectral indices turn multi-band information into a single value that highlights your target feature. They are fast, interpretable, and power many remote-sensing workflows (vegetation, water, burn scars, urban areas).

Learning objectives

  • Explain what a normalized difference index measures.
  • Compute NDVI (and one other index) in Earth Engine.
  • Read band designations for different sensors.
  • Interpret index ranges and common pitfalls.

Why it matters

Indices compress spectral information into intuitive numbers you can threshold, compare over time, or feed into classifiers-without heavy modeling.

NDVI formula graphic
Normalized difference indices scale from -1 to 1 to highlight contrast between two bands.

Quick win: NDVI on Landsat 8

// NDVI example (Landsat 8 Surface Reflectance)
var img = ee.Image('LANDSAT/LC08/C02/T1_L2/LC08_044034_20210623')
  .multiply(0.0000275).add(-0.2); // apply scale/offset
var ndvi = img.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI');
Map.centerObject(img, 9);
Map.addLayer(ndvi, {min: 0, max: 0.8, palette: ['brown', 'yellow', 'green']}, 'NDVI');
print('NDVI min/max', ndvi.reduceRegion({
  reducer: ee.Reducer.minMax(),
  geometry: img.geometry(),
  scale: 30
}));

What you should see

A green-to-brown NDVI layer and console print of min/max values near 0-0.8 for vegetated areas.

Common indices

  • NDVI = (NIR - RED) / (NIR + RED) - vegetation vigor.
  • NDWI = (NIR - SWIR) / (NIR + SWIR) - vegetation water content.
  • MNDWI = (GREEN - SWIR) / (GREEN + SWIR) - open water detection.
  • NBR = (NIR - SWIR2) / (NIR + SWIR2) - burn severity.
  • NDBI = (SWIR - NIR) / (SWIR + NIR) - built-up areas.

Pro tips

  • Band names differ by sensor: Landsat 8 NIR=B5, RED=B4; Sentinel-2 NIR=B8, RED=B4.
  • Use .normalizedDifference() to avoid manual formula mistakes.
  • Mask clouds before computing indices to avoid artifacts.

Try another index: NDWI (Sentinel-2)

var s2 = ee.ImageCollection('COPERNICUS/S2_SR')
  .filterDate('2023-06-01', '2023-06-15')
  .filterBounds(ee.Geometry.Point([-82.3, 29.6]))
  .first();
var ndwi = s2.normalizedDifference(['B8', 'B11']).rename('NDWI');
Map.addLayer(ndwi, {min: -0.5, max: 0.8, palette: ['brown','beige','cyan']}, 'NDWI');

Common mistakes

  • Using wrong band numbers for a sensor (check the Data Catalog).
  • Forgetting to scale/offset surface reflectance before computing indices.
  • Interpreting raw index values without masking clouds/shadows.

Quick self-check

  1. What range do normalized difference indices fall within?
  2. Which bands would you use for NBR on Landsat 8?
  3. Why should you cloud-mask before computing an index?

Next steps

  • Compute NDVI and NDWI on the same scene; compare histograms and maps.
  • Test MNDWI on a coastal area to isolate water bodies.
  • Read the Earth Engine docs for normalizedDifference and band designations per sensor.