将 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');
此合成图像存在的一个问题是,其中布满了云。您不必只获取集合中的最后一个像素(当您将集合添加到地图时,Earth Engine 会隐式对其调用 mosaic()
),而是可以缩减 ImageCollection
(详细了解如何缩减影像集合)。
使用 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()
作为实参。在代码编辑器的文档标签页中查看 ee.Reducer
软件包,即可查看所有 Earth Engine 归约器的列表。在为图片集合选择化简器时,请注意输出是图片,因此输出为非数值的化简器(例如 histogram
或 toList
化简器)不适用于图片集合。

缩小中值合成图后,您应该会看到类似图 6 的内容。这应该比您之前制作的近期价值复合值看起来好得多。此时,不妨退一步,考虑一下为了获得该中值复合值,我们做了哪些工作。Earth Engine 已加载美国大陆的整个 Landsat 8 集合,并计算了每个像素的中位数。这可是大量数据!当然,您可以先过滤集合,然后计算年度中位数, 就像您之前所做的那样。重点是,如果您必须下载所有这些影像并制作此合成影像,那将是一项大工程。借助 Earth Engine,您可以在几秒钟内获得结果!
如需详细了解合成和镶嵌,请点击此处。
遮盖
虽然中值合成比近值合成有所改进,但您可能仍需要遮盖图像的某些部分。遮盖图片中的像素会使这些像素变为透明,并将其从分析中排除。图像中每个波段的每个像素都有一个掩码。遮罩值为 0 或更低值的像素将是透明的。掩码值大于 0 的对象将进行渲染。可以使用类似 image1.mask(image2)
的调用来设置图片的遮罩。此调用会获取 image2
的值,并将其作为 image1
的掩码。image2
中值为 0 的任何像素在 image1
中都将变为透明。
例如,假设您想遮盖中值合成中的所有水像素。可以使用 Hansen 等人 (2013) 描述的数据集(位于 Earth Engine 数据目录中)创建水体掩码。(如需详细了解 Hansen 等人的数据集,请参阅本教程。)在此数据集中,水的值为 2,陆地的值为 1,“无数据”的值为 0。使用一些逻辑来创建在没有陆地的地方具有零值的遮罩图片:
代码编辑器 (JavaScript)
// Load or import the Hansen et al. forest change dataset. var hansenImage = ee.Image('UMD/hansen/global_forest_change_2015'); // 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
并不完全正确,因为它还包含一些无数据像素,但在当前的制图背景下是可以的。接下来,使用“水”本身来遮盖“水”。这样会生成一个图像,其中所有水像素均为 1,其他所有内容都被遮盖。最后一步是使用 mosaic()
合并图片。由于 mosaic()
适用于图片集合,因此我们将要合并的图片列表传递给图片集合构造函数,然后在最后一步调用 mosaic()
。该列表中的图片顺序非常重要。具体而言,输出图片将包含输入集合中图片堆栈的最后一个未被遮盖的像素。在这种情况下,这是可行的,因为水层是集合中的最后一张(最上层)图片,并且仅包含出现水的位置的未遮盖像素。
请注意,集合中的图片是可视化图片。当您对图片调用 visualize()
时,系统会根据您传入的可视化参数将图片转换为 3 波段 8 位图片。默认的可视化参数适用于 3 波段 8 位图像,因此在向地图添加图像时,您无需提供可视化参数。结果应如图 7 所示。

至此,您已了解如何将影像集合直观呈现为近期值合成影像、如何使用化简器合成影像集合,以及如何通过遮盖和镶嵌影像集合来制作自定义合成影像。在下一页中,了解如何向集合中的每张图片添加植被指数,以及如何使用该指数制作“最绿像素”合成图。