NDVI、对集合应用函数、质量镶嵌

之前,您学习了如何通过执行如下操作来获取单个 Landsat 场景,其中 l8 和 point 是表示 Landsat 8 TOA 集合和感兴趣区域几何图形的导入内容:

代码编辑器 (JavaScript)

// Define a point of interest. Use the UI Drawing Tools to import a point
// geometry and name it "point" or set the point coordinates with the
// ee.Geometry.Point() function as demonstrated here.
var point = ee.Geometry.Point([-122.292, 37.9018]);

// Import the Landsat 8 TOA image collection.
var l8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA');

// Get the least cloudy image in 2015.
var image = ee.Image(
  l8.filterBounds(point)
    .filterDate('2015-01-01', '2015-12-31')
    .sort('CLOUD_COVER')
    .first()
);

现在,假设您要根据 Landsat 影像计算归一化植被指数 (NDVI) 影像。植被会反射电磁光谱中近红外 (NIR) 部分的光,并吸收红色部分的光(详细了解植被的 NIR 反射率)。NDVI 使用此值来创建一个大致反映像素处发生的光合作用活动的单个值。计算公式为 (NIR - red) / (NIR + red)。这会产生一个介于 1 和 -1 之间的数字,其中光合作用活动较高的像素具有较高的 NDVI。以下是在 Earth Engine 中计算 NDVI 的一种方法:

代码编辑器 (JavaScript)

// Compute the Normalized Difference Vegetation Index (NDVI).
var nir = image.select('B5');
var red = image.select('B4');
var ndvi = nir.subtract(red).divide(nir.add(red)).rename('NDVI');

// Display the result.
Map.centerObject(image, 9);
var ndviParams = {min: -1, max: 1, palette: ['blue', 'white', 'green']};
Map.addLayer(ndvi, ndviParams, 'NDVI image');

结果应类似于图 8。请注意,我们使用您在上一节中了解到的 select() 函数来获取近红外和红色波段,然后使用您之前在 Image 数学部分中看到的图像数学运算符来计算 NDVI。最后,使用调色板显示图片。在这里,我们在调色板中使用了颜色名称,而不是十六进制字符串。(如需了解详情,请参阅这篇关于 CSS 颜色的外部参考文档。)

Tutorial_api_08_ndvi.png
图 8. 单个 Landsat 场景的 NDVI。蓝色表示 NDVI 较低,绿色表示 NDVI 较高。

归一化差值运算在遥感中非常普遍,因此 ee.Image 上有一个快捷函数,可用于简化上一个示例中的代码:

代码编辑器 (JavaScript)

var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');

将函数映射到集合

现在,假设您想为图片集中的每张图片添加 NDVI。在 Earth Engine 中,实现此目的的方法是对集合map()一个函数。请勿将 map() 与 Map 对象混淆。前者是集合上的一个方法,它在并行计算意义上使用 map,将函数应用于集合中的每个元素。该函数定义将应用于集合中每个元素的操作。您已在 JavaScript 教程中了解了一个简单的函数,现在我们将创建一个包含 Earth Engine 功能的函数。例如,将前面的 NDVI 代码复制到一个函数中,该函数会返回包含 NDVI 波段的输入图片:

代码编辑器 (JavaScript)

var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
  return image.addBands(ndvi);
};

// Test the addNDVI function on a single image.
var ndvi = addNDVI(image).select('NDVI');

此代码在计算单张图片的 NDVI 时可能效率不高,但此函数可用作 map() 的参数,以便为集合中的每张图片添加 NDVI 波段。通常,最好先在单张图片上测试函数,以确保函数按预期运行。在单张图片上测试函数并确定其符合预期后,您可以将其映射到集合:

代码编辑器 (JavaScript)

var withNDVI = l8.map(addNDVI);

为了验证此操作是否确实为该集合中的每张图片都添加了 NDVI 波段,您可以将 withNDVI 集合添加到地图中,然后使用 Inspector(检查器)标签页查询随机位置。您应该会注意到,集合中的每个图片现在都有一个名为 NDVI 的波段。

制作最绿像素合成影像

现在,您已经创建了一个图片集合,其中每张图片都有一个 NDVI 波段,我们可以探索一种新的合成方法:qualityMosaic()。您可能已经注意到 Landsat 路径之间存在不连续性,即使在中值像素合成中也是如此。造成这种情况的部分原因可能是物候差异,因为相邻路径中的图像是在不同时间(具体来说,相隔 8 天)收集的。尽量减少这种影响的一种方法是,尝试在合成图像中设置大致相同物候阶段的像素值,例如植物绿度最高的时期(叶片长出且具有光合活性)。如果我们将最大绿度定义为最大 NDVI,则可以使用 qualityMosaic() 创建一个合成图像,其中每个像素都包含集合中的最大 NDVI 像素。现在,您可以使用 withNDVI 集合中添加的 NDVI 波段:

代码编辑器 (JavaScript)

// Make a "greenest" pixel composite.
var greenest = withNDVI.qualityMosaic('NDVI');

// Display the result.
var visParams = {bands: ['B4', 'B3', 'B2'], max: 0.3};
Map.addLayer(greenest, visParams, 'Greenest pixel composite');

此代码的结果应类似于图 9。将图 9 与图 6 中所示的中位数合成图像进行比较,可以观察到最绿像素合成图像确实要绿得多。不过,仔细检查水体应该会发现一个不同的问题。具体而言,水体现在看起来有些浑浊。这是因为 qualityMosaic() 方法的工作方式:在每个位置,系统都会检查整个时间序列,并将 NDVI 波段中具有最大值的像素设置为合成值。由于云层上的 NDVI 高于水面,因此水域会显示多云像素,而植被区域则全部显示为绿色,因为当像素中的植被进行光合作用时,NDVI 最高。

Tutorial_api_09_greenest.png
图 9. Landsat 8 绿度最高像素合成。

现在,您已经了解了在 Earth Engine 中合成和拼接图像的几种方法。您可以根据按时间和地点过滤的图片或集合中的所有图片,制作近期值、中位数或最绿像素合成图像。您已了解如何对图像进行计算并提取信息。下一页介绍了从 Earth Engine 获取信息的方法,例如以图表或数据集的形式导出到 Google 云端硬盘文件夹。