GEE代码学习 day15

第十二章 过滤、映射、减少

在 Earth Engine 中筛选图片集合

FilterDate 此选项将 ImageCollection 作为输入,并返回其成员满足指定日期条件的 ImageCollection。

var imgCol = ee.ImageCollection('LANDSAT/LT05/C02/T1_L2'); 
// How many Tier 1 Landsat 5 images have ever been collected? 
print("All images ever: ", imgCol.size()); 
// A very large number  
// How many images were collected in the 2000s? 
var startDate = '2000-01-01';
var endDate = '2010-01-01';  
var imgColfilteredByDate = imgCol.filterDate(startDate, endDate); 
print("All images 2000-2010: ", imgColfilteredByDate.size()); 
// A smaller (but still large) number

FilterBounds 可能只有靠近感兴趣地点的图像才对您有用,类似于牛奶示例。正如第 I 部分中首次介绍的那样,filterBounds 将 ImageCollection 作为输入,并返回其图像围绕指定位置的 ImageCollection。如果我们获取按日期筛选的 ImageCollection,然后按边界筛选它,我们将已将集合筛选到指定日期间隔内指定点附近的那些图像。使用下面的代码,我们将计算 2000 年代初第 2 章首次访问的上海附近的图像数量:

var ShanghaiImage = ee.Image( 'LANDSAT/LT05/C02/T1_L2/LT05_118038_20000606');
Map.centerObject(ShanghaiImage, 9);  
var imgColfilteredByDateHere = imgColfilteredByDate.filterBounds(Map .getCenter());
print("All images here, 2000-2010: ", imgColfilteredByDateHere .size()); // A smaller number

Filter by Other Image Metadata:正如第 4 章中首次解释的那样,图像的日期和位置是与每张图像一起存储的特征。影像处理中的另一个重要因素是云覆盖,这是为许多集合(包括 Landsat 和 Sentinel-2 集合)中的每个影像计算的影像级别值。总体云度分数可能存储在不同数据集中的不同元数据标签名称下。例如,对于 Sentinel-2,此总体云度分数存储在 CLOUDY_PIXEL_PERCENTAGE 元数据字段中。对于 Landsat 5(在本例中使用的 ImageCollection),图像级别的云度得分使用标签 CLOUD_COVER 进行存储。如果您不熟悉如何查找此信息,这些技能首先将在第 I 部分中介绍。

在这里,我们将访问刚刚使用 filterBounds 和 filterDate 构建的 ImageCollection,然后使用 filterMetadata 函数按图像级别的云覆盖分数进一步筛选图像。接下来,让我们删除任何混浊度为 50% 或更高的图像。正如后续章节中将介绍的,使用每像素混浊度信息时,如果您认为混浊图像中的某些值可能有用,则可能需要在实际研究中保留这些图像。现在,为了说明过滤概念,我们只保留图像级云量值表明云覆盖率低于 50% 的图像。在这里,我们将获取已按 bounds 和 date 过滤的集合,并使用云百分比将其进一步过滤到新的 ImageCollection 中。将此行添加到脚本中,以按云度进行筛选,并将大小打印到控制台。

var L5FilteredLowCloudImages = imgColfilteredByDateHere  
                               .filterMetadata('CLOUD_COVER', 'less_than', 50); 
print("Less than 50% clouds in this area, 2000-2010", L5FilteredLowCloudImages.size()); // A smaller number

Filtering in an Efficient Order 对于要使用 filterBounds 的非全局空间组件的问题,首先执行空间筛选是最有效的。在下面的代码中,您将看到您可以 “链接” filter 命令,然后从左到右执行这些命令。下面,我们以相同的顺序链接过滤器如您上面指定的那样。请注意,它提供的 ImageCollection 大小与一次应用一个滤镜时的大小相同。

var chainedFilteredSet = imgCol.filterDate(startDate, endDate) 
                               .filterBounds(Map.getCenter()) 
                               .filterMetadata('CLOUD_COVER', 'less_than', 50); 
print('Chained: Less than 50% clouds in this area, 2000-2010', chainedFilteredSet.size());

在下面的代码中,我们以更高效的顺序链接过滤器,首先实现 filterBounds。这也会提供与以较低效率顺序应用滤镜时相同的 ImageCollection 大小,无论滤镜是否链接。

var efficientFilteredSet = imgCol.filterBounds(Map.getCenter()) 
                                 .filterDate(startDate, endDate) 
                                 .filterMetadata('CLOUD_COVER', 'less_than', 50); 
print('Efficient filtering: Less than 50% clouds in this area, 2000-2010', efficientFilteredSet.size());

对于图像数量,两组链接的操作中的每一组都将给出与之前相同的结果。虽然二阶效率更高,但对于这个非常小的示例,这两种方法都可能大致同时将答案返回给代码编辑器。在较大的问题中,运算顺序最为重要,因为在这些问题中,您可能会遇到仔细管理内存的挑战。与首先在地理上缩小范围的牛奶示例中一样,在 Earth Engine 中,最好先使用 filterBounds 对过滤器进行排序,然后按特异性递减的顺序对元数据过滤器进行排序。

在 Earth Engine 中对图像集合进行映射

在第 9 章中,我们以非常小的步骤计算了增强型植被指数 (EVI),以说明卫星图像上的波段运算。在该章中,代码在单个图像上调用了一次。如果我们想以相同的方式计算整个 ImageCollection 的每张图像的 EVI,该怎么办?在这里,我们使用 key 工具。在开始编写 EVI 功能之前,值得注意的是,在基于云的遥感过程中,“map”一词在多个设置中都会遇到,能够区分用途很重要。一个好的理解方式是,“map” 在 Earth Engine 中可以充当动词或名词。“map” 作为名词有两种用法。我们可以随意地提到“地图”,或者更准确地说,指的是“地图面板”;这些术语是指图像在代码接口中的显示位置。第二种方式 “map” 用作名词,指的是 Earth Engine 对象,该对象具有可以调用的函数。这方面的示例是熟悉的 Map.addLayer 和 Map.setCenter。在打算使用该词的地方,它将以紫色文本显示,并在代码编辑器中大写。我们在这里讨论的是 .map 作为动词的使用,表示在一组上重复执行一组操作的想法。这通常称为 “映射集”。

要在整个 ImageCollection 上有效地映射一组给定的操作,需要以特定方式设置处理。熟悉其他编程语言的用户可能希望看到“循环”代码来执行此操作,但在 Earth Engine 中,处理并非完全以这种方式完成。相反,我们将创建一个函数,然后将其映射到 ImageCollection 上。首先,设想创建一个只接受一个参数的函数,即 ee。图像。然后,该函数被设计为对输入 ee 执行一组指定的操作。Image 的 URL,然后重要的是,返回一个 ee。Image 作为函数的最后一步。当我们将在下面说明的 ImageCollection 上映射该函数时,效果是我们从 ImageCollection 开始,对每个图像执行操作,并接收处理后的 ImageCollection 作为输出。

我们可以创建哪些类型的函数?例如,您可以想象一个函数获取一张图像并返回一个图像,其像素的值为 1,其中给定波段的值低于特定阈值,否则为 0。映射此函数的效果将是图像的整个 ImageCollection,其中 0 和 1 表示每个图像上的测试结果。或者,您可以想象一个函数计算一个复杂的自定义索引,并发回每个像素计算的该索引的图像。

在这里,我们将创建一个函数来计算任何输入 Landsat 5 影像的 EVI,并返回为每个像素计算索引的单波段影像。将下面的函数定义复制并粘贴到 Code Editor 中,将其添加到上一节中脚本的末尾。

  • .select('SR_B4') 方法用于从这个影像对象中选择名为 'SR_B4' 的波段。'SR_B4' 通常指的是近红外(Near Infrared)波段,这在遥感影像处理中是一个常见的波段,用于植被监测、土地覆盖分类等多种应用。
  • .divide(10000) 方法将上一步骤选中的波段中的每个像素值除以10000。这个操作通常用于缩放或标准化数据,使其更适合进行后续的分析或可视化。
  • nirScaled 和 redScaled 分别是近红外和红光波段经过缩放(可能是为了单位统一或数据标准化)后的影像。
  • subtract 方法用于逐像素地从近红外波段中减去红光波段。
var makeLandsat5EVI = function(oneL5Image) { 
var nirScaled =oneL5Image.select('SR_B4').divide(10000); 
var redScaled = oneL5Image.select('SR_B3').divide(10000); 
var blueScaled = oneL5Image.select('SR_B1').divide(10000);  
// Calculate the numerator, note that order goes from left to right. 
var numeratorEVI = (nirScaled.subtract(redScaled)).multiply( 2.5);  
// Calculate the denominator 
var denomClause1 = redScaled.multiply(6); 
var denomClause2 = blueScaled.multiply(7.5); 
var denominatorEVI = nirScaled.add(denomClause1).subtract( denomClause2).add(1);  
// Calculate EVI and name it. 
var landsat5EVI = numeratorEVI.divide(denominatorEVI).rename( 'EVI'); 
return (landsat5EVI); };

值得强调的是,通常,带名特定于每个 ImageCollection。因此,例如,如果在没有波段 'SR_B4' 的图像上运行该函数,则函数调用将失败。在这里,我们在函数名称中强调了它专门用于为 Landsat 5 创建 EVI。

函数 makeLandsat5EVI 用于接收单个影像,选择合适的波段来计算 EVI,进行计算并返回单波段影像。如果我们有组成 ImageCollection 的每个图像的名称,我们可以在代码编辑器中输入名称,然后一次为每个图像调用一个函数,将图像组合成变量,然后将它们组合成一个 ImageCollection。这将非常乏味且极易出错:项目列表可能会输入错误,可能会错过图像等。相反,如上所述,我们将使用 .map。使用下面的代码,让我们打印有关云过滤集合的信息并显示它,执行 .map 命令,并浏览生成的 ImageCollection。

  • efficientFilteredSet 是一个影像集合(ImageCollection),它包含了经过筛选的Landsat 5影像。
  • map 方法是一个高阶函数,它接受一个函数(在这个例子中是 makeLandsat5EVI)作为参数,并将这个函数应用于 efficientFilteredSet 中的每个影像。
  • makeLandsat5EVI 应该是一个已经定义的函数,它接受一个影像作为输入,计算该影像的EVI,并返回计算后的影像。这个函数内部会执行之前提到的所有步骤,包括选择波段、缩放、计算分子和分母、以及最终得到EVI值。
  • L5EVIimages 是一个新的影像集合,它包含了 efficientFilteredSet 中每个影像对应的EVI影像。
var L5EVIimages = efficientFilteredSet.map(makeLandsat5EVI); 
print('Verifying that the .map gives back the same number of images: ', L5EVIimages.size()); 
print(L5EVIimages);  
Map.addLayer(L5EVIimages, {}, 'L5EVIimages', 1, 1);

输入并执行此代码后,您将看到一个灰度图像。如果您仔细观察图像的边缘,您可能会发现在图像后面绘制的其他图像看起来有点像桌子上的一叠文件。这是根据 makeLandsat5EVI 函数生成的 ImageCollection 的绘制。您可以选择 Inspector 面板并单击其中一个灰度像素以查看整个 ImageCollection 的值。单击像素后,通过打开和关闭项目列表来查找 Series 标记。打开该标签时,您将看到该像素处的 EVI 值的图表,该图表是通过在过滤后的 ImageCollection 上映射 makeLandsat5EVI 函数创建的。

减少图像集合

filter的第三部分,map, reduce 范式是 “减少” ImageCollection 中的值以提取有意义的值。在牛奶示例中,我们减少了一大堆牛奶价格以找到最小值。Earth Engine API 提供了大量 reducer,用于将一组值缩减为汇总统计数据。在这里,在通过 .map 命令执行 EVI 计算后,您可以将每个位置视为具有 EVI 值列表。每个像素都包含一组可能非常大的 EVI 值;堆栈在一个位置可能有 15 个项目,而在另一个位置可能有 200、2000 或 200,000 个项目,尤其是在使用了一组较松散的筛选条件的情况下。下面的代码计算上面创建的 ImageCollection L5EVIimages 的每个像素的平均值。将其添加到代码的底部

var L5EVImean = L5EVIimages.reduce(ee.Reducer.mean());  
print(L5EVImean); 
Map.addLayer(L5EVImean, 
             { min: -1, max: 2, palette: ['red', 'white', 'green'] }, 
            'Mean EVI');

使用相同的原理,下面的代码计算并绘制每个像素中 ImageCollection 的中值。

var L5EVImedian = L5EVIimages.reduce(ee.Reducer.median());  
print(L5EVImedian); 
Map.addLayer(L5EVImedian, 
             { min: -1, max: 2, palette: ['red', 'white', 'green'] }, 
             'Median EVI');

还有更多的 reducer 与 ImageCollection 一起使用,以生成各种摘要统计信息。Reducer 不限于仅返回 reduction 中的一个项。例如,minMax reducer 为给定的每个波段返回一个双波段图像,一个用于最小值,一个用于最大值。此处描述的 reducer 独立处理每个像素。在第 IV 部分的后续章节中,您将看到其他类型的 reducer,例如,总结每个像素周围邻域中特征的 reducer。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值