水体出现情况(1984 年至 2015 年)

GSW 数据集包含许多数据层,这些数据层以不同的方式呈现地表水数据。我们首先将直观呈现水体出现频率图层,该图层汇总了 1984 年 3 月至 2015 年 10 月期间地表水出现的位置和频率。

本教程的这一部分将:

  1. 添加一个地图图层,用于直观呈现地表水出现情况
  2. 展示如何查询地图图层的值
  3. 添加自定义样式以改进可视化效果,
  4. 使用阈值创建二值化水体掩膜图层,
  5. 将地图中心定位到世界上有趣的地方,
  6. 展示如何重构脚本,使其更易于阅读和维护。

创建基本可视化图表

首先,将以下语句复制到代码编辑器中:

代码编辑器 (JavaScript)

var gsw = ee.Image('JRC/GSW1_0/GlobalSurfaceWater');
var occurrence = gsw.select('occurrence');
Map.addLayer(occurrence);

第一条语句引用 GSW 数据集的 Earth Engine Image 对象,并将其存储在名为 gsw 的变量中。 第二条语句选择 GSW 数据集的一个图层,并将其存储在名为 occurrence 的变量中。 第三条语句将出现情况图像添加到代码编辑器的交互式地图中。

点击代码编辑器的“运行”按钮,几秒钟后,您应该会看到一张地图,其海岸线呈灰色,类似于图 1。

默认可视化图表
图 1. 全球地表水出现频率数据层的默认可视化效果。

在大多数区域,GSW 数据集显示为透明,因为未收集 Landsat 图像的位置(即海洋区域)或 32 年内任何观测均未检测到水的位置均被 遮盖。

检查值

为了探索水体出现频率图层的值,我们将使用代码编辑器的检查器标签页。 首先点击“检查器”标签页,然后点击地图以选择一个位置。检查器标签页将显示您点击的位置存在的每个图层的信息。

“检查器”标签页
图 2. “检查器”标签页输出示例。

在上面的示例中,名为 value 的层的值为 98。单位为百分点,因此该位置大约有 98% 的时间被归类为水体覆盖。 该值是每个月地表水出现值的平均值,它会根据季节性变化进行标准化,如 数据用户指南 (v2) 中所述。

通过重构改进代码

我们的脚本仅包含两条语句,但我们已经有机会重构代码,以便最终脚本更易于阅读和维护。 目前,Map.addLayer() 语句会传递一个参数 occurrence,即我们要在地图上显示的 Earth Engine 影像对象。不过,Map.addLayer() 方法还允许向其传递其他实参。如需快速查看可用的实参,请将光标置于左括号后,然后按“显示代码建议”的键盘快捷键,调出 addLayer 方法的帮助文档。(您可以通过选择“帮助”菜单 ->“快捷键”来查看键盘快捷键。)

Map.addLayer 参数
图 3. 显示 addLayer 方法的参数的屏幕截图。

键盘快捷键显示,可以向 Map.addLayer 传递五个参数:eeObject、visParams、name、shown 和 opacity。 在当前脚本中,我们传递了一个变量 occurrence,该变量被解释为第一个参数 eeObject。 如需同时传递变量对象和用于命名图层的额外实参,我们可以重构代码,以使用“具名实参”(eeObject 和 name),这些实参是从 JSON 数据结构 中传递给方法的,如下所示:

代码编辑器 (JavaScript)

Map.addLayer({eeObject: occurrence, name: 'Water Occurrence (1984-2015)'});

再次运行代码,确保在重构更改后代码仍可正常运行。 生成的地图应保持不变。

添加可视化参数

接下来,我们将改进默认可视化参数,这些参数使水体呈现灰色。添加一个新语句,用于创建变量 VIS_OCCURRENCE,并将其作为附加参数传递给 addLayer 方法。

代码编辑器 (JavaScript)

var VIS_OCCURRENCE = {
  min: 0,
  max: 100,
  palette: ['red', 'blue']
};

代码编辑器 (JavaScript)

Map.addLayer({
  eeObject: occurrence.updateMask(occurrence.divide(100)),
  name: 'Water Occurrence (1984-2015)',
  visParams: VIS_OCCURRENCE
});

存储在 JSON 结构 VIS_OCCURRENCE 中的可视化参数表示,最小值 0% 应使用红色,最大值 100% 应使用蓝色。 添加 .updateMask(occurrence.divide(100)) 会导致像素的不透明度/透明度根据出现值进行设置。

再次运行脚本,查看样式更改后的修订结果。

地表水出现频率
图 4. 布宜诺斯艾利斯附近巴拉那三角洲的水体出现情况屏幕截图,其中 0% 最小值端点使用透明红色,最大值端点使用纯蓝色。

水域现在变成蓝色了!进展不错!

创建阈值图层

水体出现频率图像包含有关预期水体出现频率的信息,其值范围为 0% 到 100%。不过,定义一个二元水层(即“水”与“非水”)进行分类。我们将使用这个简单的二元图层作为干净的背景图层,其他 GSW 图层可以放置在其上。 您可以使用以下语句创建此阈值层,该语句使用 90% 的阈值来区分水和非水。

首先,我们定义一个新的可视化变量 VIS_WATER_MASK,用于保存水体掩膜的样式信息:

代码编辑器 (JavaScript)

var VIS_WATER_MASK = {
  palette: ['white', 'black']
};

然后,我们使用大于比较运算符 .gt(90) 计算水体掩膜图层,并使用 .unmask() 方法将之前被掩膜的区域设置为零:

代码编辑器 (JavaScript)

// Create a water mask layer, and set the image mask so that non-water areas
// are opaque.
var water_mask = occurrence.gt(90).unmask(0);

最后,将图层添加到地图中。为了在所有其他图层下渲染此图层,请将以下语句放在任何其他 Map.addLayer 语句之前。

代码编辑器 (JavaScript)

Map.addLayer({
  eeObject: water_mask,
  visParams: VIS_WATER_MASK,
  name: '90% occurrence water mask'
});
90% 水体掩膜
图 5. 布宜诺斯艾利斯附近巴拉那三角洲 90% 水体掩膜的屏幕截图。

前往世界各地的有趣地点

通过平移和缩放来探索世界很有趣,但世界很大,有时直接跳转到特定位置会很有帮助。 以下是一系列语句,提供了一些在地表水方面比较有趣的地点。 只需一次取消注释一条语句,脚本在运行时就会转到相应位置。

代码编辑器 (JavaScript)

// Uncomment one of the following statements to center the map.
// Map.setCenter(-90.162, 29.8597, 10);   // New Orleans, USA
// Map.setCenter(-114.9774, 31.9254, 10); // Mouth of the Colorado River, Mexico
// Map.setCenter(-111.1871, 37.0963, 11); // Lake Powell, USA
// Map.setCenter(149.412, -35.0789, 11);  // Lake George, Australia
// Map.setCenter(105.26, 11.2134, 9);     // Mekong River Basin, SouthEast Asia
// Map.setCenter(90.6743, 22.7382, 10);   // Meghna River, Bangladesh
// Map.setCenter(81.2714, 16.5079, 11);   // Godavari River Basin Irrigation Project, India
// Map.setCenter(14.7035, 52.0985, 12);   // River Oder, Germany & Poland
// Map.setCenter(-59.1696, -33.8111, 9);  // Buenos Aires, Argentina
Map.setCenter(-74.4557, -8.4289, 11);  // Ucayali River, Peru

这只是其中一小部分有趣地点。欢迎自行添加!

再次重构…

在继续处理 GSW 数据集的下一层之前,我们将对代码进行一些重构。具体而言,我们会将类似的语句分组,并添加一些注释,将代码分为资源、常量、计算、地图居中和添加地图图层等部分。

以下是最终重构的脚本:

代码编辑器 (JavaScript)

//////////////////////////////////////////////////////////////
// Asset List
//////////////////////////////////////////////////////////////

var gsw = ee.Image('JRC/GSW1_0/GlobalSurfaceWater');
var occurrence = gsw.select('occurrence');

//////////////////////////////////////////////////////////////
// Constants
//////////////////////////////////////////////////////////////

var VIS_OCCURRENCE = {
  min: 0,
  max: 100,
  palette: ['red', 'blue']
};
var VIS_WATER_MASK = {
  palette: ['white', 'black']
};

//////////////////////////////////////////////////////////////
// Calculations
//////////////////////////////////////////////////////////////

// Create a water mask layer, and set the image mask so that non-water areas
// are opaque.
var water_mask = occurrence.gt(90).unmask(0);

//////////////////////////////////////////////////////////////
// Initialize Map Location
//////////////////////////////////////////////////////////////

// Uncomment one of the following statements to center the map.
// Map.setCenter(-90.162, 29.8597, 10);   // New Orleans, USA
// Map.setCenter(-114.9774, 31.9254, 10); // Mouth of the Colorado River, Mexico
// Map.setCenter(-111.1871, 37.0963, 11); // Lake Powell, USA
// Map.setCenter(149.412, -35.0789, 11);  // Lake George, Australia
// Map.setCenter(105.26, 11.2134, 9);     // Mekong River Basin, SouthEast Asia
// Map.setCenter(90.6743, 22.7382, 10);   // Meghna River, Bangladesh
// Map.setCenter(81.2714, 16.5079, 11);   // Godavari River Basin Irrigation Project, India
// Map.setCenter(14.7035, 52.0985, 12);   // River Oder, Germany & Poland
// Map.setCenter(-59.1696, -33.8111, 9);  // Buenos Aires, Argentina
Map.setCenter(-74.4557, -8.4289, 11);  // Ucayali River, Peru

//////////////////////////////////////////////////////////////
// Map Layers
//////////////////////////////////////////////////////////////

Map.addLayer({
  eeObject: water_mask,
  visParams: VIS_WATER_MASK,
  name: '90% occurrence water mask',
  shown: false
});
Map.addLayer({
  eeObject: occurrence.updateMask(occurrence.divide(100)),
  name: 'Water Occurrence (1984-2015)',
  visParams: VIS_OCCURRENCE
});

在下一部分中,您将探索水体出现频率随时间的变化情况。