GSW 数据集包含许多数据层,这些数据层以不同的方式呈现地表水数据。我们首先将直观呈现水体出现频率图层,该图层汇总了 1984 年 3 月至 2015 年 10 月期间地表水出现的位置和频率。
本教程的这一部分将:
- 添加一个地图图层,用于直观呈现地表水出现情况
- 展示如何查询地图图层的值
- 添加自定义样式以改进可视化效果,
- 使用阈值创建二值化水体掩膜图层,
- 将地图中心定位到世界上有趣的地方,
- 展示如何重构脚本,使其更易于阅读和维护。
创建基本可视化图表
首先,将以下语句复制到代码编辑器中:
代码编辑器 (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。
在大多数区域,GSW 数据集显示为透明,因为未收集 Landsat 图像的位置(即海洋区域)或 32 年内任何观测均未检测到水的位置均被 遮盖。
检查值
为了探索水体出现频率图层的值,我们将使用代码编辑器的检查器标签页。 首先点击“检查器”标签页,然后点击地图以选择一个位置。检查器标签页将显示您点击的位置存在的每个图层的信息。
在上面的示例中,名为 value 的层的值为 98。单位为百分点,因此该位置大约有 98% 的时间被归类为水体覆盖。
该值是每个月地表水出现值的平均值,它会根据季节性变化进行标准化,如
数据用户指南 (v2)
中所述。
通过重构改进代码
我们的脚本仅包含两条语句,但我们已经有机会重构代码,以便最终脚本更易于阅读和维护。
目前,Map.addLayer() 语句会传递一个参数 occurrence,即我们要在地图上显示的 Earth Engine 影像对象。不过,Map.addLayer() 方法还允许向其传递其他实参。如需快速查看可用的实参,请将光标置于左括号后,然后按“显示代码建议”的键盘快捷键,调出 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)) 会导致像素的不透明度/透明度根据出现值进行设置。
再次运行脚本,查看样式更改后的修订结果。
水域现在变成蓝色了!进展不错!
创建阈值图层
水体出现频率图像包含有关预期水体出现频率的信息,其值范围为 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' });
前往世界各地的有趣地点
通过平移和缩放来探索世界很有趣,但世界很大,有时直接跳转到特定位置会很有帮助。 以下是一系列语句,提供了一些在地表水方面比较有趣的地点。 只需一次取消注释一条语句,脚本在运行时就会转到相应位置。
代码编辑器 (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 });
在下一部分中,您将探索水体出现频率随时间的变化情况。