本指南介绍了如何使用 Google Colab 快速开始通过 Python 向 Earth Engine REST API 发出查询。从其他语言和环境访问该 API 时,也适用相同的概念。
注意: REST API 包含新功能和高级功能,可能不适合所有用户。如果您刚开始接触 Earth Engine,请先参阅 JavaScript 指南。
准备工作
请按照这些说明执行以下操作:
设置 Colab 笔记本
如果您是从头开始本快速入门,可以点击 Colab 起始页中的新建笔记本,创建一个新的 Colab 笔记本,然后将以下代码示例输入到新的代码单元中。Colab 已安装 Cloud SDK。其中包括 gcloud 命令行工具,可用于管理 Cloud 服务。或者,您也可以点击本页开头的按钮,运行演示笔记本。
向 Google Cloud 进行身份验证
首先需要登录,以便向 Google Cloud 发出经过身份验证的请求。
在 Colab 中,您可以运行:
PROJECT = 'my-project' !gcloud auth login --project {PROJECT}
(或者,如果您在本地运行,则从命令行运行,前提是您已安装 Cloud SDK:)
PROJECT='my-project' gcloud auth login --project $PROJECT
接受使用 Google 用户账号登录的选项,然后完成登录流程。
获取服务账号的私钥文件
您必须先下载私钥文件,然后才能使用服务账号进行身份验证。如需在 Colab 中执行此操作,请下载到笔记本虚拟机:
SERVICE_ACCOUNT='foo-name@project-name.iam.gserviceaccount.com' KEY = 'my-secret-key.json' !gcloud iam service-accounts keys create {KEY} --iam-account {SERVICE_ACCOUNT}
或者,也可以通过命令行:
SERVICE_ACCOUNT='foo-name@project-name.iam.gserviceaccount.com' KEY='my-secret-key.json' gcloud iam service-accounts keys create $KEY --iam-account $SERVICE_ACCOUNT
访问和测试凭证
现在,您可以向 Earth Engine API 发送第一个查询了。使用私钥获取凭据。使用这些凭据创建授权会话,以发出 HTTP 请求。您可以将此代码输入到 Colab 笔记本的新代码单元中。(如果您使用的是命令行,则需要确保已安装必要的库)。
from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account credentials = service_account.Credentials.from_service_account_file(KEY) scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/cloud-platform']) session = AuthorizedSession(scoped_credentials) url = 'https://earthengine.googleapis.com/v1alpha/projects/earthengine-public/assets/LANDSAT' response = session.get(url) from pprint import pprint import json pprint(json.loads(response.content))
如果一切配置正确,运行此命令将生成如下所示的输出:
{'id': 'LANDSAT',
'name': 'projects/earthengine-public/assets/LANDSAT',
'type': 'FOLDER'}
选择数据集
您可以使用 Earth Engine 代码编辑器(网址为 code.earthengine.google.com)搜索和探索可用数据集。我们来查找一些 Sentinel 2 数据。(如果您是首次使用代码编辑器,系统会在您登录时提示您授权其代表您访问 Earth Engine。)在代码编辑器顶部的搜索框中搜索“sentinel”。系统会显示多个光栅数据集:

点击“Sentinel-2: MultiSpectral Instrument (MSI), Level-1C”:

像这样的数据集说明页面包含您使用 Earth Engine 公共 Data Catalog 中的任何数据集所需的关键信息,包括数据集的简要说明、指向数据提供商的链接(可获取更多详细信息)、可能适用于数据集的任何使用限制的相关信息,以及数据集的 Earth Engine 资产 ID。
在本例中,我们在窗口右侧看到,这是一个路径为 COPERNICUS/S2_HARMONIZED 的图片集资源。
查询特定图片
此 Sentinel-2 数据集包含 2015 年至今覆盖全球的 200 多万张图像。我们针对该图片集合发出 projects.assets.listImages 查询,以查找 2017 年 4 月的一些数据,这些数据具有低云量,并且包含加利福尼亚州山景城的一个特定点。
import urllib coords = [-122.085, 37.422] project = 'projects/earthengine-public' asset_id = 'COPERNICUS/S2_HARMONIZED' name = '{}/assets/{}'.format(project, asset_id) url = 'https://earthengine.googleapis.com/v1alpha/{}:listImages?{}'.format( name, urllib.parse.urlencode({ 'startTime': '2017-04-01T00:00:00.000Z', 'endTime': '2017-05-01T00:00:00.000Z', 'region': '{"type":"Point", "coordinates":' + str(coords) + '}', 'filter': 'CLOUDY_PIXEL_PERCENTAGE < 10', })) response = session.get(url) content = response.content for asset in json.loads(content)['images']: id = asset['id'] cloud_cover = asset['properties']['CLOUDY_PIXEL_PERCENTAGE'] print('%s : %s' % (id, cloud_cover))
此脚本会查询集合中匹配的图片,解码生成的 JSON 响应,并输出每个匹配图片素材资源的资产 ID 和云量。输出应如下所示:
COPERNICUS/S2_HARMONIZED/20170420T184921_20170420T190203_T10SEG : 4.3166
COPERNICUS/S2_HARMONIZED/20170430T190351_20170430T190351_T10SEG : 0
显然,该点上方有两张图片是在本月拍摄的,且云量较低。
检查特定映像
其中一个匹配项的云量似乎基本上为零。我们来详细了解一下该资产,其 ID 为 COPERNICUS/S2_HARMONIZED/20170430T190351_20170430T190351_T10SEG。请注意,所有公开目录资源都属于项目 earthengine-public。以下 Python 代码段会发出 projects.assets.get 查询,以按 ID 提取该特定资产的详细信息,输出可用的数据波段,并输出有关第一个波段的更详细信息:
asset_id = 'COPERNICUS/S2_HARMONIZED/20170430T190351_20170430T190351_T10SEG' name = '{}/assets/{}'.format(project, asset_id) url = 'https://earthengine.googleapis.com/v1alpha/{}'.format(name) response = session.get(url) content = response.content asset = json.loads(content) print('Band Names: %s' % ','.join(band['id'] for band in asset['bands'])) print('First Band: %s' % json.dumps(asset['bands'][0], indent=2, sort_keys=True))
输出应如下所示:
Band Names: B1,B2,B3,B4,B5,B6,B7,B8,B8A,B9,B10,B11,B12,QA10,QA20,QA60
First Band: {
"dataType": {
"precision": "INTEGER",
"range": {
"max": 65535
}
},
"grid": {
"affineTransform": {
"scaleX": 60,
"scaleY": -60,
"translateX": 499980,
"translateY": 4200000
},
"crsCode": "EPSG:32610",
"dimensions": {
"height": 1830,
"width": 1830
}
},
"id": "B1",
"pyramidingPolicy": "MEAN"
}
数据波段列表与我们之前在数据集说明中看到的内容相对应。我们可以看到,此数据集在 EPSG:32610 坐标系(即 UTM Zone 10N)中包含 16 位整数数据。第一个波段的 ID 为 B1,分辨率为每像素 60 米。在此坐标系中,图片的起点位于位置 (499980,4200000)。
affineTransform.scaleY 的负值表示原点位于图像的西北角,通常情况下:y 像素索引增加对应于 y 空间坐标减少(向南)。
正在提取像素值
我们来发出 projects.assets.getPixels 查询,以从此图片的高分辨率波段中提取一些数据。数据集说明页面显示,波段 B2、B3、B4 和 B8 的分辨率为每像素 10 米。此脚本会从这四个波段中提取左上角 256x256 像素的数据图块。以 numpy NPY 格式加载数据,可以轻松地将响应解码为 Python 数据数组。
import numpy import io name = '{}/assets/{}'.format(project, asset_id) url = 'https://earthengine.googleapis.com/v1alpha/{}:getPixels'.format(name) body = json.dumps({ 'fileFormat': 'NPY', 'bandIds': ['B2', 'B3', 'B4', 'B8'], 'grid': { 'affineTransform': { 'scaleX': 10, 'scaleY': -10, 'translateX': 499980, 'translateY': 4200000, }, 'dimensions': {'width': 256, 'height': 256}, }, }) pixels_response = session.post(url, body) pixels_content = pixels_response.content array = numpy.load(io.BytesIO(pixels_content)) print('Shape: %s' % (array.shape,)) print('Data:') print(array)
输出应如下所示:
Shape: (256, 256)
Data:
[[( 899, 586, 351, 189) ( 918, 630, 501, 248) (1013, 773, 654, 378) ...,
(1014, 690, 419, 323) ( 942, 657, 424, 260) ( 987, 691, 431, 315)]
[( 902, 630, 541, 227) (1059, 866, 719, 429) (1195, 922, 626, 539) ...,
( 978, 659, 404, 287) ( 954, 672, 426, 279) ( 990, 678, 397, 304)]
[(1050, 855, 721, 419) (1257, 977, 635, 569) (1137, 770, 400, 435) ...,
( 972, 674, 421, 312) (1001, 688, 431, 311) (1004, 659, 378, 284)]
...,
[( 969, 672, 375, 275) ( 927, 680, 478, 294) (1018, 724, 455, 353) ...,
( 924, 659, 375, 232) ( 921, 664, 438, 273) ( 966, 737, 521, 306)]
[( 920, 645, 391, 248) ( 979, 728, 481, 327) ( 997, 708, 425, 324) ...,
( 927, 673, 387, 243) ( 927, 688, 459, 284) ( 962, 732, 509, 331)]
[( 978, 723, 449, 330) (1005, 712, 446, 314) ( 946, 667, 393, 269) ...,
( 949, 692, 413, 271) ( 927, 689, 472, 285) ( 966, 742, 516, 331)]]
如需从此图片中选择一组不同的像素,只需相应地指定 affineTransform 即可。请注意,affineTransform 是在图像的空间坐标参考系中指定的;如果您想改为调整原点在像素坐标中的位置,请使用以下简单公式:
request_origin = image_origin + pixel_scale * offset_in_pixels
生成缩略图
我们可以使用类似的机制来生成此图片的 RGB 缩略图。我们不会请求原始分辨率的数据,而是会明确指定区域和图片尺寸。如需获取整张图片的缩略图,我们可以使用图片的足迹几何图形作为请求区域。最后,通过指定红色、绿色和蓝色图像波段以及适当的数据值范围,我们可以获得一张美观的 RGB 缩略图。
综上所述,Python 代码段如下所示(使用 Colab IPython 图片显示 widget):
url = 'https://earthengine.googleapis.com/v1alpha/{}:getPixels'.format(name) body = json.dumps({ 'fileFormat': 'PNG', 'bandIds': ['B4', 'B3', 'B2'], 'region': asset['geometry'], 'grid': { 'dimensions': {'width': 256, 'height': 256}, }, 'visualizationOptions': { 'ranges': [{'min': 0, 'max': 3000}], }, }) image_response = session.post(url, body) image_content = image_response.content from IPython.display import Image Image(image_content)
以下是生成的缩略图:
在 Google Colab 中运行
在 GitHub 上查看源代码