Geoskill: Change Detection

Detect and quantify land cover changes between two co-registered satellite images using NDVI difference, image differencing, or Change Vector Analysis (CVA).

ruiduobao

@ruiduobao

What This Skill Does

Multi-temporal change detection tool for satellite imagery that computes NDVI difference, image differencing, and Change Vector Analysis (CVA) to detect vegetation, urban, and water changes between two time periods. Outputs change magnitude GeoTIFFs, binary change masks, and statistical reports with configurable thresholds.

Replaces manual visual comparison of satellite images by automating pixel-level change detection with multiple analytical methods and statistical reporting.

When to Use It

  • Detect deforestation or vegetation loss between two satellite image dates
  • Identify urban expansion or new construction in a region over time
  • Monitor crop health changes across growing seasons
  • Map water body shrinkage or expansion using NDVI difference
  • Generate a change statistics report for environmental impact assessments
  • Compare Landsat 8/9 and Sentinel-2 imagery for multi-sensor change analysis

Install

$ openclaw skills install @ruiduobao/change-detection

Change Detection

Detect land cover changes between two satellite images using multiple methods: NDVI difference, image differencing, and Change Vector Analysis (CVA).

Features

  • NDVI Difference: ΔNDVI = NDVI_t2 − NDVI_t1 — vegetation change
  • Image Differencing: Per-band difference — general change
  • Change Vector Analysis (CVA): Multi-band magnitude + direction
  • Binary change mask with configurable threshold
  • Statistics report with change percentages
  • Supports Landsat 8/9 and Sentinel-2

Band Configuration

SensorGreenNIRRedSWIR
Landsat 8/9B3B5B4B6
Sentinel-2B3B8B4B11

Usage

Detect vegetation change (NDVI difference)

python scripts\change-detection.py detect \
  --image-t1 2020.tif --image-t2 2023.tif \
  --sensor landsat8 --method ndvi-diff \
  --output change_magnitude.tif \
  --mask change_mask.tif

Change Vector Analysis

python scripts\change-detection.py detect \
  --image-t1 2020.tif --image-t2 2023.tif \
  --sensor landsat8 --method cva \
  --output cva_magnitude.tif \
  --mask cva_mask.tif --threshold 0.15

Generate report

python scripts\change-detection.py report \
  --mask change_mask.tif --json report.json

Installation

pip install rasterio>=1.3.0 numpy>=1.21.0 tqdm>=4.64.0
# Or: pip install -r scripts/requirements.txt

Parameters

  • --image-t1: Path to time-1 image (earlier)
  • --image-t2: Path to time-2 image (later)
  • --sensor: Sensor type (landsat8, landsat9, sentinel2)
  • --method: Detection method (ndvi-diff, image-diff, cva)
  • --output: Output change magnitude GeoTIFF
  • --mask: Output binary change mask
  • --threshold: Change threshold (default: auto via Otsu)
  • --bands: Comma-separated band indices for CVA (default: all)
  • --json: Output statistics as JSON

Output

  • Change magnitude: Float GeoTIFF showing change intensity
  • Binary mask: 1=change, 0=no change
  • Statistics: Change pixel count, percentage, method used

Dependencies

rasterio>=1.3.0
numpy>=1.21.0
tqdm>=4.64.0

Method Selection Guidance

MethodBest ForInput Requirements
ndvi-diffVegetation change (growth, deforestation, crop shift)Red + NIR bands
image-diffGeneral land cover change (any type)Same bands in both images
cvaMulti-band change, direction matters2+ matching bands

Recommendation: Start with ndvi-diff for vegetation studies; use cva when change direction (e.g., vegetation → urban) is important.

Co-registration Guidance

Misaligned images cause false changes. Before running detection:

  • Ensure both images share the same CRS and resolution
  • Use image registration tools (e.g., gdalwarp -tps, ENVI Auto-Registration, or QGIS Coregistration plugins)
  • Sub-pixel alignment (<0.5 pixel RMSE) recommended for pixel-based methods
  • Verify alignment by overlaying both images and checking stable features (roads, buildings)

CVA Direction Output

CVA produces two outputs:

  • Magnitude: Change intensity (float GeoTIFF) — higher = more change
  • Direction (angle): Indicates change type based on band contribution
Angle RangeTypical Interpretation
0°–90°Increase in both bands (e.g., vegetation growth)
90°–180°Band 1 decreases, Band 2 increases
180°–270°Decrease in both bands (e.g., vegetation loss)
270°–360°Band 1 increases, Band 2 decreases

Use --direction-output cva_direction.tif to save the angle raster.

Cross-Sensor Guidance

Comparing images from different sensors (e.g., Landsat 8 vs Sentinel-2):

  • Normalize radiometry: Apply relative radiometric normalization (e.g., histogram matching, IR-MAD)
  • Match resolutions: Resample to coarser resolution
  • Same season: Use images from similar phenological stage
  • Caution: Cross-sensor comparison introduces additional uncertainty

Cloud Masking Guidance

Clouds cause false change detections:

  • Pre-filter images with <10% cloud cover
  • Use QA_PIXEL band to mask clouds in both images
  • Consider temporal compositing (e.g., monthly median) to reduce cloud impact

Batch Processing

Process multiple image pairs with a CSV list:

python scripts\change-detection.py batch \
  --pair-list pairs.csv --sensor landsat8 --method ndvi-diff \
  --output-dir ./results/

pairs.csv format: image_t1,image_t2,output_name

Vector Output

Convert change masks to vector polygons for GIS analysis:

python scripts\change-detection.py vectorize \
  --mask change_mask.tif --output change_polygons.geojson --min-area 500

Outputs GeoJSON or Shapefile with change area attributes.

Visualization

  • Change magnitude: Apply diverging colormap (blue=no change, red=high change)
  • Binary mask: Overlay change areas in red on RGB composite
  • CVA direction: Use cyclic colormap (HSV) for angle visualization
  • Side-by-side: Show t1 image, t2 image, and change map together

Citation

@software{change_detection,
  author  = {ruiduobao},
  title   = {Change Detection Tool},
  url     = {https://github.com/ruiduobao/change-detection},
  version = {0.1.0},
  year    = {2024},
}

Troubleshooting

ErrorCauseSolution
ConnectionErrorNetwork issueCheck internet, retry
HTTP 429Rate limitWait 60s, retry
ValueErrorInvalid inputCheck parameter format
Empty outputNo change detectedLower threshold or check input
ModuleNotFoundErrorMissing depRun pip install
Misregistration artifactsImages not alignedCo-register before detection
Striped outputCloud shadowApply cloud masking

Data Source

Local raster processing — two co-registered GeoTIFF images required.


Advanced Usage

Batch Multi-Pair Detection

for year in 2020 2021 2022 2023; do
  python scripts\change-detection.py detect     --image-t1 ${year}0101.tif --image-t2 $((year+1))0101.tif     --sensor landsat8 --method ndvi-diff     --output change_${year}_$((year+1)).tif
done

CI/CD Integration (GitHub Actions)

# .github/workflows/change-detection.yml
name: Change Detection Pipeline
on:
  schedule:
    - cron: '0 6 1 */3 *'  # Every 3 months
jobs:
  detect:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - run: pip install numpy rasterio
      - run: |
          python scripts\change-detection.py detect \
            --image-t1 data/latest_2023.tif \
            --image-t2 data/latest_2024.tif \
            --sensor landsat8 --method ndvi-diff \
            --output data/change_latest.tif

Vectorize & Import to PostGIS

python scripts\change-detection.py vectorize   --input change_mask.tif --output change.geojson

ogr2ogr -f PostgreSQL PG:"dbname=gis_db" change.geojson -nln change_areas

Performance Tips

  • Use --mask with QA band to exclude clouds before detection
  • CVA method requires more memory; use --bands to limit input bands
  • --threshold accepts 'otsu' (auto) or manual float value

中文说明

对两期卫星影像进行变化检测,支持 NDVI 差值、影像差值和变化向量分析(CVA)三种方法。

功能特性

  • NDVI 差值:ΔNDVI = NDVI_t2 − NDVI_t1 — 植被变化
  • 影像差值:逐波段差值 — 通用变化
  • 变化向量分析(CVA):多波段变化强度 + 方向
  • 二值变化掩膜,可配置阈值
  • 统计报告,含变化百分比
  • 支持 Landsat 8/9 和 Sentinel-2

波段配置

传感器GreenNIRRedSWIR
Landsat 8/9B3B5B4B6
Sentinel-2B3B8B4B11

使用示例

植被变化检测(NDVI 差值)

python scripts\change-detection.py detect \
  --image-t1 2020.tif --image-t2 2023.tif \
  --sensor landsat8 --method ndvi-diff \
  --output change_magnitude.tif \
  --mask change_mask.tif

变化向量分析

python scripts\change-detection.py detect \
  --image-t1 2020.tif --image-t2 2023.tif \
  --sensor landsat8 --method cva \
  --output cva_magnitude.tif \
  --mask cva_mask.tif --threshold 0.15

生成报告

python scripts\change-detection.py report \
  --mask change_mask.tif --json report.json

安装

pip install rasterio>=1.3.0 numpy>=1.21.0 tqdm>=4.64.0
# 或: pip install -r scripts/requirements.txt

参数说明

  • --image-t1: 时相 1 影像路径(早期)
  • --image-t2: 时相 2 影像路径(晚期)
  • --sensor: 传感器类型
  • --method: 检测方法(ndvi-diff, image-diff, cva
  • --output: 输出变化强度 GeoTIFF
  • --mask: 输出二值变化掩膜
  • --threshold: 变化阈值(默认 Otsu 自动)
  • --bands: CVA 使用的波段索引(逗号分隔,默认全部)
  • --json: 以 JSON 输出统计信息

输出结果

  • 变化强度: 浮点 GeoTIFF,显示变化强度
  • 二值掩膜: 1=变化, 0=无变化
  • 统计信息: 变化像素数、占比、使用方法

依赖库

rasterio>=1.3.0
numpy>=1.21.0
tqdm>=4.64.0

方法选择指南

方法适用场景输入要求
ndvi-diff植被变化(生长、砍伐、作物变化)Red + NIR 波段
image-diff通用土地覆盖变化两幅影像波段一致
cva多波段变化,方向重要2+ 匹配波段

建议:植被研究先用 ndvi-diff;需要变化方向信息时用 cva

配准指导

未对齐的影像会导致虚假变化。检测前请确保:

  • 两幅影像使用 相同的 CRS 和分辨率
  • 使用影像配准工具(如 gdalwarp -tps、ENVI 自动配准、QGIS 配准插件)
  • 像元方法建议亚像元对齐(<0.5 像元 RMSE)
  • 叠加两幅影像检查稳定地物(道路、建筑)验证对齐

CVA 方向输出

CVA 产生两个输出:

  • 强度:变化强度(浮点 GeoTIFF)— 值越大变化越强
  • 方向(角度):根据波段贡献指示变化类型
角度范围典型解释
0°–90°两个波段均增加(如植被生长)
90°–180°波段 1 减少,波段 2 增加
180°–270°两个波段均减少(如植被损失)
270°–360°波段 1 增加,波段 2 减少

使用 --direction-output cva_direction.tif 保存角度栅格。

跨传感器指导

比较不同传感器影像(如 Landsat 8 vs Sentinel-2):

  • 辐射归一化:应用相对辐射归一化(如直方图匹配、IR-MAD)
  • 分辨率匹配:重采样至较粗分辨率
  • 同季节:使用相似物候期的影像
  • 注意:跨传感器比较引入额外不确定性 |

云掩膜指导

云会导致虚假变化检测:

  • 预过滤云量 <10% 的影像
  • 使用 QA_PIXEL 波段掩膜两幅影像中的云
  • 考虑时间合成(如月际中值)减少云影响

批量处理

使用 CSV 列表处理多对影像:

python scripts\change-detection.py batch \
  --pair-list pairs.csv --sensor landsat8 --method ndvi-diff \
  --output-dir ./results/

pairs.csv 格式:image_t1,image_t2,output_name

矢量输出

将变化掩膜转换为矢量多边形用于 GIS 分析:

python scripts\change-detection.py vectorize \
  --mask change_mask.tif --output change_polygons.geojson --min-area 500

输出 GeoJSON 或 Shapefile,含变化面积属性。

可视化

  • 变化强度:发散色阶(蓝=无变化,红=高变化)
  • 二值掩膜:在 RGB 合成图上叠加红色变化区域
  • CVA 方向:使用循环色阶(HSV)可视化角度
  • 对比:同时展示时相 1、时相 2 和变化图

引用格式

@software{change_detection,
  author  = {ruiduobao},
  title   = {Change Detection Tool},
  url     = {https://github.com/ruiduobao/change-detection},
  version = {0.1.0},
  year    = {2024},
}

故障排除

错误原因解决方案
ConnectionError网络问题检查网络,重试
HTTP 429速率限制等待 60 秒后重试
ValueError无效输入检查参数格式
无输出未检测到变化降低阈值或检查输入
ModuleNotFoundError缺少依赖运行 pip install
配准伪影影像未对齐先配准再检测
条带状输出云影应用云掩膜

数据来源

本地栅格处理 — 需要两幅配准好的 GeoTIFF 影像。

Top skills in this category