再サンプリングと解像度の低下

投影のドキュメントに記載されているように、Earth Engine はデフォルトで、再投影時に最近傍再サンプリングを行います。この動作は、resample() メソッドまたは reduceResolution() メソッドで変更できます。具体的には、これらの方法のいずれかが入力画像に適用されると、指定された再サンプリングまたは集計方法を使用して、必要な入力の再投影が行われます。

リサンプリング

resample() を使用すると、次回の投影変換で指定された再サンプリング方法('bilinear' または 'bicubic')が使用されます。入力は出力投影でリクエストされるため、入力に対する他のオペレーションの前に暗黙的な再投影が行われることがあります。そのため、入力画像で resample() を直接呼び出します。次の簡単な例を考えてみましょう。

コードエディタ(JavaScript)

// Load a Landsat image over San Francisco, California, UAS.
var landsat = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20160323');

// Set display and visualization parameters.
Map.setCenter(-122.37383, 37.6193, 15);
var visParams = {bands: ['B4', 'B3', 'B2'], max: 0.3};

// Display the Landsat image using the default nearest neighbor resampling.
// when reprojecting to Mercator for the Code Editor map.
Map.addLayer(landsat, visParams, 'original image');

// Force the next reprojection on this image to use bicubic resampling.
var resampled = landsat.resample('bicubic');

// Display the Landsat image using bicubic resampling.
Map.addLayer(resampled, visParams, 'resampled');

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

import ee
import geemap.core as geemap

Colab(Python)

# Load a Landsat image over San Francisco, California, UAS.
landsat = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20160323')

# Set display and visualization parameters.
m = geemap.Map()
m.set_center(-122.37383, 37.6193, 15)
vis_params = {'bands': ['B4', 'B3', 'B2'], 'max': 0.3}

# Display the Landsat image using the default nearest neighbor resampling.
# when reprojecting to Mercator for the Code Editor map.
m.add_layer(landsat, vis_params, 'original image')

# Force the next reprojection on this image to use bicubic resampling.
resampled = landsat.resample('bicubic')

# Display the Landsat image using bicubic resampling.
m.add_layer(resampled, vis_params, 'resampled')

'bicubic' の再サンプリングの結果、出力ピクセルは元の画像と比較して滑らかになります(図 1)。

最近傍
図 1a. 最近傍で再サンプリングされた Landsat 画像。
バイキュービック
図 1b. バイキュービック リサンプリングで再サンプリングされた Landsat 画像。

このコードサンプルの処理順序を図 2 に示します。具体的には、入力画像で指定されたリサンプリング方法を使用して、地図メルカトル投影への暗黙的な再投影が行われます。

オペレーションのフローチャート

図 2. コードエディタに表示する前に入力画像で resample() が呼び出された際のオペレーションのフローチャート。曲線は、再投影への情報の流れを示します。具体的には、使用する出力投影、スケール、再サンプリング方法です。

解像度を下げる

再投影中に再サンプリングするのではなく、別の投影でピクセルを大きなピクセルに集約することを目的としているとします。これは、Landsat ベースのプロダクトの 30 メートル ピクセルから MODIS ベースのプロダクトの粗いピクセル(大スケール)など、異なるスケールの画像データセットを比較する場合に便利です。この集計プロセスは、reduceResolution() メソッドで制御できます。resample() と同様に、画像の次の再投影に影響を与えるには、入力に対して reduceResolution() を呼び出します。次の例では、reduceResolution() を使用して、30 メートル解像度の森林被覆データと 500 メートル解像度の植生指数を比較します。

コードエディタ(JavaScript)

// Load a MODIS EVI image.
var modis = ee.Image(ee.ImageCollection('MODIS/061/MOD13A1').first())
    .select('EVI');

// Display the EVI image near La Honda, California.
Map.setCenter(-122.3616, 37.5331, 12);
Map.addLayer(modis, {min: 2000, max: 5000}, 'MODIS EVI');

// Get information about the MODIS projection.
var modisProjection = modis.projection();
print('MODIS projection:', modisProjection);

// Load and display forest cover data at 30 meters resolution.
var forest = ee.Image('UMD/hansen/global_forest_change_2023_v1_11')
    .select('treecover2000');
Map.addLayer(forest, {max: 80}, 'forest cover 30 m');

// Get the forest cover data at MODIS scale and projection.
var forestMean = forest
    // Force the next reprojection to aggregate instead of resampling.
    .reduceResolution({
      reducer: ee.Reducer.mean(),
      maxPixels: 1024
    })
    // Request the data at the scale and projection of the MODIS image.
    .reproject({
      crs: modisProjection
    });

// Display the aggregated, reprojected forest cover data.
Map.addLayer(forestMean, {max: 80}, 'forest cover at MODIS scale');

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

import ee
import geemap.core as geemap

Colab(Python)

# Load a MODIS EVI image.
modis = ee.Image(ee.ImageCollection('MODIS/006/MOD13A1').first()).select('EVI')

# Display the EVI image near La Honda, California.
m.set_center(-122.3616, 37.5331, 12)
m.add_layer(modis, {'min': 2000, 'max': 5000}, 'MODIS EVI')

# Get information about the MODIS projection.
modis_projection = modis.projection()
display('MODIS projection:', modis_projection)

# Load and display forest cover data at 30 meters resolution.
forest = ee.Image('UMD/hansen/global_forest_change_2015').select(
    'treecover2000'
)
m.add_layer(forest, {'max': 80}, 'forest cover 30 m')

# Get the forest cover data at MODIS scale and projection.
forest_mean = (
    forest
    # Force the next reprojection to aggregate instead of resampling.
    .reduceResolution(reducer=ee.Reducer.mean(), maxPixels=1024)
    # Request the data at the scale and projection of the MODIS image.
    .reproject(crs=modis_projection)
)

# Display the aggregated, reprojected forest cover data.
m.add_layer(forest_mean, {'max': 80}, 'forest cover at MODIS scale')

この例では、出力プロジェクションが reproject() で明示的に設定されています。MODIS 正弦曲線投影への再投影中、小さいピクセルは再サンプリングではなく、指定されたリデューサー(例では ee.Reducer.mean())で集約されます。この一連の操作を図 3 に示します。この例では reproject() を使用して reduceResolution() の効果を可視化していますが、ほとんどのスクリプトでは明示的に再投影する必要はありません。こちらの警告をご覧ください。

オペレーションのフローチャート

図 3. reproject() の前に入力画像で reduceResolution() が呼び出された場合のオペレーションのフローチャート。曲線は、再投影への情報の流れを示します。具体的には、使用する出力投影、スケール、ピクセル集計方法です。

ReduceResolution のピクセル重み

reduceResolution() 集計プロセスで使用されるピクセルの重みは、集計される小さいピクセルと、出力投影で指定された大きなピクセルの重複に基づいています。これを図 4 に示します。

入力ピクセル数と出力ピクセル数

図 4. reduceResolution() の入力ピクセル(黒)と出力ピクセル(青)。

デフォルトの動作では、入力ピクセルがカバーする出力ピクセル領域の割合として入力ピクセルの重みが計算されます。この図では、出力ピクセルの面積は a で、交差領域が b の入力ピクセルの重みは b/a として計算され、交差領域が c の入力ピクセルの重みは c/a として計算されます。この動作により、平均レジューサー以外のレジューサーを使用すると予期しない結果になる可能性があります。たとえば、ピクセルあたりの森林面積を計算するには、平均レジューサーを使用してピクセル被覆率を計算し、面積を乗算します(小さいピクセルの面積を計算して、合計レジューサーで合計するのではなく)。

コードエディタ(JavaScript)

// Compute forest area per MODIS pixel.
var forestArea = forest.gt(0)
    // Force the next reprojection to aggregate instead of resampling.
    .reduceResolution({
      reducer: ee.Reducer.mean(),
      maxPixels: 1024
    })
    // The reduce resolution returns the fraction of the MODIS pixel
    // that's covered by 30 meter forest pixels.  Convert to area
    // after the reduceResolution() call.
    .multiply(ee.Image.pixelArea())
    // Request the data at the scale and projection of the MODIS image.
    .reproject({
      crs: modisProjection
    });
Map.addLayer(forestArea, {max: 500 * 500}, 'forested area at MODIS scale');

Python の設定

Python API とインタラクティブな開発で geemap を使用する方法については、 Python 環境のページをご覧ください。

import ee
import geemap.core as geemap

Colab(Python)

# Compute forest area per MODIS pixel.
forest_area = (
    forest.gt(0)
    # Force the next reprojection to aggregate instead of resampling.
    .reduceResolution(reducer=ee.Reducer.mean(), maxPixels=1024)
    # The reduce resolution returns the fraction of the MODIS pixel
    # that's covered by 30 meter forest pixels.  Convert to area
    # after the reduceResolution() call.
    .multiply(ee.Image.pixelArea())
    # Request the data at the scale and projection of the MODIS image.
    .reproject(crs=modis_projection)
)
m.add_layer(forest_area, {'max': 500 * 500}, 'forested area at MODIS scale')
m