1简介
在本模块中,我们将讨论以下概念:
-
处理海洋的遥感图像。
-
从图像时间序列创建视频。
-
GEE 中的时间序列分析。
-
向图形用户界面添加基本元素。
2背景
深水地平线漏油事件被认为是有史以来最大的海上意外漏油事件。该井释放了超过 490 万桶石油,其中 410 万桶在 2010 年 4 月 20 日至 7 月 15 日期间进入墨西哥湾。通过燃烧或撇去海洋表面的石油和通过在海洋表面释放超过 184 万加仑的化学分散剂 (Corexit) 并直接进入海洋表面以下约 5,000 英尺的油井排放的油流中。即使做出了这些努力,漏油事件也严重影响了海湾的沿海和海洋生态系统。尽管为评估石油在这些生态系统中的影响付出了广泛的努力,但受泄漏影响的大面积区域使其变得困难。在本模块中,我们将通过监测受溢油高度影响的区域内藻类浓度随时间的变化趋势,对此次溢油的生态影响进行自己的探索。由于藻类是海洋生态系统的主要生产者,监测它们的种群如何受到这种变化的影响可能有助于我们更好地了解石油对受影响生态系统状态的整体影响。
一位野生动物生物学家正在观察被油浸过的马尾藻,即马尾藻。这代表了许多小型海洋生物栖息地的丧失。 图片来源:美国国家应对小组
3 GEE 趋势分析
3.1遥感直接监测油品
遥感直接检测石油的能力有限。这是因为油反射光的方式与水的反射方式大致相同。然而,油确实会影响水的表面粗糙度。石油浓度高的地区可以使海洋表面光滑。因此,在“深水地平线”泄漏事件后,大部分探测石油的遥感工作都涉及机载雷达,这是一种可以捕捉表面纹理的有源传感器。不幸的是,这些数据在 GEE 中不可用。虽然无源传感器不太适合直接检测水面上的油污,但 NASA MODIS 快速响应小组的遥感专业人员使用油的平滑质量以非常聪明的方式对其进行检测。
3.2阳光
根据太阳角度和传感器之间的关系,水体表面可以有效地充当镜子,将大部分光线直接反射回传感器。这个过程被称为sunglint,在处理遥感水图像时,这是一个始终如一的挑战。Sunglit 有效地改变了它所覆盖的表面的所有数据,因为到达传感器的能量只是阳光的直接反射,而不是基于表面吸收和反射的光的子集。我们知道油具有抚平水面的能力,当这种情况发生在阳光明媚的区域内时,油覆盖的表面反射的光比单独的水要多。这意味着在阳光照射的区域,油会比水更亮。下图由 Aqua MODIS 传感器捕获,清楚地显示了深水地平线溢油首次释放油 35 天后的油污程度。左上角是密西西比河三角洲。
含有大量地表油的阳光区域的图像。当您远离太阳光的中心(图像右侧)时,您可以观察到油的反射率的变化。 学分:美国宇航局地球观测站
因为我们知道传感器 (MODIS) 和日期,让我们尝试在 GEE 中复制此图像。
// A point representing the general location of deepwater horizon oil rig.
var dw = ee.Geometry.Point([-88.36555556,28.73805556]);
// Pull in MODIS Aqua imagery and visualize the sunglint oil.
var mod2 = ee.ImageCollection("MODIS/006/MYD09GA")
.filterDate("2010-05-25","2010-05-26");
// Add to map.
Map.addLayer(mod2, {bands: ["sur_refl_b01","sur_refl_b04","sur_refl_b03"],
gamma: 1,
max: 10278.86,
min: 192.14000000000001,
opacity: 1}, "mod2");
// Add Deepwater Horizon location to map.
Map.addLayer(dw,{},"DWH");
// Set map to center on deep water horizon location
Map.setCenter(-88.36555556,28.73805556, 8);
上面在 GEE 中创建的 MODIS 图像的复制。您可以调整 Gamma 以使图像略微变亮。
这张图片显示,在泄漏的第一个月,石油已经广泛扩散。在 GEE 中,MODIS 图像可用于预处理的表面反射率级别。有关何时应使用表面反射率图像的详细信息,请参阅模块 5. 虽然这对于随着时间的推移进行比较非常有用,但这意味着图像中具有非常高反射率值的一些元素实际上作为图像预处理的一部分被屏蔽掉了。这包括上图中的防晒油区域。考虑到这一点,基于 MODIS 图像对石油范围进行稳健的定量评估是不可行的。尽管如此,这是一张引人注目的图片,可以用来激发人们对美国历史上最大的环境灾难之一的故事的兴趣。此次泄漏石油泄漏超过 100 天,是一场重大的生态灾难,夺走了 11 人的生命。
虽然不太清楚,但下图还显示了在最初爆炸后的第二天可见的烟雾。深水地平线钻机在沉入海底之前燃烧了两天。
// Pull in MODIS aqua imagery and filter for specific date.
var smokePlume = ee.ImageCollection("MODIS/006/MYD09GA")
.filterDate("2010-04-21","2010-04-22");
// Add to map.
Map.addLayer(smokePlume, {bands: ["sur_refl_b01","sur_refl_b04","sur_refl_b03"],
gamma: 1.32,
max: 3278.86,
min: 192.14000000000001,
opacity: 1}, "smokePlume");
虽然不是最好的图像,但密西西比河沉积物丰富的出口东南部海洋中较轻的区域是燃烧的深水地平线石油钻井平台产生的烟雾。
该图像具有很多定性价值,为了快速获得这一点,我们将在石油活跃泄漏期间制作 MODIS 图像的延时电影。
4景观变化视频
GEE 最初是一个使用 Landsat 图像开发全球无云镶嵌图的项目。该产品成为 Google 地球的基础地图。创建无云拼接后,使用 GEE 基础设施制作的下一个产品是主要景观变化的延时视频。这些视频非常引人入胜,对我们星球表面发生的剧烈变化进行了令人恐惧的描述。花几分钟看一些预制的例子是值得的。
要制作其中一个视频,我们需要完成三件事。
-
定义一个感兴趣的区域。
-
沿日期范围拉入图像。
-
定义可视化参数。
为了创建感兴趣的区域,我们将在 Deepwater Horizon 钻机的先前位置周围进行缓冲。GEE 将使用缓冲区的尺寸来设置视频的边界框。基本上,即使我们在地图上的形状是圆形,我们最终还是会得到一个正方形。将以下代码添加到现有脚本中以开始使用。
// Buffer around the deep water horizon site.
var buffer = dw.buffer({distance:150000} );
Map.addLayer(buffer, {}, 'buffer');
我们将继续使用 Aqua MODIS 表面反射率图像并使用我们之前定义的可视化参数。在这种情况下,我们在四个月的时间内选择图像。视频中将有大约 120 张图像。将以下代码添加到您的脚本中。
// Define the visualization parameters.
var vis = {gamma: 1,
max: 10278.86,
min: 192.14000000000001,
opacity: 1};
var collection = ee.ImageCollection("MODIS/006/MYD09GA")
// Get four months of imagery.
.filterDate('2010-04-01','2010-7-30')
// Need to have 3-band imagery for the video.
.select(['sur_refl_b01', 'sur_refl_b04', 'sur_refl_b03'])
// Use the map function to apply the same visualizations to all images.
.map(function(image) {
return image.visualize(vis);
});
Map.addLayer({eeObject: collection, name:'Video images'});
有了这些元素,最后一步就是导出视频。这与 GEE 中的任何其他导出功能一样有效,但有一些特定于视频质量的独特参数。
Dimensions
:视频的像素分辨率。提供单个号码时假定为 720 乘 720。
FramesPerSecond
:定义每秒显示的图像数量。我们正在显示大约 120 张图像,因此以每秒四帧的速度,我们的视频将长约 30 秒。如果您想使用此视频进行更定性的评估,您可以将其降至每秒 1 帧。将代码添加到现有脚本中。
// Export (change dimensions or scale for higher quality).
Export.video.toDrive({
collection: collection,
description: 'modisDWH',
dimensions: 720,
framesPerSecond: 4,
region: buffer
});
与从 GEE 导出的任何内容一样,您需要在运行脚本后通过选择任务窗格中的运行按钮来执行此过程。导出此视频需要一些时间。根据您的连接速度和为视频选择的参数,此过程预计需要 10 到 20 分钟。为您的学习领域制作视频可以为您提供有趣且引人入胜的资源,展示该地区的一些特征。该视频将清楚地表明,墨西哥湾是一个普遍多云的地方,但会有一些图像,阳光下的油会发出明亮的光芒。可以在此处找到视频示例。
在本模块的下一步中,我们将研究更定量的方法来比较该区域随时间的光合活性。
5深水地平线溢油的生态影响
根据现场调查数据,这张地图显示了墨西哥湾海洋石油的潜伏期和沿海石油的严重程度。虽然没有比例尺,但巴吞鲁日和彭萨科拉相距大约 250 英里。 图片来源:美国国家应对小组
如上图所示,深水地平线漏油事件的主要影响是石油在生态系统中的持久性。随着油井开放超过 100 天,由于洋流和天气条件的变化,石油出现在墨西哥湾的广大地区。测量实际的生态影响是一项真正的挑战,因为海洋表面的许多地方都存在石油,并且影响了整个营养级的物种。我们将尝试监测泄漏对构成墨西哥湾海洋食物网基础的光合藻类的影响。
5.1藻华
深水地平线事件是点源污染的一个例子。但墨西哥湾,特别是密西西比河三角洲周围,已经处理非点源污染已有一段时间了。密西西比河排放了美国大约三分之一的土地,该地区的大部分地区都处于密集的农业发展之中。为了种植植物,需要向农田施用额外的养分,例如氮和磷。虽然这些营养物质被植物利用,但有些营养物质在降水事件中被冲走并最终进入海洋。结果,自然产生的藻类种群获得了额外的营养,并大量开花。春季洪水将大量沉积物和溶解的营养物质带入墨西哥湾。这可以显着增加沿海的藻类数量。沿海岸的水中呈浅绿色可见藻华。 学分:美国宇航局地球观测站
上面的真彩色 MODIS 图像显示了整个密西西比河三角洲春季高水位事件产生的沉积物羽流(棕褐色)和藻华(浅绿色)。我们将尝试看看在海洋表面持续存在石油的年份与不存在石油的年份相比,藻华的程度和强度是否存在可测量的差异。
5.2 MODIS 叶绿素-a 产品
MODIS Aqua 传感器自 2000 年以来一直在捕获图像。在此期间,遥感界还开发了许多专门为 MODIS 图像设计的内容特定算法。许多算法已经变成了最终用户可以在 GEE 中快速参与的预处理产品。对于随着时间的推移绘制藻类种群,我们将依赖 GEE 中可用的这些预处理产品之一,Ocean Color SMI:标准映射图像 MODIS Aqua Data
GEE 中可用的 MODIS Ocean Color 图像集合的描述。
“chlor_a”波段是叶绿素-a 的近地表浓度,它基于 MODIS 传感器的蓝色和绿色波段之间的经验关系。叶绿素-a 是负责光合作用的主要分子,有助于植物的绿色。通过绘制叶绿素-a 浓度图,我们假设藻类是该海洋区域中这种分子的主要来源。
5.3区分两年的图像
只要您拥有正确的图像,就值得生成一些您感兴趣的生态特征的简单可视化。我们将通过生成 2009 年和 2010 年的叶绿素 a 密度图来做到这一点。我们还将利用这两个图像之间的差异来可视化两年之间叶绿素 a 密度的空间模式。
我们将过滤我们的数据集 a 以捕获油井活跃泄漏的月份。请打开一个新脚本,从以下代码开始。
// Set map to center on deep water horizon location
Map.setCenter(-88.36555556,28.73805556, 7);
// Define visualization parameters so the images are both presented in the same way.
var vis2 = {min:-7, max:14};
// Generate the based dataset for our processes.
var mod09 = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
.filterDate("2009-04-20","2009-07-31")
.select("chlor_a")
.median();
Map.addLayer(mod09, vis2, "09");
// Generate the based dataset for our processes.
var mod10 = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
.filterDate("2010-04-20","2010-07-31")
.select("chlor_a")
.median();
Map.addLayer(mod10, vis2, "10");
// Difference the model by subtracting.
var diff = mod10.subtract(mod09);
Map.addLayer(diff, {min:-6, max:6}, "diff");
使用检查器工具查看值的差异。较暗的区域表明 2009 年存在更多的藻类,较浅的区域表明 2010 年存在更多的藻类。
2009 年和 2010 年之间藻类浓度的差异。深色区域代表藻类浓度降低的区域,浅色区域是藻类浓度增加的区域。
非常黑暗的区域可能会提示我们油对藻类生产力有影响。但这是一个复杂的系统,明智的做法是查看数据的趋势,而不是直接比较两个时间步长。我们将研究两种不同的方法来观察藻类生产力随时间的变化趋势。
6 MODIS 系列的趋势分析
遥感数据的趋势分析是一个很大的研究领域。这是一种重要的方法,因为在复杂系统中,单一事件可能在短期内产生影响,但由于系统的弹性,随着时间的推移对生态系统功能几乎没有影响。使用 MODIS 传感器,我们可以获得 2002 年至今的藻类浓度数据。我们将使用两种不同的方法准备这些数据,以突出平均值和每日测量值随时间的变化。两种方法都突出了不同的趋势,并提供了有关溢油对藻类种群影响的独特信息。
6.1中值法。
在上面的图像比较方法中,我们查看了两个图像之间的差异。在这个例子中,我们将开发一种方法,使我们能够对所有年份的可用数据进行类似的比较。我们将通过创建一个包含油井泄漏时间段的中值缩小图像的字典来稍微自动化这个过程。我们正在使用自定义构建的函数来构建我们的图像字典。此功能需要用户进行一些调整,因此我们在说明中包含了一些描述性文本,以便用户知道确切需要什么。如果您发现自己生成的函数在许多不同情况下被您以外的人使用,这是一个很好的做法。将以下代码添加到您当前的脚本中。
var constructMODDict = function(geometry)
/*
This function takes in a geometry feature from the GUI and uses it to
generate a dictionary of median reduce images for the specified date range
inputs
geometry = geometry object representing you area of interest
y_list = set based on sensor type
imagecollection = unique id for collection type
filterDate = cat() this is used to refine the month and day of start and end time
With adaptation this should be flexible across sensors and times
*/
{
var startMonth = "-04-20";
var endMonth = "-07-31";
// Construct a dictionary for MODIS.
var y_list = ee.List.sequence(2002, 2018);
var ystr_list = y_list.map(function(y){return ee.Number(y).format('%1d')});
var mod = y_list.map(function(y){return ee.ImageCollection('NASA/OCEANDATA/MODIS-Aqua/L3SMI')
.filterDate(ee.String(ee.Number(y).format('%1d')).cat(startMonth),
ee.String(ee.Number(y).format('%1d')).cat(endMonth))
.select("chlor_a")
.median()
.clip(geometry);
})
var mod_dict = ee.Dictionary.fromLists(ystr_list, mod);
// Return MODIS dictionary.
return mod_dict;
};
简而言之,此功能会在设定的日期范围内拉入所有图像,选择特定波段,应用中值缩减器,并将图像剪辑到几何特征。我们希望在多年内做到这一点,因此我们创建了一个我们想要涵盖的年份的列表。该列表被转换为ee.Number
对象,用于选择和操作列表中所有年份的图像。创建图像时,它会存储在列表中。然后我们将该列表转换为一个字典,它允许我们通过将其键定义为它所代表的年份来跟踪图像。有关更多字典示例,请参阅模块 10。
运行上面的函数会将特性带入内存。在下面的代码中,我们调用该函数并提供几何特征作为输入。创建您自己的几何特征,包括路易斯安那州、密西西比州和阿拉巴马州的更多海岸线。作为参考,请使用第 5 节中受影响的沿海地区地图,并确保它包括距海岸 20 或 30 英里的距离。藻类在浅水区最为普遍,但我们希望包括潜在的栖息地。将以下代码添加到您的脚本以运行该函数。
// Apply function across the new geometry.
var elements = constructMODDict(geometry);
print(elements, "Image dictionary");
图像字典是存储数据的便捷功能,因为我们可以使用代表图像拍摄年份的键来选择图像。这使得分类和理解您正在使用的图像变得容易。也就是说,字典对于显示和运行图像分析没有用处。因此,我们将从字典中创建一个图像集合。将以下代码添加到现有脚本中。
// Convert the images in the dictionary to an image collection.
var collection2 = ee.ImageCollection.fromImages([
ee.Image(elements.get('2002')),
ee.Image(elements.get('2003')),
ee.Image(elements.get('2004')),
ee.Image(elements.get('2005')),
ee.Image(elements.get('2006')),
ee.Image(elements.get('2007')),
ee.Image(elements.get('2008')),
ee.Image(elements.get('2009')),
ee.Image(elements.get('2010')),
ee.Image(elements.get('2011')),
ee.Image(elements.get('2012')),
ee.Image(elements.get('2013')),
ee.Image(elements.get('2014')),
ee.Image(elements.get('2015')),
ee.Image(elements.get('2016')),
ee.Image(elements.get('2017')),
ee.Image(elements.get('2018'))
]);
print(collection2)
Map.addLayer(collection2,{},'ic')
这不是一种有效的方法,但它确实有效。如果您的字典中有大量图像,则必须找到一种更有创意的方法来创建这个新的图像集合。探索的另一种选择是map()GEE 中的函数,它的工作方式类似于 for 循环或lapply()
R 中的函数。
将图像集添加到地图后,我们可以使用检查器工具在地图上选择一个位置,并查看所选位置在 17 年时间段内的叶绿素 a 中值浓度直方图。石油泄漏发生在 2010 年,我们的图像从 2002 年开始。这意味着直方图上的第八个位置代表 2010 年。您可以通过将直方图上的值与 2009 年和 2010 年栅格中的值进行比较来验证这一点。检查器工具将在您选择的位置显示所有图像的值。
显示所有可用 MODIS 图像中选定位置的叶绿素 a 浓度中值的直方图。
6.2单个图像在一个区域内的趋势
上面的示例是快速检查所选位置的中值的绝佳资源。但是,此方法可以掩盖感兴趣的唯一值,例如最小和最大浓度。在此示例中,我们将构建一个类似的数据集,但不会减少一年中的图像。因此,我们将为我们选择的每一年的每一天提供价值。将以下代码添加到您的脚本中。
// Define start and end dates.
var start = '2008-01-01';
var end = '2012-12-31';
// Select all images with the months of April to July with a date range
var col = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
.filterDate(start, end)
.filter(ee.Filter.calendarRange(4,7,'month'))
.filterBounds(geometry)
.select("chlor_a");
print(col, "Individual Images By Year");
在上面的代码中,我们应用了一个非常熟悉的过滤过程,并添加了一个新的过滤元素。该ee.Filter.calendarRange()
功能允许您按图像元数据(时间戳、日、月、年)中的时间元素进行过滤。在我们的例子中,我们选择的是在一年中的第四个月到第七个月之间拍摄的图像。这是一个非常方便的过滤器!
可用于运行汇总统计的小感兴趣区域的示例。
这个几何特征将定义我们编译数据的来源。为了可视化数据,我们将使用该ui.Chart()
函数。此函数需要用于输入数据的 imageCollection、用于定义区域的几何特征以及用于将区域内的所有元素编译为单个值的 reducer 函数。将以下代码添加到您的脚本以生成和查看图表。
// Plot a time series of the chlor_a at a single location or summarize values within an area.
var l8Chart = ui.Chart.image.series({imageCollection: col,
region: roi,
reducer: ee.Reducer.median()}
).setChartType('ScatterChart');
print(l8Chart);
该图表将出现在您的控制台中。使用图表右上角的箭头将图表打开为全尺寸网页。您还可以选择保存数据或图表图像以供进一步工作。
2010 年石油释放日期范围内多年图像中的每日叶绿素-a 浓度。
很容易看出汇总数据和单个图像数据如何讲述略有不同的故事。单个图像数据的复杂性清楚地表明,藻类浓度是一个非常动态的特征,并且对随着时间的变化做出科学合理的声明将需要大量的额外工作。重要的是数据就在那里,只是需要付出努力。
7结论
在本模块中,我们开发了一种方法,使我们能够查看墨西哥湾藻类浓度的时间序列数据,以估计深水地平线漏油事件对该生态系统基础营养级的影响。该系统的规模和复杂性表明,要得出有关实际影响的结论性结果将需要大量额外的工作。但是从这个过程中可以清楚地看出,GEE 提供了进行时间序列分析的计算能力和灵活性。希望您可以使用这些工具和方法来提出您自己的问题,了解生态干扰随时间推移的长期影响。
7.1完整的趋势分析代码
// Set map to center on deep water horizon location.
Map.setCenter(-88.36555556,28.73805556, 6);
// Define visualization parameters so the images are both presented in the same way.
var vis2 = {min:-7, max:14};
// Generate the based dataset for our processes.
var mod09 = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
.filterDate("2009-04-20","2009-07-31")
.select("chlor_a")
.median();
Map.addLayer(mod09, vis2, "09");
// Generate the based dataset for our processes.
var mod10 = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
.filterDate("2010-04-20","2010-07-31")
.select("chlor_a")
.median();
Map.addLayer(mod10, vis2, "10");
// Difference the model by subtracting.
var diff = mod10.subtract(mod09);
Map.addLayer(diff, {min:-6, max:6}, "diff");
var constructMODDict = function(geometry)
/*
This function takes in a geometry feature from the GUI and uses it to
generate a dictionary of median reduce images for the specified date range
inputs
geometry = geometry object representing you area of interest
y_list = set based on sensor type
imagecollection = unique id for collection type
filterDate = this is used to refine the month and day of start and end time
With adaptation this should be flexible across sensors and date ranges.
*/
{
var startMonth = "-04-20";
var endMonth = "-07-31";
// Construct a dictionary for MODIS.
var y_list = ee.List.sequence(2002, 2018);
var ystr_list = y_list.map(function(y){return ee.Number(y).format('%1d')});
var mod = y_list.map(function(y){return ee.ImageCollection('NASA/OCEANDATA/MODIS-Aqua/L3SMI')
.filterDate(ee.String(ee.Number(y).format('%1d')).cat(startMonth),
ee.String(ee.Number(y).format('%1d')).cat(endMonth))
.select("chlor_a")
.median()
.clip(geometry);
})
var mod_dict = ee.Dictionary.fromLists(ystr_list, mod);
// Return MODIS dictionary.
return mod_dict;
};
// Apply function across the new geometry.
var elements = constructMODDict(geometry);
print(elements, "Image dictionary");
// Convert the images in the dictionary to an image collection.
var collection2 = ee.ImageCollection.fromImages([
ee.Image(elements.get('2002')),
ee.Image(elements.get('2003')),
ee.Image(elements.get('2004')),
ee.Image(elements.get('2005')),
ee.Image(elements.get('2006')),
ee.Image(elements.get('2007')),
ee.Image(elements.get('2008')),
ee.Image(elements.get('2009')),
ee.Image(elements.get('2010')),
ee.Image(elements.get('2011')),
ee.Image(elements.get('2012')),
ee.Image(elements.get('2013')),
ee.Image(elements.get('2014')),
ee.Image(elements.get('2015')),
ee.Image(elements.get('2016')),
ee.Image(elements.get('2017')),
ee.Image(elements.get('2018'))
]);
print(collection2)
Map.addLayer(collection2,{},'ic')
// Define start and end dates.
var start = '2008-01-01';
var end = '2012-12-31';
// Select all images with the months of April to July with a date range.
var col = ee.ImageCollection("NASA/OCEANDATA/MODIS-Aqua/L3SMI")
.filterDate(start, end)
.filter(ee.Filter.calendarRange(4,7,'month'))
.filterBounds(geometry)
.select("chlor_a");
print(col, "Individual Images By Year");
// Plot a time series of the chlor_a at a single location
// or summarize values within an area.
var l8Chart = ui.Chart.image.series({imageCollection: col,
region: roi,
reducer: ee.Reducer.median()}
).setChartType('ScatterChart');
print(l8Chart);