Earth Engine 的设计旨在让您在进行计算时几乎无需担心地图投影。与规模一样,计算所用的投影是根据“拉取”方式确定的。具体而言,输入是在输出投影中请求的。输出可根据函数参数(例如 crs)、Code Editor 和 geemap 地图对象(具有 maps mercator (EPSG:3857) 投影)确定,也可通过 reproject() 调用确定。在代码编辑器或 geemap 中显示图片时,系统会以地图墨卡托投影格式请求输入。请考虑对具有正弦投影的 MODIS 图像执行以下操作:
代码编辑器 (JavaScript)
// 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');
import ee import geemap.core as geemap
Colab (Python)
# 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 投影决定。此投影会向后传播到整个操作序列,以便在地图墨卡托投影中请求输入,并以由地图缩放级别确定的比例进行请求。
在 Earth Engine 中,投影由坐标参考系(CRS 或许多方法的 crs 参数)指定。您可以通过对图片调用 projection() 来检查图片的投影:
代码编辑器 (JavaScript)
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());
import ee import geemap.core as geemap
Colab (Python)
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。例如:
代码编辑器 (JavaScript)
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA'); var mosaic = collection.filterDate('2018-01-01', '2019-01-01').mosaic(); print(mosaic.projection());
import ee import geemap.core as geemap
Colab (Python)
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() 调用之前代码中的计算将在指定的投影中完成。例如,如需强制在特定投影中生成复合:
代码编辑器 (JavaScript)
// Some projection that is suitable for your area of interest. var proj = ee.Projection(...); var output = collection.reduce(...).reproject(proj);
import ee import geemap.core as geemap
Colab (Python)
# Some projection that is suitable for your area of interest. proj = ee.Projection(...) output = collection.reduce(...).reproject(proj)
以下几种情况需要固定投影:
- 计算梯度(例如
ee.Terrain.gradient或ee.Terrain.slope)。 reduceResolution,用于将高分辨率像素聚合为低分辨率像素。(详细了解如何降低分辨率)。
除非绝对必要,否则您应避免使用 reproject(),原因如下:例如,假设您重新投影了某个内容并将其添加到地图中。如果您在 reproject() 调用中指定的比例远小于地图的缩放级别,Earth Engine 将以非常小的比例请求所有输入,覆盖非常广阔的空间范围。这可能会导致一次请求过多的数据,从而导致错误。
如果最终输出的投影与 reproject() 调用中指定的投影不同,则会导致另一次重新投影。这也是在代码中使用 reproject() 时需要谨慎的另一个原因。请看以下示例,该示例强制将 MODIS 影像先重新投影到 WGS84,然后再重新投影到地图墨卡托,以便在代码编辑器地图中显示:
代码编辑器 (JavaScript)
// 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');
import ee import geemap.core as geemap
Colab (Python)
# 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 自动执行,以便在地图上显示结果。另请注意,有关使用哪种投影的信息会从请求传播回输入。