Forest Health Indices
Calculate vegetation indices (NDVI, NDMI, NBR, EVI) from Sentinel-2 satellite imagery to monitor forest health, detect drought stress, and identify burn areas.
Overview
The Forest Health Indices pattern calculates four key spectral vegetation indices from Sentinel-2 multispectral satellite imagery. These indices are essential for monitoring forest health, detecting drought stress, identifying wildfire damage, and tracking vegetation changes over time.
Indices Calculated
NDVI (Normalized Difference Vegetation Index)
The most widely used vegetation index. Measures photosynthetic activity and vegetation density.
NDVI = (NIR - Red) / (NIR + Red)
= (B08 - B04) / (B08 + B04)
| NDVI Value | Interpretation |
|---|---|
| -1.0 to 0 | Water, snow, clouds, bare soil |
| 0 to 0.2 | Barren rock, sand, or dead vegetation |
| 0.2 to 0.4 | Sparse vegetation, shrubs, grassland |
| 0.4 to 0.6 | Moderate vegetation |
| 0.6 to 1.0 | Dense, healthy vegetation |
NDMI (Normalized Difference Moisture Index)
Detects vegetation water content and drought stress. Useful for early detection of water stress before visible symptoms appear.
NDMI = (NIR - SWIR1) / (NIR + SWIR1)
= (B08 - B11) / (B08 + B11)
| NDMI Value | Interpretation |
|---|---|
| -1.0 to 0 | Bare soil, very dry vegetation |
| 0 to 0.2 | Water-stressed vegetation |
| 0.2 to 0.4 | Moderate moisture levels |
| 0.4 to 1.0 | High vegetation water content |
NBR (Normalized Burn Ratio)
Identifies burned areas and assesses burn severity. Essential for wildfire monitoring and post-fire recovery tracking.
NBR = (NIR - SWIR2) / (NIR + SWIR2)
= (B08 - B12) / (B08 + B12)
| NBR Value | Interpretation |
|---|---|
| -0.5 to -0.1 | High burn severity |
| -0.1 to 0.1 | Moderate burn severity |
| 0.1 to 0.27 | Low burn severity |
| 0.27 to 0.66 | Unburned vegetation |
For change detection, calculate dNBR = pre-fire NBR - post-fire NBR
EVI (Enhanced Vegetation Index)
Improved version of NDVI that reduces atmospheric interference and soil background effects. More accurate in high-biomass regions.
EVI = 2.5 × ((NIR - Red) / (NIR + 6×Red - 7.5×Blue + 1))
= 2.5 × ((B08 - B04) / (B08 + 6×B04 - 7.5×B02 + 1))
EVI ranges from -1 to 1, with similar interpretation to NDVI but less saturation in dense vegetation.
Usage
Pull the Task Image
fabric image pull forest-indices
Basic Usage
Calculate all four indices from Sentinel-2 data:
fabric task run forest-indices \
--input-dir ./sentinel2_bands/ \
--output-dir ./results/
Calculate Specific Indices
Only calculate NDVI and NDMI:
fabric task run forest-indices \
--input-dir ./sentinel2_bands/ \
--output-dir ./results/ \
--indices "NDVI,NDMI"
In a Pipeline
tasks:
calculate-indices:
image: public.ecr.aws/m33/forest-indices:latest
depends_on:
- download-imagery
inputs:
input_dir: "{{ tasks.download-imagery.outputs.data_dir }}"
output_dir: /data/indices
indices: ["NDVI", "NDMI", "NBR", "EVI"]
Input Requirements
Band Files
The task automatically detects band files with flexible naming:
# Supported naming patterns:
B04.tif
B04_10m.tif
T32TQM_20240715T103031_B04_10m.tif
Directory Structure
input_dir/
├── B02.tif # Blue (10m) - required for EVI
├── B04.tif # Red (10m)
├── B08.tif # NIR (10m)
├── B11.tif # SWIR1 (20m) - auto-resampled to 10m
└── B12.tif # SWIR2 (20m) - auto-resampled to 10m
Output
Output Files
Each index is saved as a GeoTIFF with preserved spatial metadata:
output_dir/
├── ndvi.tif # Values: -1 to 1
├── ndmi.tif # Values: -1 to 1
├── nbr.tif # Values: -1 to 1
└── evi.tif # Values: -1 to 1
Output Properties
- Format: GeoTIFF with LZW compression
- Resolution: 10m (20m bands automatically resampled)
- CRS: Preserved from input
- NoData: -9999
Visualization
In QGIS
- Open the output .tif file
- Right-click layer → Properties → Symbology
- Set render type to "Singleband pseudocolor"
- Set min/max to -1 and 1
- Choose color ramp: RdYlGn (Red-Yellow-Green)
Recommended Color Scales
| Index | Color Ramp | Min | Max |
|---|---|---|---|
| NDVI | RdYlGn | -0.2 | 0.8 |
| NDMI | BrBG | -0.3 | 0.5 |
| NBR | RdYlBu | -0.5 | 0.7 |
| EVI | RdYlGn | -0.2 | 0.8 |
Performance
- Processing time: ~30 seconds per 100 km² at 10m resolution
- Memory usage: ~2 GB peak for typical scenes
- Docker image size: 450 MB
Use Cases
Drought Monitoring
Track NDMI over time to detect early signs of water stress:
# Process multiple dates
for date in 2026-01 2026-02 2026-03; do
fabric task run forest-indices \
--input-dir ./sentinel2_${date}/ \
--output-dir ./timeseries/${date}/
done
Wildfire Assessment
Calculate pre- and post-fire NBR to assess burn severity:
# Pre-fire baseline
fabric task run forest-indices \
--input-dir ./pre_fire/ \
--output-dir ./pre_fire_indices/ \
--indices "NBR"
# Post-fire assessment
fabric task run forest-indices \
--input-dir ./post_fire/ \
--output-dir ./post_fire_indices/ \
--indices "NBR"
# dNBR = pre_NBR - post_NBR (calculate in QGIS or Python)
Forest Health Baseline
Create a comprehensive baseline of forest conditions:
fabric run forest-monitoring \
--input-study_area "Black Forest, Germany" \
--input-date_range "2026-06-01/2026-06-30" \
--input-indices "NDVI,NDMI,NBR,EVI"
Related
- Understanding Vegetation Indices - Learn the science behind these indices
- Writing Pipelines - Create multi-step workflows
Requirements
Required Bands
| Band ID | Name | Resolution | Purpose |
|---|---|---|---|
| B02 | Blue | 10m | Visible blue band for EVI calculation |
| B04 | Red | 10m | Visible red band for vegetation indices |
| B08 | NIR | 10m | Near-infrared for vegetation health |
| B11 | SWIR1 | 20m | Short-wave infrared for moisture content |
| B12 | SWIR2 | 20m | Short-wave infrared for burn detection |