如果您需要比代码编辑器界面或 “earthengine”命令行工具的 upload
命令提供的更灵活的方式来将图片上传到 Google Earth Engine (EE),可以使用名为“清单”的 JSON 文件描述图片上传,并使用命令行工具的 upload image --manifest
命令。
如需查看完整示例,请参阅此 Colab 笔记本,其中演示了如何使用清单将图片图块作为单个素材资源上传。
一次性设置
- 清单上传功能仅适用于位于 Google Cloud Storage 中的文件。 如需开始使用 Google Cloud Storage,请创建一个 Google Cloud 项目(如果您还没有的话)。请注意,设置时需要指定用于结算的信用卡。EE 本身目前不会向任何人收费,但如果您先将文件转移到 Google Cloud Storage,然后再将其上传到 EE,则需要支付一笔小费用。对于典型的上传数据大小(几十或几百 GB),费用将非常低。
- 在您的项目中,启用 Cloud Storage API 并创建存储分区。
- 安装 Earth Engine Python 客户端。其中包含
earthengine
命令行工具,我们将使用该工具上传数据。 - 对于自动上传,您可能需要使用与您的项目关联的 Google Cloud 服务账号。您无需服务账号即可进行测试,但请在有空时开始熟悉使用服务账号。
如果将非常大的源文件(100 GB 或更大)拆分为多个图块,上传速度可能会更快。
资产 ID 和名称
对于 Cloud 项目拥有的资产,请使用以下命名惯例:projects/some-project-id/assets/some-asset-id
。
了解旧版项目和用户自有资产的素材资源名称
对于较旧的旧版项目,清单中的资源名称需要与 Earth Engine 中其他位置显示的资源 ID 略有不同。如需上传资产 ID 以 users/some_user
或 projects/some_project
开头的资产,清单中的资产名称必须在 ID 前面附加字符串 projects/earthengine-legacy/assets/
。例如,应使用名称 projects/earthengine-legacy/assets/users/username/my_geotiff
上传 EE 资产 ID users/username/my_geotiff
。
是的,这意味着 projects/some_projects/some_asset
等 ID 会转换为包含两次 projects
的名称:projects/earthengine-legacy/assets/projects/some_projects/some_asset
。这很容易让人混淆,但为了符合 Google Cloud API 标准,这是必要的。
使用清单
以下代码块显示了一个基本清单。该脚本会从名为 gs://earthengine-test
的 Google Cloud Storage 存储分区中上传名为 small.tif
的文件。
{ "name": "projects/some-project-id/assets/some-asset-id", "tilesets": [ { "sources": [ { "uris": [ "gs://earthengine-test/small.tif" ] } ] } ] }
如需使用该脚本,请将其保存到名为 manifest.json
的文件中,然后运行以下命令:
earthengine upload image --manifest /path/to/manifest.json
(文件 gs://earthengine-test/small.tif
存在且可供公开读取,您可以将其用于测试。)
图块集
JSON 清单结构略显复杂,但这有助于提供足够的灵活性来解决一个常见的上传问题:如何描述将来自多个源文件的像素组合到单个素材资源中的所有可能方式。具体而言,有两种独立的方法可以将文件分组:
- 马赛克。有时,多个文件代表多个图块(例如,每个图块为 1x1 度平方)。此类文件必须拼接(合并在一起)到 EE 素材资源中的同一频段。
- 分开使用各个频段。有时,多个文件代表多个频段。此类文件必须作为 EE 素材资源中的频段堆叠在一起。
(可能需要同时使用这两种方式,但这种情况很少见。)
为了描述这些选项,清单引入了图块集的概念。单个图块集对应于单个 GDAL 源。 因此,单个图块集中的所有来源都必须具有相同的 GDAL 结构(波段数和类型、投影、转换、缺失值)。由于 GDAL 源可以包含多个波段,因此一个图块集可能包含多个 EE 波段的数据。
对于拼接数据提取,清单将如下所示:
{ "name": "projects/some-project-id/assets/some-asset-id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/N30W22.tif" ] }, { "uris": [ "gs://bucket/N31W22.tif" ] } ] } ] }
对于单独的频段,清单将如下所示(您还需要添加 bands
部分,如下文所述):
{ "name": "projects/some-project-id/assets/some-asset-id", "bands": ..., "tilesets": [ { "id": "tileset_for_band1", "sources": [ { "uris": [ "gs://bucket/band1.tif" ] } ] }, { "id": "tileset_for_band2", "sources": [ { "uris": [ "gs://bucket/band2.tif" ] } ] } ] }
请注意,对于单独的图层,我们必须为每个图块集分配不同的图块集 ID,以便于区分。图块集 ID 可以是任意字符串,这些字符串不会保留在上传的资源中。图块集 ID 仅用于提取过程中,以区分堆叠的图块集。
频段
第二个重要概念是将源文件与 EE 素材资源频段进行匹配。
这可以使用清单的 bands
部分来完成。
可以省略 bands
部分,在这种情况下,系统会先根据第一个图块集的文件创建条带,然后根据下一个图块集创建条带,以此类推。
默认情况下,频段的名称为“b1”“b2”等。如需替换默认频段名称,请在末尾添加“bands”部分,如下所示:
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/rgb.tif" ] } ] } ], "bands": [ { "id": "R", "tilesetBandIndex": 0 }, { "id": "G", "tilesetBandIndex": 1 }, { "id": "B", "tilesetBandIndex": 2 } ] }
EE 带的数量必须与所有图块集的带总数相同。
如果您不想提取文件中的所有波段,可以使用 tilesetBandIndex
字段指明应提取哪些 GDAL 波段。
第一个乐段的 tilesetBandIndex 为 0。
示例:
假设源文件有四个波段:“tmin”“tmin_error”“tmax”“tmax_error”。我们只想提取“tmin”和“tmax”。相关清单部分将如下所示:
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "id": "temperature", "sources": [ { "uris": [ "gs://bucket/temperature.tif" ] } ] } ], "bands": [ { "id": "tmin", "tilesetBandIndex": 0, "tilesetId": "temperature" }, { "id": "tmax", "tilesetBandIndex": 2, "tilesetId": "temperature" } ] }
遮罩频段
频段遮盖由清单的 maskBands
组件控制。
支持三种可能的掩码配置(但始终假定掩码波段是某个文件中的最后一个波段)。
- 用于遮盖同一文件中的所有数据带。
- 用于遮盖来自所有其他文件的所有数据带。
- 针对部分数据带进行遮盖。
1. 最常见的情况是,单个 GeoTIFF 的最后一个波段用作其他波段的掩码。这仅适用于类型为字节的 GeoTIFF。使用以下清单:
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "id": "data_tileset", "sources": [ { "uris": [ "gs://bucket/data_file.tif" ] } ] } ], "bands": [ { "id": "data_band", "tilesetId": "data_tileset" }, { "id": "qa_band", "tilesetId": "data_tileset" } ], "maskBands": [ { "tilesetId": "data_tileset" } ] }
2. 如需将掩码 GeoTIFF 用作另一个 GeoTIFF 中的所有波段的掩码,请使用以下清单:
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "id": "data_tileset", "sources": [ { "uris": [ "gs://bucket/data_file.tif" ] } ] }, { "id": "mask_tileset", "sources": [ { "uris": [ "gs://bucket/mask_file.tif" ] } ] } ], "bands": [ { "id": "data_band", "tilesetId": "data_tileset" }, { "id": "qa_band", "tilesetId": "data_tileset" } ], "maskBands": [ { "tilesetId": "mask_tileset" } ] }
3. 如需将 GeoTIFF 用作另一个文件中特定波段的掩码,请使用以下清单(与上例的不同之处在于,maskBands
中的 bandIds
字段已设置):
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "id": "data_tileset", "sources": [ { "uris": [ "gs://bucket/data_file.tif" ] } ] }, { "id": "mask_tileset", "sources": [ { "uris": [ "gs://bucket/mask_file.tif" ] } ] } ], "bands": [ { "id": "data_band", "tilesetId": "data_tileset" }, { "id": "qa_band", "tilesetId": "data_tileset" } ], "maskBands": [ { "tilesetId": "mask_tileset", "bandIds": ["data_band"] } ] }
在上一个示例中,我们使用了 data_tileset
图块集的两个图层,但仅对其中一个图层 (data_band
) 应用了遮罩,如仅提供的 maskBands
列表对象的 bandIds
字段所指定。
请注意,只有 maskBands
中提及的图块集的最后一个带状图层会用作掩码带状图层。
关于金字塔式传销的政策
在提取期间,Earth Engine 构建图片金字塔时,必须反复将 2x2 像素网格缩减为单个像素,并以某种方式转换像素值。默认情况下,系统会对像素值求平均值。在大多数情况下,如果光栅图像带表示的是大致连续的数据,则求平均值是正确的做法。不过,在以下两种情况下,依赖默认值会产生不正确的结果,在这种情况下,必须设置频段定义中的 pyramidingPolicy
字段(如果未设置,则默认假定其值为“MEAN”)。
对于栅格图像的分类(例如土地覆盖分类),最合理的像素金字塔化方法是,取四个值中的多数值来生成下一个值。这可以使用“MODE”金字塔式政策来实现:
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/landcover.tif" ] } ] } ], "bands": [ { "id": "landcover", "pyramidingPolicy": "MODE" } ] }
对于“MEAN”和“MODE”均不适用的光栅图像带(例如,位填充像素),应使用“SAMPLE”金字塔化政策。“SAMPLE”始终采用每个 2x2 网格的左上角像素的值。以下示例将“MEAN”金字塔化政策分配给表示连续变量的波段(“NDVI”),并将“SAMPLE”分配给数据的“QA”波段。
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/ndvi.tif" ] } ] } ], "bands": [ { "id": "NDVI", "tilesetBandIndex": 0, "pyramidingPolicy": "MEAN" }, { "id": "QA", "tilesetBandIndex": 1, "pyramidingPolicy": "SAMPLE" } ] }
开始时间和结束时间
所有素材资源都应指定开始时间和结束时间,以便为数据提供更多背景信息,尤其是在将其纳入合集时。这些字段并非必填,但我们强烈建议您尽可能使用它们。
开始时间和结束时间通常是指观察时间,而不是源文件生成的时间。
为简单起见,结束时间被视为不含此时间的边界。例如,对于时长恰好为一天的素材资源,请将两个连续日期的午夜(例如 1980-01-31T00:00:00 和 1980-02-01T00:00:00)作为开始时间和结束时间。 如果资产没有时长,请将结束时间设置为与开始时间相同。 将清单中的时间表示为 ISO 8601 字符串。我们建议假定结束时间不包括该时间(例如,对于每日素材资源,结束时间为次日凌晨),以简化日期值。
示例:
{ "name": "projects/some-project-id/assets/some-asset-id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/img_20190612.tif" ] } ] } ], "startTime": "1980-01-31T00:00:00Z", "endTime": "1980-02-01T00:00:00Z" }
清单结构参考文档
以下 JSON 结构包含所有可能的图片上传清单字段。 如需查找字段定义,请参阅以下 清单字段定义部分。
{ "name": <string>, "tilesets": [ { "dataType": <string>, "id": <string>, "crs": <string>, "sources": [ { "uris": [ <string> ], "affineTransform": { "scaleX": <double>, "shearX": <double>, "translateX": <double>, "shearY": <double>, "scaleY": <double>, "translateY": <double> } } ] } ], "bands": [ { "id": <string>, "tilesetId": <string>, "tilesetBandIndex": <int32>, "missingData": { "values": [<double>] }, "pyramindingPolicy": <string> } ], "maskBands": [ { "tilesetId": <string>, "bandIds": [ <string> ] } ], "footprint": { "points": [ { "x": <double>, "y": <double> } ], "bandId": <string> }, "missingData": { "values": [<double>] }, "pyramidingPolicy": <string>, "uriPrefix": <string>, "startTime": { "seconds": <integer> }, "endTime": { "seconds": <integer> }, "properties": { <unspecified> } }
清单字段定义
名称
string
要创建的素材资源的名称。
name
采用“projects/*/assets/**”格式(例如“projects/earthengine-legacy/assets/users/USER/ASSET”)。
图块集
list
用于定义功能块集的属性的字典列表。
如需了解详情,请参阅以下 tilesets
字典元素字段。
tilesets[i].dataType
string
指定数据的数字数据类型。默认值为 GDAL 报告的类型,在这种情况下,无需进行定义。
数据类型 | 值 |
---|---|
未指定 | "DATA_TYPE_UNSPECIFIED" |
8 位有符号整数 | “INT8” |
8 位无符号整数 | "UINT8" |
16 位有符号整数 | "INT16" |
16 位无符号整数 | "UINT16" |
32 位有符号整数 | “INT32” |
32 位无符号整数 | "UINT32" |
32 位浮点数 | “FLOAT32” |
64 位浮点数 | "FLOAT64" |
tilesets[i].id
string
图块集的 ID。在资源清单中指定的图块集之间必须是唯一的。此 ID 会在处理步骤中舍弃;它仅用于将图块集与乐队相关联。空字符串是有效的 ID。
tilesets[i].crs
string
像素网格的坐标参考系统,应尽可能指定为标准代码(例如 EPSG 代码),否则应采用 WKT 格式。
tilesets[i].sources
list
定义图片文件及其附件属性的字典列表。如需了解详情,请参阅以下 sources
字典元素字段。
tilesets[i].sources[j].uris
list
要提取的数据的 URI 列表。仅支持 Google Cloud Storage URI。每个 URI 都必须采用以下格式指定:gs://bucket-id/object-id
。
主对象应是列表的第一个元素,侧边栏应在后面列出。每个 URI 都以 ImageManifest.uriPrefix
(如果已设置)为前缀。
tilesets[i].sources[j].affineTransform
dictionary
可选的仿射转换。仅当 uris
(包括所有边车)中的数据不足以放置像素时,才应指定此值。
以字典的形式提供,其中包含以下键:“scaleX”“shearX”“translateX”“shearY”“scaleY”“translateY”。
如需了解详情,请参阅
此参考文档。
键和值示例:
{ "scaleX": 0.1, "shearX": 0.0, "translateX": -180.0, "shearY": 0.0, "scaleY": -0.1, "translateY": 90.0 }
乐队
list
字典列表,用于定义来自图块集的单个图层的属性。
请注意,资产的频段顺序与 bands
的顺序相同。
如需了解详情,请参阅以下 bands
字典元素字段。
bands[i].id
string
频段的 ID(名称)。
bands[i].tilesetId
string
与频段对应的图块集的 ID。
bands[i].tilesetBandIndex
int32
与相应地图块中相应地图块的编号(从零开始)。
bands[i].missingData.values
list
值列表(双精度类型),表示该频段中没有数据。
bands[i].pyramidingPolicy
string
“金字塔式”结构政策。如需了解详情,请点击 此链接。选项包括:
- “MEAN”(默认)
- “MODE”
- "SAMPLE"
maskBands
list
字典列表,用于定义来自图块集的单个掩码带的属性。
最多可以提供 1 个遮罩频段。
如需了解详情,请参阅以下 maskBands
字典元素字段。
maskBands[i].tilesetId
string
与掩码带对应的图块集的 ID。图块集的最后一个带始终用作遮罩带。
maskBands[i].bandIds
list of strings
遮罩频段适用的频段 ID 的列表。如果为空,则掩码带会应用于素材资源中的所有带。每个频段只能有一个对应的掩码频段。
占用空间
dictionary
一个字典,用于定义图片中所有有效像素的足迹的属性。
如果为空,则默认占用空间为整个图片。如需了解详情,请参阅以下 footprint
字典元素字段。
footprint.points
list
点列表,用于定义图片中所有有效像素的足迹。点由一个字典定义,其中“x”和“y”键的值为浮点值。点列表用于描述一个环,该环构成了简单多边形的外部,并且必须包含图片的所有有效像素的中心。此环必须是线性环:最后一个点必须等于第一个点。坐标采用 bandId
指定的频段的投影。
注意:请使用非整数坐标(例如每个像素的中心),因为如果像素(1x1 矩形)与足迹相交,则 footprint
会被视为包含该像素。为避免意外选择相邻像素,请勿使用整数值坐标,因为它们是像素之间的边界。沿像素中心绘制足迹可防止包含意外像素,这可能会导致预期像素与地图边界(例如反经线或极点)相邻时出现错误。
例如,对于所有四个像素都有效的 2x2 图片,以下是一个可能的环:
[ { "x": 0.5, "y": 0.5 }, { "x": 0.5, "y": 1.5 }, { "x": 1.5, "y": 1.5 }, { "x": 1.5, "y": 0.5 }, { "x": 0.5, "y": 0.5 } ]
footprint.bandId
string
相应 CRS 用于定义足迹坐标的波段的 ID。 如果为空,则使用第一个频段。
missingData.values
list
值(双精度类型)列表,表示图像的所有波段中都没有数据。适用于未指定自己的 missingData
的所有频段。
pyramidingPolicy
string
“金字塔式”结构政策。如果未指定,系统会默认应用政策“MEAN”。适用于未指定自己的所有频段。 如需了解详情,请点击 此链接。选项包括:
- “MEAN”(默认)
- “MODE”
- "SAMPLE"
uriPrefix
string
可选前缀,用于附加到清单中定义的所有 uris
。
startTime
integer
与资产关联的时间戳(如果有)。这通常对应于卫星图片的拍摄时间。对于与时间间隔对应的素材资源(例如一个月或一年内的平均值),此时间戳对应于该时间间隔的开始时间。以秒和(可选)纳秒为单位,自公元纪年 (1970-01-01) 开始计算。假定采用世界协调时间 (UTC) 时区。
endTime
integer
对于与时间间隔对应的素材资源(例如一个月或一年内的平均值),此时间戳对应于该时间间隔的结束时间(不含该时间)。以秒和(可选)纳秒为单位,自公元纪年 (1970-01-01) 开始计算。假定采用世界协调时间 (UTC) 时区。
媒体资源
dictionary
键值对的任意扁平字典。键必须为字符串,值可以是数字或字符串。用户上传的素材资源尚不支持列表值。
限制
JSON 清单大小
JSON 清单文件大小上限为 10 MB。如果您要上传的文件很多,请考虑如何减少描述数据集所需的字符数。例如,使用 uriPrefix
字段可免去为 uris
列表中的每个 URI 提供 Google Cloud 存储分区路径。如果需要进一步缩减大小,请尝试缩短文件名。
图片文件格式
每个图片文件都必须是 TIFF 图片。如果清单中未指定 CRS,则文件必须是包含嵌入 CRS 的 GeoTIFF。
TIFF 文件可以使用 DEFLATE、JPEG-XL/JXL、LERC、LERC_DEFLATE、LERC_ZSTD、LZMA、LZW、WEBP 或 ZSTD 进行压缩。
以下是关于如何获得最佳大文件上传体验的建议:
- 最佳选择:ZSTD 在速度和压缩率之间取得了良好的平衡。
- 避免:虽然 LZMA 压缩效果很好,但速度可能非常慢。
- 未压缩文件:会导致文件更大,上传时间更长。
- 有损压缩(例如,JPEG):可能会改变像素值。使用无损压缩(例如DEFLATE、LZMA、LZW、ZSTD)除非您了解对数据的潜在影响。