基于 GEE 的 2010—2020 年归一化植被指数 NDVI 与核植被指数 kNDVI 年度变化分析

ops/2025/4/2 2:24:42/

目录

1 前言

2 代码解析

2.1 定义感兴趣区域并居中显示

2.2 加载数据集并过滤

2.3 定义 kNDVI 计算函数

2.4 生成年度影像集合

2.5 计算 NDVI 和 kNDVI 的时间序列

2.6 可视化时间序列

2.7 导出影像到 Google Drive

3 完整代码

4 运行结果


1 前言

在遥感领域,归一化植被指数(NDVI)是一个广泛使用的指标,用于评估植被覆盖和健康状况。然而,随着研究的深入,基于 NDVI 的改进指标,如核归一化植被指数(kNDVI),逐渐受到关注。本篇博客将详细介绍如何使用 Google Earth Engine (GEE) 的 JavaScript API,通过一段代码实现 NDVI 和 kNDVI 的计算、可视化以及数据导出。我们将逐步解析代码,帮助读者理解其逻辑和应用场景。

NDVI 是基于红光和近红外波段反射率计算的植被指数,其值范围在 -1 到 1 之间,反映了植被的生长状态。kNDVI 是 NDVI 的非线性变体,通过引入双曲正切函数(tanh)对 NDVI 进行变换,使其对高植被覆盖区域的敏感性更强。这在研究长期植被动态或高密度植被区时尤为有用。

主要内容:

  1. 定义一个感兴趣区域(ROI)。
  2. 从 Landsat 数据集中提取 2010-2020 年的 NDVI 数据。
  3. 计算 kNDVI。
  4. 生成 NDVI 和 kNDVI 的年度时间序列图。
  5. 将结果导出到 Google Drive。

2 代码解析

2.1 定义感兴趣区域并居中显示

var roi = geometry;
Map.centerObject(roi, 6);
  • roi:用户定义的几何区域,通常在 GEE 编辑器中通过绘图工具手动指定。
  • Map.centerObject(roi, 6):将地图视图居中于 roi,缩放级别为 6。这一步确保我们能在 GEE 的交互式地图上直观查看研究区域。

2.2 加载数据集并过滤

var dataset = ee.ImageCollection('LANDSAT/COMPOSITES/C02/T1_L2_ANNUAL_NDVI').filterBounds(roi).filterDate('2010-01-01', '2020-12-31');
  • ee.ImageCollection:加载 Landsat 的年度 NDVI 合成数据集(LANDSAT/COMPOSITES/C02/T1_L2_ANNUAL_NDVI)。该数据集基于 Landsat Tier 1 Level 2 数据预计算了 NDVI。
  • .filterBounds(roi):过滤出与 roi 空间相交的影像。
  • .filterDate('2010-01-01', '2020-12-31'):限定时间范围为 2010 年至 2020 年。

2.3 定义 kNDVI 计算函数

function calculateKNDVI(NDVI) {return NDVI.pow(2).tanh().rename('kNDVI');
}
  • calculateKNDVI:一个自定义函数,用于计算 kNDVI。
  • NDVI.pow(2):将 NDVI 值平方。
  • .tanh():应用双曲正切函数,输出范围为 (-1, 1),增强高 NDVI 值的区分度。
  • .rename('kNDVI'):将结果波段重命名为 kNDVI。

2.4 生成年度影像集合

var years = ee.List.sequence(2010, 2020);var annualData = years.map(function(year) {var yearStr = ee.Number(year).format('%d');var image = dataset.filterDate(yearStr.cat('-01-01'), yearStr.cat('-12-31')).mean().clip(roi);var NDVI = image.select('NDVI').rename('NDVI');var kNDVI = calculateKNDVI(NDVI);return NDVI.addBands(kNDVI).set('year', year);
});var annualCollection = ee.ImageCollection(annualData);
  • ee.List.sequence(2010, 2020):生成 2010-2020 的年份列表。
  • .map(function(year) {...}):对每个年份执行操作:
    • yearStr.cat('-01-01') 和 yearStr.cat('-12-31'):构造每年的起止日期。
    • .filterDate().mean():过滤该年份数据并计算均值。
    • .clip(roi):裁剪到感兴趣区域。
    • NDVI.addBands(kNDVI):将 NDVI 和 kNDVI 合并为多波段影像。
    • .set('year', year):为影像添加年份属性。
  • ee.ImageCollection(annualData):将结果转为影像集合。

2.5 计算 NDVI 和 kNDVI 的时间序列

var ndviSeries = annualCollection.map(function(img) {var mean = img.select('NDVI').reduceRegion({reducer: ee.Reducer.mean(),geometry: roi,scale: 500,maxPixels: 1e13}).get('NDVI');return ee.Feature(null, {'year': img.get('year'), 'NDVI': mean});
});var kndviSeries = annualCollection.map(function(img) {var mean = img.select('kNDVI').reduceRegion({reducer: ee.Reducer.mean(),geometry: roi,scale: 500,maxPixels: 1e13}).get('kNDVI');return ee.Feature(null, {'year': img.get('year'), 'kNDVI': mean});
});
  • .reduceRegion():对指定波段(NDVI 或 kNDVI)在 roi 内计算均值。
    • reducer: ee.Reducer.mean():使用均值缩减器。
    • scale: 500:计算分辨率为 500 米。
    • maxPixels: 1e13:设置最大像素数,避免超出计算限制。
  • ee.Feature(null, {...}):将年份和均值封装为无几何信息的要素,用于后续绘图。

2.6 可视化时间序列

var ndviChart = ui.Chart.feature.byFeature(ndviSeries, 'year', ['NDVI']).setOptions({title: 'NDVI trend',hAxis: {title: 'Year'},vAxis: {title: 'NDVI'},lineWidth: 2,pointSize: 4,colors: ['green']});
print(ndviChart);var kndviChart = ui.Chart.feature.byFeature(kndviSeries, 'year', ['kNDVI']).setOptions({title: 'kNDVI trend',hAxis: {title: 'Year'},vAxis: {title: 'kNDVI'},lineWidth: 2,pointSize: 4,colors: ['blue']});
print(kndviChart);
  • ui.Chart.feature.byFeature:根据要素集合绘制折线图。
    • X 轴为 year,Y 轴为 NDVI 或 kNDVI。
  • .setOptions({...}):设置图表样式,包括标题、轴标签、线条宽度、点大小和颜色。
  • print():将图表输出到 GEE 控制台。

2.7 导出影像到 Google Drive

years.evaluate(function(yearList) {yearList.forEach(function(year) {var image = annualCollection.filter(ee.Filter.eq('year', year)).first();Export.image.toDrive({image: image.select('NDVI'),description: "NDVI_" + year,fileNamePrefix: "NDVI_" + year,scale: 500,region: roi,crs: "EPSG:4326",maxPixels: 1e13,folder: 'Annual_NDVI'});Export.image.toDrive({image: image.select('kNDVI'),description: "kNDVI_" + year,fileNamePrefix: "kNDVI_" + year,scale: 500,region: roi,crs: "EPSG:4326",maxPixels: 1e13,folder: 'Annual_kNDVI'});});
});
  • years.evaluate():将服务器端的年份列表转为客户端可用的 JavaScript 数组。
  • .forEach():对每个年份执行导出:
    • .filter().first():从集合中提取该年份的影像。
    • Export.image.toDrive():将 NDVI 和 kNDVI 影像分别导出。
      • scale: 500:分辨率为 500 米。
      • crs: "EPSG:4326":使用 WGS84 坐标系。
      • folder:分别存储在 Annual_NDVI 和 Annual_kNDVI 文件夹中。

3 完整代码

var roi = geometry;
Map.centerObject(roi, 6);var dataset = ee.ImageCollection('LANDSAT/COMPOSITES/C02/T1_L2_ANNUAL_NDVI').filterBounds(roi).filterDate('2010-01-01', '2020-12-31');function calculateKNDVI(NDVI) {return NDVI.pow(2).tanh().rename('kNDVI');
}var years = ee.List.sequence(2010, 2020);var annualData = years.map(function(year) {var yearStr = ee.Number(year).format('%d');var image = dataset.filterDate(yearStr.cat('-01-01'), yearStr.cat('-12-31')).mean().clip(roi);var NDVI = image.select('NDVI').rename('NDVI');var kNDVI = calculateKNDVI(NDVI);return NDVI.addBands(kNDVI).set('year', year);
});var annualCollection = ee.ImageCollection(annualData);var ndviSeries = annualCollection.map(function(img) {var mean = img.select('NDVI').reduceRegion({reducer: ee.Reducer.mean(),geometry: roi,scale: 500,maxPixels: 1e13}).get('NDVI');return ee.Feature(null, {'year': img.get('year'), 'NDVI': mean});
});var kndviSeries = annualCollection.map(function(img) {var mean = img.select('kNDVI').reduceRegion({reducer: ee.Reducer.mean(),geometry: roi,scale: 500,maxPixels: 1e13}).get('kNDVI');return ee.Feature(null, {'year': img.get('year'), 'kNDVI': mean});
});var ndviChart = ui.Chart.feature.byFeature(ndviSeries, 'year', ['NDVI']).setOptions({title: 'NDVI trend',hAxis: {title: 'Year'},vAxis: {title: 'NDVI'},lineWidth: 2,pointSize: 4,colors: ['green']});
print(ndviChart);var kndviChart = ui.Chart.feature.byFeature(kndviSeries, 'year', ['kNDVI']).setOptions({title: 'kNDVI trend',hAxis: {title: 'Year'},vAxis: {title: 'kNDVI'},lineWidth: 2,pointSize: 4,colors: ['blue']});
print(kndviChart);years.evaluate(function(yearList) {yearList.forEach(function(year) {var image = annualCollection.filter(ee.Filter.eq('year', year)).first();Export.image.toDrive({image: image.select('NDVI'),description: "NDVI_" + year,fileNamePrefix: "NDVI_" + year,scale: 500,region: roi,crs: "EPSG:4326",maxPixels: 1e13,folder: 'Annual_NDVI'});Export.image.toDrive({image: image.select('kNDVI'),description: "kNDVI_" + year,fileNamePrefix: "kNDVI_" + year,scale: 500,region: roi,crs: "EPSG:4326",maxPixels: 1e13,folder: 'Annual_kNDVI'});});
});

4 运行结果

点击RUN即可下载数据
NDVI趋势折线图
kNDVI趋势折线图

http://www.ppmy.cn/ops/171231.html

相关文章

三极管放大信号的奥秘:它能放大直流信号吗?

点击下面图片带您领略全新的嵌入式学习路线 🔥爆款热榜 88万阅读 1.6万收藏 文章目录 **引言:为什么三极管如此重要?****一、三极管为什么能放大信号?****1. 三极管的基本结构****2. 放大原理:以小控大****3. 信号放…

Windows 图形显示驱动开发-WDDM 2.4功能-GPU 半虚拟化(十二)

DxgkDdiQueryAdapterInfo 更新 DXGKARG_QUERYADAPTERINFO 结构已更新,以包括以下字段以支持半虚拟化: 添加了 Flags 成员,允许 Dxgkrnl 指示以下内容: 它将 VirtualMachineData 设置为指示调用来自 VM。它将 SecureVirtualMach…

【C++】右值引用与完美转发

目录 一、右值引用: 1、左值与右值: 2、左值引用和右值引用: 二、右值引用的使用场景: 1、左值引用的使用场景: 2、右值引用的使用场景: 移动构造 移动赋值 三、完美转发: 1、万能引用…

安卓的布局方式

一、RelativeLayout 相对布局 特点:每个组件相对其他的某一个组件进行定位。 (一)主要属性 1、设置和父组件的对齐: alignParentTop : 设置为true,代表和父布局顶部对齐。 其他对齐只需要改变后面的Top为 Left、Right 或者Bottom&…

LangChain缓冲记忆组件的使用与解析

作为LangChain中使用最频繁的基础记忆组件,缓冲记忆类采用原生数据处理机制,主要提供以下四种实现: 一、ConversationBufferMemory(全量缓冲记忆) 功能特性:基础型记忆存储实现逻辑:完整存储所…

基础认证-单选题(一)

单选题 1、下列关于request方法和requestlnStream方法说法错误的是(C) A 都支持取消订阅响应事件 B 都支持订阅HTTP响应头事件 C 都支持HttpResponse返回值类型 D 都支持传入URL地址和相关配置项 2、如需修改Text组件文本的透明度可通过以下哪个属性方法进行修改 (C) A dec…

Appium中元素定位之一组元素定位API

应用场景 和定位一个元素相同&#xff0c;但如果想要批量的获取某个相同特征的元素&#xff0c;使用定位一组元素的方式更加方便 在 Appium 中定位一组元素的 API 与定位单个元素的 API 类似&#xff0c;但它们返回的是一个元素列表&#xff08;List<MobileElement>&am…

【LVS】负载均衡群集部署(DR模式)

部署前IP分配 DR服务器&#xff1a;192.168.166.101 vip&#xff1a;192.168.166.100 Web服务器1&#xff1a;192.168.166.104 vip&#xff1a;192.168.166.100 Web服务器2&#xff1a;192.168.166.107 vip&#xff1a;192.168.166.100 NFS服务器&#xff1a;192.168.166.108 …