Skip to content

Change Detection

Persona: Forest ecologist, land manager, conservation analyst Concept: #vegetationDifficulty: Intermediate

Scenario

Detect vegetation change in the Sierra Nevada, California, by comparing Sentinel-2 summer composites from 2020 (baseline) and 2024 (current). Compute NDVI for both periods, calculate the difference, classify change into health zones, and summarize by watershed.

Data Sources

LayerSourceTypeResolution
Sentinel-2 2020Copernicus Sentinel-2 L2Araster10m
Sentinel-2 2024Copernicus Sentinel-2 L2Araster10m
WatershedsUSGS WBD HUC-10vectorN/A
Fire perimetersMTBS 2020-2024vectorN/A

Operations Used

OperationPurpose
imagery_radiometric_indicesCompute NDVI from Sentinel-2 bands
raster_calcCompute NDVI difference (2024 - 2020)
raster_reclassifyClassify change into loss/stable/gain zones
analysis_zonal_statsSummarize change per watershed

Complete Workspace

yaml
name: sierra-ndvi-change
version: "1.0"
description: >
  NDVI change detection in the Sierra Nevada, California.
  Compares summer 2020 baseline to summer 2024 to identify
  vegetation loss (drought/fire) and recovery areas.

settings:
  default_bbox: [-120.3, 37.9, -119.8, 38.4]
  default_crs: EPSG:4326

layers:

  # --- SOURCE IMAGERY ---

  source/sentinel2-2020:
    uri: cache/sierra-sentinel2-2020.tif
    type: raster
    description: Sentinel-2 L2A summer composite, July-August 2020

  source/sentinel2-2024:
    uri: cache/sierra-sentinel2-2024.tif
    type: raster
    description: Sentinel-2 L2A summer composite, July-August 2024

  source/watersheds:
    uri: cache/sierra-huc10.geojson
    type: vector
    description: HUC-10 watershed boundaries
    style:
      stroke: "#1565C0"
      fill: transparent

  source/fire-perimeters:
    uri: cache/sierra-fires-2020-2024.geojson
    type: vector
    description: MTBS fire perimeters (2020-2024)
    style:
      stroke: "#FF4444"
      fill: "rgba(255,68,68,0.2)"

  # --- NDVI COMPUTATION ---

  analysis/ndvi-2020:
    type: raster
    description: NDVI from 2020 baseline imagery
    compute:
      op: imagery_radiometric_indices
      inputs:
        imagery: { layer: source/sentinel2-2020 }
      params:
        index: ndvi
        red_band: 4
        nir_band: 8
    style:
      palette: ndvi
      rescale: "-0.2,0.9"

  analysis/ndvi-2024:
    type: raster
    description: NDVI from 2024 current imagery
    compute:
      op: imagery_radiometric_indices
      inputs:
        imagery: { layer: source/sentinel2-2024 }
      params:
        index: ndvi
        red_band: 4
        nir_band: 8
    style:
      palette: ndvi
      rescale: "-0.2,0.9"

  # --- CHANGE DETECTION ---

  analysis/ndvi-change:
    type: raster
    description: NDVI difference (2024 - 2020). Negative = vegetation loss.
    compute:
      op: raster_calc
      inputs:
        a: { layer: analysis/ndvi-2024 }
        b: { layer: analysis/ndvi-2020 }
      params:
        expression: "a - b"
    style:
      palette: rdylgn
      rescale: "-0.5,0.5"
      info:
        fields: [ndvi_change]
        section: Vegetation Change

  # --- CLASSIFICATION ---

  analysis/change-classes:
    type: raster
    description: >
      Vegetation change classification:
      1=severe loss, 2=moderate loss, 3=stable, 4=moderate gain, 5=recovery
    compute:
      op: raster_reclassify
      inputs:
        raster: { layer: analysis/ndvi-change }
      params:
        breaks: [-1.0, -0.3, -0.1, 0.1, 0.3, 1.0]
        labels: [1, 2, 3, 4, 5]

  # --- WATERSHED STATISTICS ---

  results/change-by-watershed:
    type: vector
    description: NDVI change statistics per watershed
    compute:
      op: analysis_zonal_stats
      inputs:
        raster: { layer: analysis/ndvi-change }
        zones: { layer: source/watersheds }
      params:
        stats: [mean, min, max, std, count]
    style:
      type: fill
      property: mean
      palette: rdylgn
      table:
        columns:
          - { field: name, label: Watershed }
          - { field: mean, label: "Mean NDVI change", format: ".3f" }
          - { field: min, label: "Min NDVI change", format: ".3f" }
          - { field: count, label: Pixels }

Key Insight

The workspace YAML is a DAG. Each layer references its inputs by path:

source/sentinel2-2020 → analysis/ndvi-2020 ──┐
                                               ├→ analysis/ndvi-change → analysis/change-classes
source/sentinel2-2024 → analysis/ndvi-2024 ──┘                       → results/change-by-watershed

The platform resolves dependencies and executes in the correct order. No imperative script needed.

Licensed under CC-BY-4.0