Earth Engine 使用入门

本入门指南旨在帮助您快速开始使用 Earth Engine JavaScript API 进行编程。如需简要了解 JavaScript 以及有关 Earth Engine API 的更深入练习,请参阅教程。如需了解推荐的 JavaScript 编码风格,请参阅 Google JavaScript 风格指南

借助 Google Earth Engine,用户可以在 Google 基础������上存���的地理参照图像和矢量上运行算法。Google Earth Engine API 提供了一个函数库,可应用于数据以进行显示和分析。Earth Engine 的公共数据目录包含大量公开图像和矢量数据集。您还可以在用户的个人文件夹中创建不公开的资源。

如何使用这些文档

Earth Engine 文档面向熟悉地理空间数据分析的用户。这些文档主要按数据类型进行构建。例如,左侧导航栏包含指向与重要数据类型(例如 ImageImageCollectionFeatureFeatureCollectionGeometryReducerChartJoinArray)相关的部分或页面的链接。本指南仅介绍了这些类型的相关信息,仅供您参考。还有一些部分介绍了机器学习、专用算法或特定于传感器的算法(例如 Landsat 算法)、面向公众的应用数据(资产)管理,以及 Earth Engine 内部运作的重要详细信息。 在深入了解这些内容之前,请先从这里开始!

代码编辑器

代码编辑器是一个用于开发 Earth Engine 应用的交互式环境(图 1)。中间面板提供了一个 JavaScript 代码编辑器。编辑器上方有用于保存当前脚本、运行脚本和清除映射的按钮。获取链接按钮会在地址栏中为脚本生成唯一的网址。底部面板中的地图包含脚本添加的图层。顶部有一个用于搜索数据集和地点的搜索框。左侧面板包含代码示例、已保存的脚本、可搜索的 API 参考文档以及私密数据的资源管理器。右侧面板包含用于查询地图的检查器、输出控制台,以及用于长时间运行的任务的管理器。 右上角的“帮助”按钮 包含指向本指南和其他帮助资源的链接。 如需了解详情,请参阅代码编辑器指南获取帮助指南

代码编辑器
图 1. Earth Engine 代码编辑器,网址为 code.earthengine.google.com

在代码编辑器中打开和运行代码

以下步骤演示了如何打开 Earth Engine 并执行用于显示图片的自定义脚本。为了获得最佳效果,您可能需要安装最新版本的 Chrome(Google 的网络浏览器),该版本可在此处获取。

  1. 前往以下网址打开 Earth Engine 代码编辑器: code.earthengine.google.com
  2. 前往代码编辑器最左侧的脚本标签页。您可以在此处找到一系列用于访问、显示和分析 Earth Engine 数据的示例脚本。
  3. 在“图片集合”下,选择“滤除的复合图”示例。您会在中央控制台中看到一个脚本。按 Run 按钮以执行脚本。“经过过滤的合成图”示例会选择与科罗拉多州和犹他州重叠或位于其边界内的 Landsat 7 图像。然后,它会显示所选图片的真实彩色合成图像。这些示例向您介绍了常用的方法,例如 filter()clip()Map.addLayer()

Earth Engine 数据结构

Earth Engine 中最重要的两个地理数据结构是 ImageFeature,分别对应于光栅数据类型和矢量数据类型。图片由波段和属性字典组成。 地图项由 Geometry 和属性字典组成。一堆图像(例如图像时间序列)由 ImageCollection 处理。一组地图项由 FeatureCollection 处理。Earth Engine 中的其他基本数据结构包括 DictionaryListArrayDateNumberString(如需详细了解基本数据类型,请参阅此教程)。请��必注���,这些都是服务器端对象,其操作方式与客户端 JavaScript 对象不同(了解详情)。

Earth Engine 算法

您可以通过多种方式在 API 中运行操作:

  • 调用附加到对象的方法。
  • 调用算法。
  • 调用 Code Editor 专用函数。
  • 定义新函数。

代码编辑器的 Docs(文档)标签页列出了每个 API 类的方法。例如,Image 类具有 add() 方法:

Code Editor (JavaScript)

var image3 = image1.add(image2);

此方法会将 image2 的频段添加到 image1 的频段。 ee.Algorithms 类别包含目前支持的专用或特定于领域的处理算法列表。例如,如需根据输入数字地形模型 (DEM) 创建地形图层,请执行以下操作:

Code Editor (JavaScript)

var terrainImage = ee.Algorithms.Terrain(dem);

代码编辑器专用函数包括 MapExport 方法,分别用于控制如何将图层添加到地图面板或导出到 Google 云端硬盘。您还可以使用以下方法在 JavaScript 中创建函数

Code Editor (JavaScript)

var myFunction = function(args) {
  // do something
  return something;
};

“映射”部分所示,用户定义的函数非��适用于使用以下方法创建自定义功能或修改集合的元素:

Code Editor (JavaScript)

var collection2 = collection1.map(aFunction);

以下部分将通过各种简单的用例来说明这些概念。

'Hello world!' JavaScript

将信息输出到控制台是一项基本任务,可用于获取有关对象的信息、显示计算的数值结果、显示对象元数据或帮助调试。代码编辑器中标志性的“Hello World!”示例为:

Code Editor (JavaScript)

print('Hello world!');

将这行代码复制到 Code Editor 的代码编辑器中,然后点击 Run。请注意,输出结果会显示在代码编辑器右侧的控制台标签页中。下面的示例与遥感更相关,它会输出 Landsat 8 图像的元数据:

Code Editor (JavaScript)

print(ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318'));

仔细检查控制台中的输出,查看可用于 Landsat 图像的元数据。

向地图添加数据

除了将信息输出到控制台之外,向 Map 添加数据也是可视化地理数据的方法。请使用 Map.addLayer() 执行此操作。在以下示例中,使用 ee.Image() 实例化了 Image(稍后会介绍如何查找这些图片),并使用 Map.addLayer() 将其添加到地图中,然后将地图居中显示在图片上:

Code Editor (JavaScript)

// Load an image.
var image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318');

// Center the map on the image.
Map.centerObject(image, 9);

// Display the image.
Map.addLayer(image);

Map.centerObject() 的第二个参数是缩放级别,数字越大,比例越大(放得越大)。Map 函数的参数在 API 参考文档中进行了详细介绍,您可以通过文档标签页访问该文档。如果图片的外观不令人满意,请使用 Map.addLayer() 的附加参数配置显示参数。例如:

Code Editor (JavaScript)

// Load the image from the archive.
var image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318');

// Define visualization parameters in an object literal.
var vizParams = {bands: ['B5', 'B4', 'B3'], min: 0.02, max: 0.4, gamma: 1.3};

// Center the map on the image and display.
Map.centerObject(image, 9);
Map.addLayer(image, vizParams, 'Landsat 8 false color');

请注意,可视化参数由对象字面量定义,其中包括要显示的波段列表、最小反射率值和最大反射率值,以及伽玛值。 (如需详细了解 Landsat 波段,请点击此处。)如需详细了解图片可视化,请点击此处

使用 Map.addLayer() 将地图项和地图项集合添加到地图。例如:

Code Editor (JavaScript)

var counties = ee.FeatureCollection('TIGER/2018/Counties');
Map.addLayer(counties, {}, 'counties');

查找图片、图片集和地图项集合

您可以通过搜索 Earth Engine 数据目录来发现图片、图片集和地图项集。例如,在搜索字段中输入“Landsat 8”会显示一个栅格数据集列表。(如需查看 Earth Engine 数据集的完整列表,请访问 Earth Engine 数据目录)。 点击数据集名称即可获取简短说明、时间可用性信息、数据提供方和合集 ID。点击 Import 按钮,系统会在脚本顶部自动创建一个 Imports 部分,并为此集合添加一个变量。

或者,复制集合 ID 并将其粘贴到代码中。例如,选择“Landsat 8”搜索的 Tier 1 TOA 结果,然后复制 ID,如下所示:

Code Editor (JavaScript)

var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA');

由于这是一个包含许多图片的集合,这些图片涵盖了地球陆地表面,因此若要在该集合中查找单张图片,需要进行过滤以缩小搜索范围。 或者,您也可以使用合成和拼接技术将图片集合缩减为单张图片。如需详细了解过滤和合成(请参阅减少),请参阅下一部分。

您还可以通过数据目录使用地图项集合。与图像集相比,它们的表示方式较小,但您可以找到国际边界、人口普查区边界、水系边界和保护区边界等。如需详细了解如何导入您自己的矢量数据集,请点击此处

过滤和排序

通常需要按空间和/或时间过滤集合,以限制结果数量。例如,假设您要对 Landsat 8 场景集进行排序,以便查找旧金山的无云场景。首先,需要定义感兴趣的区域。这时,���个点通常���有用。激活 Code Editor 右侧的 Inspector 标签页,然后点击感兴趣区域的中心附近,复制 Inspector 标签页中的坐标,然后使用以下代码构建 Point

Code Editor (JavaScript)

var point = ee.Geometry.Point(-122.262, 37.8719);

构建开始日期和结束日期:

Code Editor (JavaScript)

var start = ee.Date('2014-06-01');
var finish = ee.Date('2014-10-01');

使用点和日期过滤 Landsat 8 集合,然后使用元数据属性(在检查 Landsat 8 场景元数据期间发现)进行排序:

Code Editor (JavaScript)

var filteredCollection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
  .filterBounds(point)
  .filterDate(start, finish)
  .sort('CLOUD_COVER', true);

您可以放心地打印和检查此合集。(如果合集包含的图片过多,则打印速度会非常慢、超时或返回错误)。请注意,集合中的图片是存储在 ImageCollection 的“features”属性中的 List。您可以像上面所示那样,将该集合中的任何图片的 ID 复制到 Image 构造函数中。或者,获取第一张图片(云层覆盖率最低):

Code Editor (JavaScript)

var first = filteredCollection.first();

使用 filter() 作为实参来访问完整的 Earth Engine 过滤功能。ee.Filter(上面使用的 filterBounds()filterDate() 方法是快捷方式)。例如,以下代码会创建 Filter,使用它过滤 FeatureCollection 并显示结果:

Code Editor (JavaScript)

// Load a feature collection.
var featureCollection = ee.FeatureCollection('TIGER/2016/States');

// Filter the collection.
var filteredFC = featureCollection.filter(ee.Filter.eq('NAME', 'California'));

// Display the collection.
Map.setCenter(-119.604, 37.798, 6);
Map.addLayer(filteredFC, {}, 'California');

频段计算

使用 Image 方法对图片执行数学运算。这可能包括波段重组(光谱指数)、图像差分或数学运算(例如乘以常数)。例如,计算相隔 20 年的常态化差值植生指标 (NDVI) 图像之间的差异:

Code Editor (JavaScript)

// This function gets NDVI from Landsat 5 imagery.
var getNDVI = function(image) {
  return image.normalizedDifference(['B4', 'B3']);
};

// Load two Landsat 5 images, 20 years apart.
var image1 = ee.Image('LANDSAT/LT05/C02/T1_TOA/LT05_044034_19900604');
var image2 = ee.Image('LANDSAT/LT05/C02/T1_TOA/LT05_044034_20100611');

// Compute NDVI from the scenes.
var ndvi1 = getNDVI(image1);
var ndvi2 = getNDVI(image2);

// Compute the difference in NDVI.
var ndviDifference = ndvi2.subtract(ndvi1);

请注意,此示例中使用了用户定义的 function。如需详细了解函数,请参阅下一部分。

映射(在 for 循环之外可以执行的操作)

使用 map() 遍历集合中的项。(在 Earth Engine 中,for 循环并非执行此操作的正确方式,应避免使用)。map() 函数可应用于 ImageCollectionFeatureCollectionList,并接受 function 作为其参数。函数的参数是其映射到的集合的元素。这对于以相同方式修改集合的每��元素(例如添加)非常有用。例如,以下代码会向 ImageCollection 中的每个图片添加 NDVI 波段:

Code Editor (JavaScript)

// This function gets NDVI from Landsat 8 imagery.
var addNDVI = function(image) {
  return image.addBands(image.normalizedDifference(['B5', 'B4']));
};

// Load the Landsat 8 TOA data, filter by location and date.
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
  .filterBounds(ee.Geometry.Point(-122.262, 37.8719))
  .filterDate('2014-06-01', '2014-10-01');

// Map the function over the collection.
var ndviCollection = collection.map(addNDVI);

另一项常见任务是向 FeatureCollection 中的地图项添加新属性(或“属性”或“字段”)。在以下示例中,新属性是涉及两个现有属性的计算:

Code Editor (JavaScript)

// This function creates a new property that is the sum of two existing properties.
var addField = function(feature) {
  var sum = ee.Number(feature.get('property1')).add(feature.get('property2'));
  return feature.set({'sum': sum});
};

// Create a FeatureCollection from a list of Features.
var features = ee.FeatureCollection([
  ee.Feature(ee.Geometry.Point(-122.4536, 37.7403),
    {property1: 100, property2: 100}),
    ee.Feature(ee.Geometry.Point(-118.2294, 34.039),
    {property1: 200, property2: 300}),
]);

// Map the function over the collection.
var featureCollection = features.map(addField);

// Print a selected property of one Feature.
print(featureCollection.first().get('sum'));

// Print the entire FeatureCollection.
print(featureCollection);

请注意,为了使用 add() 方法,需要将属性值转换为 ee.Number,以便系统将其识别为数字。集合的类型可以通过 map() 更改。例如:

Code Editor (JavaScript)

// This function returns the image centroid as a new Feature.
var getGeom = function(image) {
  return ee.Feature(image.geometry().centroid(), {foo: 1});
};

// Load a Landsat 8 TOA collection.
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
  .filterBounds(ee.Geometry.Point(-122.262, 37.8719))
  .filterDate('2014-06-01', '2014-10-01');

// Map the function over the ImageCollection.
var featureCollection = ee.FeatureCollection(collection.map(getGeom));

// Print the collection.
print(featureCollection);

请注意,根据图片重心创建的每个地图项都添加了属性 (foo)。在最后一行中,转换会使生成的集合可识别为 FeatureCollection

减少

在 Earth Engine 中,缩减是指跨时间、空间、波段、数组和其他数据结构聚合数据的方法。API 中提供了多种用于此目的的方法。例如,如需对 ImageCollection 进行合成,请使用 reduce() 将集合中的图片缩减为一张图片。一个简单的示例是,创建之前定义的 Landsat 8 集合中云量最少的五个场景的中位数合成图:

Code Editor (JavaScript)

// Load a Landsat 8 TOA collection.
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
  // Filter by date and location.
  .filterBounds(ee.Geometry.Point(-122.262, 37.8719))
  .filterDate('2014-01-01', '2014-12-31')
  // Sort by increasing cloudiness.
  .sort('CLOUD_COVER');

// Compute the median of each pixel for each band of the 5 least cloudy scenes.
var median = collection.limit(5).reduce(ee.Reducer.median());

缩减也是获取 FeatureFeatureCollection 定义的区域中图片的统计信息的方法。假设任务是计算感兴趣区域内的像素平均值。为此,请使用 reduceRegion()。例如:

Code Editor (JavaScript)

// Load and display a Landsat TOA image.
var image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318');
Map.addLayer(image, {bands: ['B4', 'B3', 'B2'], max: 0.3});

// Create an arbitrary rectangle as a region and display it.
var region = ee.Geometry.Rectangle(-122.2806, 37.1209, -122.0554, 37.2413);
Map.addLayer(region);

// Get a dictionary of means in the region.  Keys are bandnames.
var mean = image.reduceRegion({
  reducer: ee.Reducer.mean(),
  geometry: region,
  scale: 30
});

如需详细了解 reducer,请参阅 “Reducer”文档

遮盖

ee.Image 中的每个像素都有一个值和一个掩码,值介于 0(无数据)到 1 之间,掩码介于 0(无数据)到 1 之间。系统会将已掩码的像素(其中 mask==0)视为无数据。当掩码值介于 0 到 1 之间时,像素具有值,但在进行数值计算时,该值会按掩码进行加权。

您可以使用遮罩使像素透明或将其从分析中排除。当蒙版值为零时,像素会被遮盖。继续使用图片差异示例,使用掩码来显示差异间隔内 NDVI 增加和减少的区域:

// This function gets NDVI from Landsat 5 imagery.
var getNDVI = function(image) {
  return image.normalizedDifference(['B4', 'B3']);
};

// Load two Landsat 5 images, 20 years apart.
var image1 = ee.Image('LANDSAT/LT05/C02/T1_TOA/LT05_044034_19900604');
var image2 = ee.Image('LANDSAT/LT05/C02/T1_TOA/LT05_044034_20100611');

// Compute NDVI from the scenes.
var ndvi1 = getNDVI(image1);
var ndvi2 = getNDVI(image2);

// Compute the difference in NDVI.
var ndviDifference = ndvi2.subtract(ndvi1);
// Load the land mask from the SRTM DEM.
var landMask = ee.Image('CGIAR/SRTM90_V4').mask();

// Update the NDVI difference mask with the land mask.
var maskedDifference = ndviDifference.updateMask(landMask);

// Display the masked result.
var vizParams = {min: -0.5, max: 0.5, palette: ['FF0000', 'FFFFFF', '0000FF']};
Map.setCenter(-122.2531, 37.6295, 9);
Map.addLayer(maskedDifference, vizParams, 'NDVI difference');

请注意,在此示例中,NDVI 差异的掩码会由包含 updateMask() 的土地掩码更新。这会将 NDVI 差异像素的遮罩设置为土地遮罩,只要 NDVI 差异遮罩不为零,就会执行此操作。

遮盖功能还可用于从分析中排除数据。请考虑“缩减”部分中的 reduceRegion() 示例。假设任务是计算加利福尼亚州圣克拉拉县的季节性平均 NDVI,不包括多云像素。以下示例演示了多种概念:过滤、映射、缩减和使用云遮罩:

Code Editor (JavaScript)

// This function gets NDVI from a Landsat 8 image.
var addNDVI = function(image) {
  return image.addBands(image.normalizedDifference(['B5', 'B4']));
};

// This function masks cloudy pixels.
var cloudMask = function(image) {
  var clouds = ee.Algorithms.Landsat.simpleCloudScore(image).select(['cloud']);
  return image.updateMask(clouds.lt(10));
};

// Load a Landsat collection, map the NDVI and cloud masking functions over it.
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
  .filterBounds(ee.Geometry.Point([-122.262, 37.8719]))
  .filterDate('2014-03-01', '2014-05-31')
  .map(addNDVI)
  .map(cloudMask);

// Reduce the collection to the mean of each pixel and display.
var meanImage = collection.reduce(ee.Reducer.mean());
var vizParams = {bands: ['B5_mean', 'B4_mean', 'B3_mean'], min: 0.02, max: 0.4};
Map.addLayer(meanImage, vizParams, 'mean');

// Load a region in which to compute the mean and display it.
var counties = ee.FeatureCollection('TIGER/2018/Counties');
var santaClara = ee.Feature(counties.filter(ee.Filter.eq('NAME', 'Santa Clara')).first());
Map.addLayer(santaClara);

// Get the mean of NDVI in the region.
var mean = meanImage.select(['nd_mean']).reduceRegion({
  reducer: ee.Reducer.mean(),
  geometry: santaClara.geometry(),
  scale: 30
});

// Print mean NDVI for the region.
mean.get('nd_mean').evaluate(function(val){
  print('Santa Clara spring mean NDVI:', val);
});