Earth Engine 支持由存储在 Google Cloud Storage (GCS) 中的 Cloud Optimized GeoTIFF (COG) 支持的资产。
注册 COG 支持的资产时,Earth Engine 会在创建时为图像的空间和元数据字段编制索引。这样,在集合中使用该图片时,其性能可与标准提取的资源相媲美(请参阅云优化 GeoTIFF (COG) 概览)。
本指南涵盖准备文件、编写清单、提交注册请求、配置权限以及更新或删除已注册的素材资源。
准备工作
在注册 COG 之前,您必须正确设置 Cloud Storage 资源。
存储桶位置
为了让 Earth Engine 能够访问您的 Cloud Storage 存储桶,该存储桶必须位于以下数据中心区域或多区域之一:
us多区域- 包含
us-central1的任何美国双区域 us-central1区域
如果您的存储桶位于任何其他区域数据中心(例如 us-east4 或 europe-west1),Earth Engine 将拒绝注册和读取请求。请参阅支持的 Cloud Storage 存储桶位置。
存储类别和结算
- 我们建议使用 Standard 存储类别。Standard Storage 没有最短存储时长规则,因此如果您更新或替换临时文件,则不会产生提前删除结算罚金。
- 虽然 Earth Engine 计算循环不会产生 Cloud Storage 数据检索附加费,但通过外部工具(例如桌面地理信息系统 (GIS) 软件)访问非 Standard Storage 层级会产生高昂的检索费用。
- 您必须在 Google Cloud 项目中启用结算功能,才能使用 Cloud Storage。请参阅 Cloud Storage 快速入门,开始使用。
准备 COG
Earth Engine 直接从 Cloud Storage 读取 COG,仅提取计算所需的标头和图块,因此文件布局非常重要。TIFF 必须:
- 平铺,具有 16x16 到 2048x2048 的 2 的幂次方方形图块尺寸。为获得最佳性能,我们建议使用 512x512。
- 经过排列,所有图片文件目录 (IFD) 均位于开头。
- 包含 2 的幂概览(如果有)。概览不是必需的,但建议对大于单个图块的图片使用概览。
- 使用 BAND 或 PIXEL 交错(请参阅单波段文件与多波段文件了解权衡)。
如需转换图片,请使用 GDAL 的 COG 驱动程序,该驱动程序可一步生成所需的布局(平铺、概览和标题放置)。为分类数据添加 OVERVIEW_RESAMPLING=NEAREST;默认值为 CUBIC。如需了解压缩、概览和布局建议,请参阅准备外部 COG 的最佳实践。
GDAL 3.11+ CLI
gdal raster convert in.tif out.tif \
-f COG \
--co BIGTIFF=YES \
--co BLOCKSIZE=512 \
--co INTERLEAVE=BAND \
--co OVERVIEWS=IGNORE_EXISTING \
--co COMPRESS=ZSTD \
--co LEVEL=16 \
--co PREDICTOR=YES \
--co NUM_THREADS=ALL_CPUS
传统 CLI
在 3.11 之前的 GDAL 版本中省略 INTERLEAVE=BAND。
gdal_translate in.tif out.tif \
-of COG \
-co BIGTIFF=YES \
-co BLOCKSIZE=512 \
-co INTERLEAVE=BAND \
-co OVERVIEWS=IGNORE_EXISTING \
-co COMPRESS=ZSTD \
-co LEVEL=16 \
-co PREDICTOR=YES \
-co NUM_THREADS=ALL_CPUS
构建清单
无论您是使用 Earth Engine Python 客户端库、earthengine 命令行工具还是 Earth Engine REST API 注册 COG,都必须定义一个图片上传清单,用于指定资源目标位置、Cloud Storage URI 和可选波段元数据。API 和命令行工具将 COG 支持的资源称为外部图片(ee.data.startExternalImageIngestion()、earthengine upload external_image、projects.image.importExternal)。
示例:支持所有波段的单个 COG 如果您的 COG 包含所有波段(例如 RGB),则清单只需要一个图块集:
{
"name": "projects/my-project/assets/my_cog_asset",
"tilesets": [
{
"id": "default_tileset",
"sources": [
{
"uris": [
"gs://google-sample-bucket/my_optimized_image.tif"
]
}
]
}
]
}
示例:多个 COG(每个波段一个) 如果您有不同波段的单独文件(例如,红色、绿色和蓝色在单独的文件中):
{
"name": "projects/my-project/assets/my_multi_band_cog",
"tilesets": [
{
"id": "red_tileset",
"sources": [ { "uris": [ "gs://google-sample-bucket/band_red.tif" ] } ]
},
{
"id": "green_tileset",
"sources": [ { "uris": [ "gs://google-sample-bucket/band_green.tif" ] } ]
}
],
"bands": [
{ "id": "R", "tilesetId": "red_tileset", "tilesetBandIndex": 0 },
{ "id": "G", "tilesetId": "green_tileset", "tilesetBandIndex": 0 }
]
}
清单限制
由 COG 支持的素材资源的清单具有一些限制,这些限制不适用于标准提取清单:
- 单个存储桶:清单中的所有 URI 都必须位于同一 Cloud Storage 存储桶中。
- 每个来源一个 URI:每个
ImageSource必须只包含一个 URI。您无法将多个文件拼接成单个图块集来源。如需拼接多个 COG 场景,请将每个 COG 注册为一项资产,然后使用.mosaic()将它们合并到ee.ImageCollection中。 - 无
mask_bands:不支持顶级mask_bands字段。在清单中使用missingData,或确保 TIFF 具有内部 nodata 值。 - tileset 中没有
data_type:请勿在tilesets部分中指定data_type;系统会自动检测。 - 来源中没有
dimensions:请勿在ImageSource中指定dimensions。 - 否
subdataset_prefix/subdataset_suffix。 - 没有
min_tile_area_ratio或skip_metadata_read。
提交注册请求
您可以使用 Earth Engine Python 客户端库、earthengine 命令行工具或 Earth Engine REST API 将清单提交到 Earth Engine。选择最适合您工作流的方法。
Python 客户端库
在 Python 脚本或 Jupyter 笔记本中,初始化项目后使用 Earth Engine Python 客户端库 (ee.data):
import ee
# 1. Authenticate and initialize
ee.Authenticate()
ee.Initialize(project='your-project-id')
# 2. Define the manifest as a Python dictionary
manifest = {
"name": "projects/your-project-id/assets/my_cog_asset",
"tilesets": [
{
"id": "default_tileset",
"sources": [
{
"uris": [
"gs://google-sample-bucket/my_optimized_image.tif"
]
}
]
}
]
}
# 3. Register the asset
result = ee.data.startExternalImageIngestion(manifest)
print(f"Asset registered: {result['name']}")
命令行工具
在终端中,将清单保存到名为 manifest.json 的文件中,然后运行 earthengine 上传命令:
# 1. Verify your environment is authenticated
earthengine authenticate
# 2. Register the asset
earthengine --project your-project-id \
upload external_image \
--manifest manifest.json
REST API
对于不使用客户端库的自动化工作流,请直接向 Earth Engine REST API 端点 projects.image.importExternal 发送已获授权的 POST 请求(此处使用 Python 进行演示):
import json
from pprint import pprint
import ee
from google.auth.transport.requests import AuthorizedSession
# 1. Authenticate and start an authorized HTTP session
ee.Authenticate()
ee_project = 'your-project-id'
session = AuthorizedSession(
ee.data.get_persistent_credentials().with_quota_project(ee_project)
)
# 2. Define the REST request body wrapping the manifest
request = {
'imageManifest': {
'name': f'projects/{ee_project}/assets/my_cog_asset',
'tilesets': [
{
'id': 'default_tileset',
'sources': [
{
'uris': [
'gs://google-sample-bucket/my_optimized_image.tif'
]
}
]
}
]
}
}
# 3. Send the POST request
url = (
'https://earthengine.googleapis.com/v1alpha/'
f'projects/{ee_project}/image:importExternal'
)
response = session.post(url=url, data=json.dumps(request))
pprint(json.loads(response.content))
提交后,注册请求会启动轻量级元数据索引编制操作。由于 COG 注册不会复制像素数据,因此此操作通常会在几秒钟内完成。
配置权限
与标准 Earth Engine 资产不同,COG 的像素数据保留在 Cloud Storage 中。与他人共享由 COG 支持的资产时,您必须向他们授予对 Earth Engine 资产和 Cloud Storage 文件的读取权限。
授予 Cloud Storage 存储桶权限
协作者需要拥有从 Cloud Storage 读取文件的权限。
所需权限:
storage.buckets.get(用于检索存储桶元数据和位置)storage.objects.get(用于读取像素数据)
您可以使用以下标准 Cloud Storage 角色授予这些权限:
- Storage Bucket Viewer(提供
storage.buckets.get权限,用于读取存储桶元数据和位置) - Storage Object Viewer(提供
storage.objects.get权限以读取像素数据)
在 Google Cloud 控制台中进行配置的步骤:
- 前往 Cloud Storage 浏览器。
- 点击您的存储桶名称。
- 选择权限标签页。
- 点击授予访问权限。
- 添加协作者的邮箱(或 Google 群组,或
allUsers,以允许公开访问)。 - 分配 Storage Bucket Viewer 和 Storage Object Viewer 角色。
- 点击保存。
共享 Earth Engine 资产
使用 Earth Engine 资源管理器或 CLI 共享资源本身。如需了解详情,请参阅资产管理指南。
更新、替换和删除 COG 支持的资产
COG 支持的资产是指向 Cloud Storage 中特定版本文件的指针,以及 Earth Engine 在您注册该文件时编入索引的元数据(足迹、投影、波段和概览布局)。Earth Engine 会固定文件版本,以便此元数据不会与像素不同步,这也是更新 COG 支持的资产与更新标准资产的不同之处。
对象世代
注册 COG 时,Earth Engine 会记录 Cloud Storage 对象的世代(其版本号)以及 URI。您可以在素材资源的元数据中看到固定的世代;它在 URI 上显示为 #<generation> 后缀:
Python
asset = ee.data.getAsset('projects/your-project-id/assets/my_cog_asset')
print(asset['tilesets'][0]['sources'][0]['uris'])
# ['gs://google-sample-bucket/my_optimized_image.tif#1750427474244728']
您也可以在注册(或重新注册)素材资源时,在清单 URI 中添加 #<generation> 后缀,自行固定特定版本。如果没有此参数,Earth Engine 会读取当前对象,并固定它找到的任何世代。明确固定有助于回滚到启用了对象版本控制的存储桶所保留的早期版本。
如果您在 Cloud Storage 中覆盖该文件,它会获得一个新世代;如果您删除该文件,则固定的世代会消失。无论哪种情况,读取资产的像素都会失败,除非存储桶上的对象版本控制保留了旧版本,在这种情况下,Earth Engine 会继续读取旧像素。无论采用哪种方式,使用索引记录的元数据操作(例如 ee.data.getAsset()、bandNames() 和集合过滤)都会继续正常运行。
更改素材资源的文件后更新素材资源
如需将现有素材资源指向其文件的新版本,请使用相同的素材资源名称重新注册该素材资源,并启用覆盖功能。Earth Engine 会在一次同步调用中重新读取 GeoTIFF 标头、重新为元数据编制索引,并固定新世代。素材资源的现有权限会保留,但其属性、时间范围和波段名称来自新清单,因此请添加您之前使用 ee.data.updateAsset() 设置的所有内容。
- Python:
ee.data.startExternalImageIngestion(manifest, allow_overwrite=True) - 命令行:
earthengine upload external_image --force --manifest manifest.json - REST API:在
projects.image.importExternal请求正文中,将"overwrite": true作为顶级字段与"imageManifest"一起添加。
您无需先删除素材资源,删除素材资源反而会适得其反:独立素材资源会失去其权限,集合中的图片会短暂地从集合中消失。请注意,ee.data.updateAsset() (projects.assets.patch) 只能更改属性、时间范围和波段名称,而无法更改资产指向的文件。
独立生命周期
Earth Engine 资产和 Cloud Storage 对象是分开管理的:
- 删除 Earth Engine 资产(
earthengine rm或ee.data.deleteAsset())只会移除资产记录。Cloud Storage 中的文件不会受到影响。 - 删除 Cloud Storage 中的文件不会移除素材资源;它仍会显示在列表及其集合中(请参阅对象世代)。
处理大型集合
Earth Engine API 中没有批量或递归删除功能:每个资产都必须单独删除,并且集合必须为空才能删除。earthengine rm -r 会为您处理此问题,但会逐个发出删除请求,因此包含数万张图片的集合可能需要数小时才能移除。
- 如需替换合集的图片,请覆盖而不是删除。 按名称重新注册每个映像,并启用覆盖(见上文)。这样,每张图片只需要一个请求,而不是两个,可以始终保持集合中填充了内容,并避免删除和重新创建集合本身(集合本身是其权限所在的位置)。仅删除不在新集合中的图片。
如需删除许多资产,请通过脚本并行执行。使用
ee.data.listAssets()列出资源(使用BASIC视图,该视图仅返回名称和类型,而不是每张图片的完整元数据),并从小型线程池中删除这些资源。素材资源请求会共享项目级速率限制,因此请保持适度的并发(大约 10 个工作器),并让客户端库的内置重试机制处理所有429 Too Many Requests响应:Python
import concurrent.futures import ee ee.Initialize(project='your-project-id') collection = 'projects/your-project-id/assets/my_collection' listing = ee.data.listAssets({'parent': collection, 'view': 'BASIC'}) asset_ids = [a['name'] for a in listing['assets']] def delete(asset_id): try: ee.data.deleteAsset(asset_id) except ee.EEException as e: return f'{asset_id}: {e}' with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: failures = [f for f in executor.map(delete, asset_ids) if f] if failures: print('\n'.join(failures)) else: ee.data.deleteAsset(collection)只有在所有图片都被删除的情况下,集合才会被删除,因此,如果部分删除失败,集合仍会保留,以便重新运行。
同样的模式也适用于注册多个映像:将辅助函数中的
ee.data.deleteAsset(asset_id)替换为ee.data.startExternalImageIngestion(manifest, allow_overwrite=True),并将其映射到清单列表中。即使在首次运行时也传递allow_overwrite=True,可使批处理在部分失败后安全地重新运行,因为任何已创建的资源都会被替换,而不会导致错误。
使用已注册的素材资源
注册后,您可以在 Earth Engine 脚本中访问 COG 支持的图片素材资源,就像访问任何标准提取的图片素材资源一样:
JavaScript
var image = ee.Image('projects/your-project-id/assets/my_cog_asset');
Python
image = ee.Image('projects/your-project-id/assets/my_cog_asset')
如需了解有关权限、更新文件和管理大型集合的常见问题解答,请参阅常见问题解答的 COG 部分。