本入门指南旨在帮助您快速开始使用 Earth Engine JavaScript API 进行编程。如需简要了解 JavaScript 以及有关 Earth Engine API 的更深入练习,请参阅教程。如需了解推荐的 JavaScript 编码风格,请参阅 Google JavaScript 风格指南。
借助 Google Earth Engine,用户可以在 Google 基础架构上存储的地理参照图像和矢量上运行算法。Google Earth Engine API 提供了一个函数库,可应用于数据以进行显示和分析。Earth Engine 的公共数据目录包含大量公开图像和矢量数据集。您还可以在用户的个人文件夹中创建不公开的资源。
如何使用这些文档
Earth Engine 文档面向熟悉地理空间数据分析的用户。这些文档主要按数据类型进行构建。例如,左侧导航栏包含指向与重要数据类型(例如 Image
、ImageCollection
、Feature
、FeatureCollection
、Geometry
、Reducer
、Chart
、Join
和 Array
)相关的部分或页面的链接。本指南仅介绍了这些类型的相关信息,仅供您参考。还有一些部分介绍了机器学习、专用算法或特定于传感器的算法(例如 Landsat 算法)、面向公众的应用、数据(资产)管理,以及 Earth Engine 内部运作的重要详细信息。
在深入了解这些内容之前,请先从这里开始!
代码编辑器
代码编辑器是一个用于开发 Earth Engine 应用的交互式环境(图 1)。中间面板提供了一个 JavaScript 代码编辑器。编辑器上方有用于保存当前脚本、运行脚本和清除映射的按钮。获取链接按钮会在地址栏中为脚本生成唯一的网址。底部面板中的地图包含脚本添加的图层。顶部有一个用于搜索数据集和地点的搜索框。左侧面板包含代码示例、已保存的脚本、可搜索的 API 参考文档以及私密数据的资源管理器。右侧面板包含用于查询地图的检查器、输出控制台,以及用于长时间运行的任务的管理器。 右上角的“帮助”按钮 代码编辑器指南和获取帮助指南。
包含指向本指南和其他帮助资源的链接。 如需了解详情,请参阅
在代码编辑器中打开和运行代码
以下步骤演示了如何打开 Earth Engine 并执行用于显示图片的自定义脚本。为了获得最佳效果,您可能需要安装最新版本的 Chrome(Google 的网络浏览器),该版本可在此处获取。
- 前往以下网址打开 Earth Engine 代码编辑器: code.earthengine.google.com。
- 前往代码编辑器最左侧的脚本标签页。您可以在此处找到一系列用于访问、显示和分析 Earth Engine 数据的示例脚本。
- 在“图片集合”下,选择“滤除的复合图”示例。您会在中央控制台中看到一个脚本。按 Run 按钮以执行脚本。“经过过滤的合成图”示例会选择与科罗拉多州和犹他州重叠或位于其边界内的 Landsat 7 图像。然后,它会显示所选图片的真实彩色合成图像。这些示例向您介绍了常用的方法,例如
filter()
、clip()
和Map.addLayer()
。
Earth Engine 数据结构
Earth Engine 中最重要的两个地理数据结构是 Image
和 Feature
,分别对应于光栅数据类型和矢量数据类型。图片由波段和属性字典组成。
地图项由 Geometry
和属性字典组成。一堆图像(例如图像时间序列)由 ImageCollection
处理。一组地图项由 FeatureCollection
处理。Earth Engine 中的其他基本数据结构包括 Dictionary
、List
、Array
、Date
、Number
和 String
(如需详细了解基本数据类型,请参阅此教程)。请务必注意,这些都是服务器端对象,其操作方式与客户端 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);
代码编辑器专用函数包括 Map
和 Export
方法,分别用于控制如何将图层添加到地图面板或导出到 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()
函数可应用于 ImageCollection
、FeatureCollection
或 List
,并接受 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());
缩减也是获取 Feature
或 FeatureCollection
定义的区域中图片的统计信息的方法。假设任务是计算感兴趣区域内的像素平均值。为此,请使用 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); });