将 Landsat 8 TOA 反射率集合加载到名为 l8 的变量中后,您会看到以下代码会生成近期值合成:
代码编辑器 (JavaScript)
var l8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA'); var landsat2016 = l8.filterDate('2016-01-01', '2016-12-31'); Map.addLayer(landsat2016, visParams, 'l8 collection');
此合成图像存在的问题之一是,其中有很多云。您可以缩减 ImageCollection,而不是仅获取集合中的最后一个像素(当您向地图添加集合时,Earth Engine 会隐式调用 mosaic())(详细了解如何缩减图片集合)。
使用 Reducer 进行组合
您首先了解了用于获取图片区域统计信息的 reducer。这是空间缩减。如果图片集合表示一段时间内的图片,则将图片集合缩减为图片是时态缩减。您使用的 Reducer 类型决定了 Earth Engine 如何处理重叠像素。Landsat 8 每 16 天访问一次地球上的同一地点。这意味着,在 6 个月的时间内,大约会有 12 张图片(在场景重叠的地方会有更多图片)。地图上的每个像素都派生自一堆像素,其中每个像素来自所显示集合中的每张图片。
如果只是将集合添加到地图中,则会选择最新像素,即堆栈中最新图片的像素。您可以使用 Earth Engine 缩减器来更改此行为。例如,您可以指示 Earth Engine 选择堆栈中的中位数,而不是从堆栈中获取最新像素。这样做的好处是去除了云(具有高值)和阴影(具有低值)。使用中位数缩减器缩减图片集合时,合成值是每个波段在一段时间内的中位数。例如,使用 2016 年的 Landsat 场景:
代码编辑器 (JavaScript)
// Get the median over time, in each band, in each pixel. var median = l8.filterDate('2016-01-01', '2016-12-31').median(); // Make a handy variable of visualization parameters. var visParams = {bands: ['B4', 'B3', 'B2'], max: 0.3}; // Display the median composite. Map.addLayer(median, visParams, 'median');
此代码中的新内容是应用于图片集的 median() 方法。
与过滤方法一样,这也是一种快捷方式,可用于在图片集合上执行更通用的 reduce() 方法,该方法接受 ee.Reducer() 作为参数。如需查看所有 Earth Engine 缩减器的列表,请参阅代码编辑器文档标签页中的 ee.Reducer 软件包。在考虑为图片集合使用 reducer 时,请注意输出是图片,因此具有非数字输出的 reducer(例如 histogram 或 toList reducer)不适用于图片集合。
缩小中位数合成图像后,您应该会看到类似图 6 的内容。这应该比您之前创建的近期值合成图像看起来好得多。此时,有必要回顾一下,思考一下为了制作该中位数合成图像,我们做了哪些工作。Earth Engine 已加载美国大陆的整个 Landsat 8 集合,并计算了每个像素的中位数。这可是海量数据!当然,您可以先过滤集合, 就像您之前所做的那样,然后计算年度中位数。关键在于,如果您必须下载所有这些图像并制作此合成图像,那将是一个大项目。借助 Earth Engine,您可以在几秒钟内获得结果!
如需详细了解合成和拼接,请点击此处。
遮盖
虽然中位数合成图像比近期值合成图像有所改进,但您可能需要遮盖图像的某些部分。遮盖图片中的像素会使这些像素透明,并将其从分析中排除。图像每个波段中的每个像素都有一个掩膜。遮罩值为 0 或更低的值将透明。系统会渲染掩码值大于 0 的所有内容。图片的遮罩通过 image1.mask(image2) 等调用进行设置。此调用会获取 image2 的值,并将其作为 image1 的掩码。image2 中值为 0 的任何像素都将在 image1 中变为透明。
例如,假设您想遮盖中值合成中的所有水像素。您可以使用 Hansen 等人 (2013) 描述的数据集(位于 Earth Engine Data Catalog 中)创建水体掩膜。(如需详细了解 Hansen 等人的数据集,请参阅此教程。)在此数据集中,水的值为 2,陆地的值为 1,“无数据”的值为 0。使用一些逻辑来创建蒙版图片,其中没有陆地的位置值为零:
代码编辑器 (JavaScript)
// Load or import the Hansen et al. forest change dataset. var hansenImage = ee.Image('UMD/hansen/global_forest_change_2025_v1_13'); // Select the land/water mask. var datamask = hansenImage.select('datamask'); // Create a binary mask. var mask = datamask.eq(1); // Update the composite mask with the water mask. var maskedComposite = median.updateMask(mask); Map.addLayer(maskedComposite, visParams, 'masked');
此代码中有一些新内容值得详细说明。首先,select() 函数可用于从图片中提取感兴趣的波段。在这里,我们仅选择我们关注的频段:datamask。下一个新内容是逻辑运算符 eq(),它代表“等于”。我们使用 eq(1) 创建一个二值图像,其中 datamask 波段中值不为 1 的所有像素(即水体或无数据的像素)在生成的图像中值都为 0。
经过此遮盖处理后,中位数合成影像中位于陆地上的所有像素(根据 Hansen 等人的数据集)都可见,但位于水体(或无数据)上的像素是透明的,并且会从您对 maskedComposite 图像进行的任何分析中排除。
拼接
通过结合使用图片集合、逻辑运算符、遮盖和合成等概念,您可以获得有趣的制图结果。例如,假设您希望图像中的陆地像素以真彩色显示,而所有其他像素以蓝色显示,则可以执行以下操作:
代码编辑器 (JavaScript)
// Make a water image out of the mask. var water = mask.not(); // Mask water with itself to mask all the zeros (non-water). water = water.mask(water); // Make an image collection of visualization images. var mosaic = ee.ImageCollection([ median.visualize(visParams), water.visualize({palette: '000044'}), ]).mosaic(); // Display the mosaic. Map.addLayer(mosaic, {}, 'custom mosaic');
这段代码包含许多操作,我们来剖析一下。首先,我们使用 not() 逻辑运算符来反转之前创建的掩码。具体而言,not() 会将所有零转换为 1,将所有非零转换为零。将该变量称为 water 并不完全正确,因为它还包含一些无数据像素,但在当前的制图上下文中,这样称呼是可以的。接下来,使用“water”本身对其进行遮盖。这样会生成一张图片,其中所有水体像素均为 1,其他所有像素均被遮盖。最后一步是使用 mosaic() 组合图片。由于 mosaic() 适用于图片集合,因此我们会将要合并的图片列表传递给图片集合构造函数,然后调用 mosaic() 作为最后一步。该列表中图片的顺序非常重要。具体而言,输出图片将包含输入集合中图片堆栈中的最后一个未遮盖像素。在本例中,这种方法之所以有效,是因为水层是集合中的最后一张(最顶层)图片,并且仅包含水体所在位置的未遮盖像素。
请注意,集合中的图片是可视化图片。当您对图片调用 visualize() 时,系统会根据您传入的可视化参数将其转换为 3 波段 8 位图片。默认可视化参数适用于 3 波段、8 位图像,因此在将图像添加到地图时,您无需指定可视化参数。结果应如图 7 所示。
至此,您已经了解了如何将图片集合可视化为近期值合成,如何使用化简器合成图片集合,以及如何通过对图片集合进行遮盖和拼接来制作自定义合成。在下一页中,您将了解如何向集合中的每张图片添加植被指数,并使用该指数制作“最绿像素”合成图像。