投影

Earth Engine 的设计使得您在进行计算时几乎无需担心地图投影。与缩放一样,计算所采用的投影是基于“拉取”方式确定的。具体而言,输入是在输出投影中请求的。输出可以通过函数参数(例如 crs)、Code Editor 和 geemap 地图对象(采用 maps Mercator (EPSG:3857) 投影)或 reproject() 调用确定。当您在 Code Editor 或 geemap 中显示图片时,系统会以 maps mercator 格式请求输入。请考虑对具有正弦投影的 MODIS 图像执行以下简单操作:

// The input image has a SR-ORG:6974 (sinusoidal) projection.
var image = ee.Image('MODIS/061/MOD13A1/2014_05_09').select(0);

// Normalize the image and add it to the map.
var rescaled = image.unitScale(-2000, 10000);
var visParams = {min: 0.15, max: 0.7};
Map.addLayer(rescaled, visParams, 'Rescaled');

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
# The input image has a SR-ORG:6974 (sinusoidal) projection.
image = ee.Image('MODIS/061/MOD13A1/2014_05_09').select(0)

# Normalize the image and add it to the map.
rescaled = image.unitScale(-2000, 10000)
vis_params = {'min': 0.15, 'max': 0.7}
m = geemap.Map()
m.add_layer(rescaled, vis_params, 'Rescaled')
m

此代码示例的操作顺序如图 1 所示。请注意,输入的投影由输出决定,具体而言,是代码编辑器中地图显示的 maps mercator 投影。此投影会通过一系列操作传播回来,以便以地图的缩放级别决定的比例,在 Maps Mercator 中请求输入。

投影
图 1. 与在 Code Editor 地图中显示 MODIS 图片对应的操作流程图。每个操作的预测结果(流程图的左侧)由输出确定。曲线表示信息流向重新投影:具体而言,是输出投影和比例。

在 Earth Engine 中,投影由坐标参考系 (CRS 或许多方法的 crs 参数) 指定。您可以通过对图片调用 projection() 来检查图片的投影:

var image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(0);
print('Projection, crs, and crs_transform:', image.projection());
print('Scale in meters:', image.projection().nominalScale());

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318').select(0)
display('Projection, crs, and crs_transform:', image.projection())
display('Scale in meters:', image.projection().nominalScale())

请注意,通过对 projection() 返回的 ee.Projection 调用 nominalScale(),您可以确定图片的原生分辨率。原始分辨率是图片金字塔最低级别的标称像素尺度(以米为单位)。由于图片的每个波段可以具有不同的比例和/或投影,因此,如果您对至少有一个波段的投影与其他波段不同的图片调用 projection(),则可能会看到如下错误:

默认投影

除非您需要在特定投影中进行计算,否则通常无需指定投影。只有在输出不明确的情况下,Earth Engine 才会要求您指定投影和/或比例。缩减包含不同投影图像的 ImageCollection(即创建合成图像)可能会导致模糊不清。如果图片是具有不同投影的输入图片的合成图或拼接图,则其投影将采用默认投影,即 1 度比例的 WGS84。 例如:

var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA');
var mosaic = collection.filterDate('2018-01-01', '2019-01-01').mosaic();
print(mosaic.projection());

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
mosaic = collection.filterDate('2018-01-01', '2019-01-01').mosaic()
display(mosaic.projection())

如果您尝试在计算中使用这样的图片,可能会看到类似以下内容的错误:

通常,不希望或不打算进行 1 度级别的汇总,因此 Earth Engine 会提供这条友好提醒,以便您为输出提供完整的规范。

用户通常会对此行为感到困惑,并担心“丢失”投影信息,但系统实际上不会在需要之前计算像素(了解详情),并且在需要时,请求中始终会附带输出投影,其中指定了如何计算复合图像。

在大多数用例中,不进行投影并不是问题,实际上是一种有价值的优化,因为这样可以预览任何缩放级别的结果,而无需等待完整分辨率计算完成。但这确实意味着,在不同缩放级别下,输出可能会有所不同。

如果优化的显示图片因故不够用,可以通过重新投影输出(如以下部分所述)来强制在特定投影中进行计算。

重新投影

您可以使用 reproject() 方法强制在特定投影中执行操作。使用 reproject() 会导致在 reproject() 调用中指定的投影中请求输入。 在 reproject() 调用之前,代码中的计算将在指定的投影中完成。例如,如需强制在特定投影中生成复合图,请执行以下操作:

// Some projection that is suitable for your area of interest.
var proj = ee.Projection(...);
var output = collection.reduce(...).reproject(proj);

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
# Some projection that is suitable for your area of interest.
proj = ee.Projection(...)
output = collection.reduce(...).reproject(proj)

需要固定投影的一些情况包括:

  • 计算梯度(例如 ee.Terrain.gradientee.Terrain.slope)。
  • reduceResolution,适用于您希望将较高分辨率的像素汇总为较低分辨率的情况。(详细了解如何降低分辨率)。

除非绝对必要,否则您应避免使用 reproject(),原因有很多。例如,假设您重新投影某个对象并将其添加到地图中。如果您在 reproject() 调用中指定的比例远小于地图的缩放级别,Earth Engine 将请求非常小比例的所有输入,并涵盖非常广泛的空间范围。这可能会导致一次请求的数据量过多,从而导致错误。

如果最终输出的投影与 reproject() 调用中指定的投影不同,则会导致另一次重新投影。这也是在代码中谨慎使用 reproject() 的另一个原因。请考虑以下示例,该示例会强制将 MODIS 图像先重新投影到 WGS84,然后再重新投影到 maps mercator,以便在代码编辑器地图中显示:

// The input image has a SR-ORG:6974 (sinusoidal) projection.
var image = ee.Image('MODIS/061/MOD13A1/2014_05_09').select(0);

// Operations *before* the reproject call will be done in the projection
// specified by reproject().  The output results in another reprojection.
var reprojected = image
    .unitScale(-2000, 10000)
    .reproject('EPSG:4326', null, 500);
Map.addLayer(reprojected, {min: 0.15, max: 0.7}, 'Reprojected');

如需了解 Python API 以及如何使用 geemap 进行交互式开发,请参阅 Python 环境页面。

import ee
import geemap.core as geemap
# The input image has a SR-ORG:6974 (sinusoidal) projection.
image = ee.Image('MODIS/061/MOD13A1/2014_05_09').select(0)

# Operations *before* the reproject call will be done in the projection
# specified by reproject(). The output results in another reprojection.
reprojected = image.unitScale(-2000, 10000).reproject('EPSG:4326', None, 500)
m = geemap.Map()
m.add_layer(reprojected, {'min': 0.15, 'max': 0.7}, 'Reprojected')
m

图 2 图解了与此简单重投影示例对应的操作流程。请注意,第一个重新投影是显式的,如 reproject() 调用中所指定。第二次重新投影是隐式的,由 Earth Engine 自动执行,以便在地图上显示结果。另请注意,有关要使用哪种投影的信息会从请求传播回输入。

重新投影
图 2. 与代码编辑器地图中 MODIS 图片的重投影对应的操作流程图。曲线表示信息流向重新投影:具体而言,是输出投影和比例。