GEE&Python-demo:利用Sentinel-监测北京奥林匹克森林公园年NDVI变化(附Python版)

GEE&Python-demo:利用Sentinel-监测北京奥林匹克森林公园年NDVI变化(附Python版)

一、项目背景植被覆盖度是衡量城市生态健康的重要指标。NDVI(归一化植被指数)利用植物在近红外波段的高反射和红光波段的强吸收特性,广泛用于植被监测。北京奥林匹克森林公园作为城市绿肺,其植被年际变化能反映城市生态政策与气候影响。传统遥感处理繁琐,而Google Earth Engine(GEE)提供了强大的云端计算能力。本文通过GEE JavaScript API和Python(geemap库)双语言实现,展示如何用Sentinel-2时间序列分析奥林匹克森林公园的NDVI年变化。## 二、技术栈与数据- 数据源 :ESA Sentinel-2 MSI Level-2A(已大气校正)- 分析区域 :北京奥林匹克森林公园(北五环,中心点约39.993°N, 116.390°E)- 时间范围 :2019-2023年每年6-8月(生长旺季)- 核心工具 : - GEE JavaScript Code Editor - Python + geemap + earthengine-api## 三、GEE JavaScript版:快速原型验证以下代码在GEE Code Editor中运行。我们首先加载北京奥林匹克森林公园的矢量边界(使用GEE内置的FAO数据集或手动绘制),然后逐年计算NDVI平均值。javascript// 1. 定义研究区域(手动绘制或从资产导入)var roi = ee.FeatureCollection('FAO/GAUL/2015/level2') .filter(ee.Filter.eq('ADM2_NAME', 'Chaoyang')) .filter(ee.Filter.eq('ADM1_NAME', 'Beijing')) .geometry(); // 简化:实际需手动裁剪至奥林匹克公园区域// 更精确做法:直接绘制多边形(示例用矩形近似)var park = ee.Geometry.Rectangle([116.380, 39.985, 116.400, 40.005]);// 2. 定义时间序列函数function calcAnnualNDVI(year) { var startDate = ee.Date.fromYMD(year, 6, 1); var endDate = ee.Date.fromYMD(year, 8, 31); // 加载Sentinel-2影像集,去云处理 var s2 = ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(park) .filterDate(startDate, endDate) .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20)) .map(function(image) { // 计算NDVI并添加波段 var ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI'); return image.addBands(ndvi).clip(park); }); // 取中值合成(减少云噪) var median = s2.median(); return median.select('NDVI').set('year', year);}// 3. 逐年计算并输出var years = ee.List.sequence(2019, 2023);var ndviCollection = ee.ImageCollection.fromImages( years.map(function(y) { return calcAnnualNDVI(y); }));// 4. 打印各年平均值var means = ndviCollection.map(function(img) { var mean = img.reduceRegion({ reducer: ee.Reducer.mean(), geometry: park, scale: 10, maxPixels: 1e9 }); return ee.Feature(null, { year: img.get('year'), meanNDVI: mean.get('NDVI') });});print('Annual NDVI means:', means);Export.table.toDrive({ collection: means, description: 'OlympicPark_NDVI_Annual'});关键点注释 :- 使用normalizedDifference直接计算NDVI = (B8-B4)/(B8+B4)- 通过中值合成避免单景影像的云遮挡- 逐年reduceRegion获取区域统计值## 四、Python版:geemap自动化工作流Python版更适合批量处理和可视化。使用geemap库可以无缝对接GEE,无需前端界面。pythonimport eeimport geemapimport pandas as pdimport matplotlib.pyplot as plt# 初始化GEE(需先认证)ee.Authenticate()ee.Initialize(project='your-project-id')# 定义区域(同上,使用矩形代替)park = ee.Geometry.Rectangle([116.380, 39.985, 116.400, 40.005])def get_annual_ndvi(year): """获取指定年份的NDVI中值合成""" start = f'{year}-06-01' end = f'{year}-08-31' s2 = (ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(park) .filterDate(start, end) .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20)) .map(lambda img: img.clip(park))) # 计算NDVI并合成 def add_ndvi(img): ndvi = img.normalizedDifference(['B8', 'B4']).rename('NDVI') return img.addBands(ndvi) ndvi_coll = s2.map(add_ndvi).select('NDVI') median_ndvi = ndvi_coll.median() # 区域统计 mean_dict = median_ndvi.reduceRegion( reducer=ee.Reducer.mean(), geometry=park, scale=10, maxPixels=1e9 ) return mean_dict.getInfo()['NDVI']# 逐年计算years = list(range(2019, 2024))ndvi_values = []for yr in years: try: val = get_annual_ndvi(yr) ndvi_values.append(val) print(f'{yr} NDVI均值: {val:.3f}') except Exception as e: print(f'{yr} 计算失败: {e}') ndvi_values.append(None)# 可视化plt.figure(figsize=(10, 5))plt.plot(years, ndvi_values, 'o-', color='green', linewidth=2)plt.title('北京奥林匹克森林公园年均NDVI变化 (2019-2023)')plt.xlabel('年份')plt.ylabel('NDVI均值')plt.grid(True, linestyle='--', alpha=0.7)plt.xticks(years)plt.ylim(0.3, 0.7) # 根据实际情况调整# 添加趋势线import numpy as npvalid = [(y, v) for y, v in zip(years, ndvi_values) if v is not None]if len(valid) > 2: x = [p[0] for p in valid] y = [p[1] for p in valid] z = np.polyfit(x, y, 1) p = np.poly1d(z) plt.plot(x, p(x), 'r--', alpha=0.5, label='趋势线') plt.legend()plt.tight_layout()plt.savefig('olympic_park_ndvi_trend.png', dpi=300)plt.show()重点说明 :- 使用geemap.CenterMap可定位到奥林匹克公园(未在代码中展示)- 通过reduceRegionscale=10匹配Sentinel-2原始分辨率- 异常处理确保单年失败不影响整体流程## 五、结果解读与可视化运行上述代码后,我们将获得类似下表的数据(示例值):| 年份 | 平均NDVI ||------|----------|| 2019 | 0.532 || 2020 | 0.548 || 2021 | 0.561 || 2022 | 0.557 || 2023 | 0.543 |趋势分析 :- 2019-2021年NDVI呈现上升趋势,可能与公园植被成熟及养护提升有关- 2022年略有下降,可能与极端高温干旱有关- 2023年继续小幅下降,需结合降雨数据分析Python版生成的趋势图如下图所示(此处为文字描述,实际运行会生成PNG文件)。## 六、扩展与调优1. 更精确的边界 :使用OpenStreetMap或高德API获取奥林匹克森林公园实际轮廓。2. 时间窗口优化 :可改为5-10月(生长季)或逐月分析。3. 去云增强 :使用ee.Algorithms.Landsat.simpleComposite或S2云概率波段。4. 多指数对比:同时计算EVI、NDWI等指数。## 七、总结本文通过GEE JavaScript和Python双语言实现,完整演示了利用Sentinel-2监测北京奥林匹克森林公园年NDVI变化的方法。核心步骤包括:1. 定义研究区域并过滤影像2. 计算NDVI并合成年际中值3. 区域统计提取均值4. 结果可视化与趋势分析GEE极大地降低了遥感数据处理门槛,而Python版提供了更灵活的可视化和自动化能力。实际应用中,建议结合地面观测数据进行验证,并注意影像云量滤波和尺度效应对结果的影响。整套代码可直接迁移至其他城市公园或自然保护区,为城市生态监测提供数据支撑。

相关推荐
C++、Java和Python的菜鸟1 小时前
第9章 后端Web进阶(AOP)
java·开发语言·前端
软萌萌的12 小时前
Python零基础从入门到精通详细教程-数据类型
开发语言·windows·python
东北赵四2 小时前
关于Java泛型的知识点及其相关面试题
java·windows·python
姓蔡小朋友2 小时前
Java线程并发
java·开发语言·python
海带紫菜菠萝汤2 小时前
免费在线翻译器横评:2026年6款PDF翻译工具对比
人工智能·python·pdf
我星期八休息2 小时前
扩展— TCP 全连接队列与 tcpdump 抓包
linux·服务器·开发语言·前端·网络·tcp/ip·tcpdump
小小代码狗2 小时前
PHP 常用函数与变量参考文档
开发语言·安全·php
编程阿峰3 小时前
Python 环境配置(二)安装jupyter、matplotlib、numpy库
开发语言·python·jupyter·numpy·matplotlib
AC赳赳老秦3 小时前
CSDN 技术社区数据采集:OpenClaw 抓取公开技术热帖,生成领域技术热点周报
java·大数据·前端·数据库·python·php·openclaw