合成、マスキング、モザイク処理

Landsat 8 TOA 反射率コレクションを l8 という変数に読み込むと、次のコードによって最新値のコンポジットが生成されます。

コードエディタ(JavaScript)

var l8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA');
var landsat2016 = l8.filterDate('2016-01-01', '2016-12-31');
Map.addLayer(landsat2016, visParams, 'l8 collection');

この合成画像の問題の一つは、雲が多いことです。コレクションの最後のピクセルを取得する代わりに(コレクションを地図に追加すると、Earth Engine は暗黙的に mosaic() を呼び出します)、ImageCollection を縮小できます(画像コレクションの縮小の詳細)。

レデューサを使用した合成

レデューサは、画像領域の統計情報を取得するために初めて導入されました。これは空間的な削減でした。画像コレクションを画像に縮小することは、コレクションが時間の経過とともに画像を表す場合の時間的な縮小です。使用する Reducer のタイプによって、Earth Engine が重複するピクセルを処理する方法が決まります。Landsat 8 は 16 日ごとに地球上の同じ場所を観測します。つまり、6 か月間で約 12 枚の画像が撮影されます(シーンが重複する場所ではさらに多くなります)。地図上の各ピクセルは、ピクセルのスタック(表示されているコレクション内の各画像から 1 つずつ)から派生します。

コレクションを地図に追加するだけでは、最新のピクセル(スタック内の最新の画像から取得したピクセル)が選択されます。この動作は、Earth Engine のレデューサを使用して変更できます。たとえば、スタックから最新のピクセルを取得するのではなく、スタックの中央値を選択するように Earth Engine に指示できます。これにより、雲(値が高い)と影(値が低い)を除去できるというメリットがあります。中央値レデューサを使用して画像コレクションを縮小すると、複合値は各バンドの中央値(経時的)になります。たとえば、2016 年の Landsat シーンを使用する場合:

コードエディタ(JavaScript)

// Get the median over time, in each band, in each pixel.
var median = l8.filterDate('2016-01-01', '2016-12-31').median();

// Make a handy variable of visualization parameters.
var visParams = {bands: ['B4', 'B3', 'B2'], max: 0.3};

// Display the median composite.
Map.addLayer(median, visParams, 'median');

このコードの新しい点は、画像コレクションに適用される median() メソッドです。 フィルタリング メソッドと同様に、これは ee.Reducer() を引数として受け取る画像コレクションのより一般的な reduce() メソッドのショートカットです。コードエディタの [Docs] タブにある ee.Reducer パッケージを参照して、すべての Earth Engine レデューサのリストを確認してください。画像コレクションのリデューサーを検討する際は、出力が画像であることに注意してください。そのため、数値以外の出力を持つリデューサー(histogram や toList リデューサーなど)は、画像コレクションでは機能しません。

Tutorial_api_06_median_composite
図 6. Landsat 8 の中央値コンポジット。

中央値コンポジットをズームアウトすると、図 6 のようになります。これは、以前に作成した最近の値のコンポジットよりもかなり良く見えるはずです。この時点で、一歩引いて、中央値コンポジットを作成するために何が行われたかを検討する価値があります。Earth Engine は、米国本土全体の Landsat 8 コレクション全体を読み込み、すべてのピクセルの中央値を計算しました。これは大量のデータです。もちろん、 以前に行ったように、最初にコレクションをフィルタリングして、年間の中央値を計算することもできます。重要なのは、このすべての画像をダウンロードしてこのコンポジットを作成する必要がある場合、それは大きなプロジェクトになるということです。Earth Engine を使用すると、数秒で結果が得られます。

合成とモザイク処理について詳しくは、こちらをご覧ください。

マスキング

中央値コンポジットは、最近値コンポジットよりも改善されていますが、画像の一部をマスクしたい場合があります。画像内のピクセルをマスキングすると、それらのピクセルが透明になり、分析から除外されます。画像の各バンドの各ピクセルにはマスクがあります。マスク値が 0 以下のものは透明になります。マスクの値が 0 より大きいものはレンダリングされます。画像のマスクは、image1.mask(image2) などの呼び出しを使用して設定されます。この呼び出しは、image2 の値を取得して image1 のマスクにします。image2 で値が 0 のピクセルは、image1 で透明になります。

たとえば、中央値コンポジット内のすべての水ピクセルをマスクするとします。ウォーターマスクは、Earth Engine Data Catalog にある Hansen et al.(2013)で説明されているデータセットを使用して作成できます。(Hansen らのデータセットの詳細については、こちらのチュートリアルをご覧ください)。このデータセットでは、水の値は 2、陸地の値は 1、「データなし」の値は 0 です。少しロジックを使用して、陸地がない場所にゼロがあるマスク画像を作成します。

コードエディタ(JavaScript)

// Load or import the Hansen et al. forest change dataset.
var hansenImage = ee.Image('UMD/hansen/global_forest_change_2025_v1_13');

// Select the land/water mask.
var datamask = hansenImage.select('datamask');

// Create a binary mask.
var mask = datamask.eq(1);

// Update the composite mask with the water mask.
var maskedComposite = median.updateMask(mask);
Map.addLayer(maskedComposite, visParams, 'masked');

このコードには、詳しく説明する価値のある新しい要素がいくつかあります。まず、select() 関数は、画像から目的のバンドを抽出するのに役立ちます。ここでは、対象となるバンド datamask のみを選択します。次に新しいのは、論理演算子 eq() です。これは「等しい」という意味です。eq(1) を使用して、datamask バンドで値が 1 でないすべてのピクセル(水またはデータなし)が、結果の画像で値 0 になるバイナリ画像を作成します。

このマスキングの結果、中央値コンポジット内の陸地(Hansen et al. データセットによる)のすべてのピクセルが表示されますが、水域(または nodata)のピクセルは透明になり、maskedComposite 画像に対して行う分析から除外されます。

モザイク処理

画像コレクション、論理演算子、マスキング、合成のコンセプトを組み合わせることで、興味深い地図作成の結果を得ることができます。たとえば、陸地のピクセルをトゥルーカラーで表示し、他のすべてのピクセルを青色で表示する画像が必要な場合は、次のようにします。

コードエディタ(JavaScript)

// Make a water image out of the mask.
var water = mask.not();

// Mask water with itself to mask all the zeros (non-water).
water = water.mask(water);

// Make an image collection of visualization images.
var mosaic = ee.ImageCollection([
  median.visualize(visParams),
  water.visualize({palette: '000044'}),
]).mosaic();

// Display the mosaic.
Map.addLayer(mosaic, {}, 'custom mosaic');

このコードでは多くの処理が行われているため、詳しく見ていきましょう。まず、not() 論理演算子を使用して、前に作成したマスクを反転します。具体的には、not() はすべてのゼロを 1 に、ゼロ以外をすべてゼロに変換します。この変数には nodata ピクセルも含まれているため、water と呼ぶのは完全に正しいとは言えませんが、現在の地図作成のコンテキストでは問題ありません。次に、「water」をそれ自体でマスクします。これにより、すべての水ピクセルが 1 で、それ以外はすべてマスクされた画像が生成されます。最後のステップは、mosaic() を使用して画像を結合することです。mosaic() は画像コレクションに対して機能するため、結合する画像のリストを画像コレクション コンストラクタに渡し、最後のステップとして mosaic() を呼び出します。このリスト内の画像の順序は重要です。具体的には、出力画像には、入力コレクションの画像スタックから最後にマスクされていないピクセルが含まれます。この場合、水レイヤはコレクションの最後の(一番上の)画像であり、水が発生するマスクされていないピクセルのみが含まれているため、この処理が機能します。

コレクション内の画像は可視化画像です。画像に対して visualize() を呼び出すと、渡した可視化パラメータに従って 3 バンドの 8 ビット画像に変換されます。デフォルトの可視化パラメータは 3 バンド、8 ビットの画像に適しているため、地図に画像を追加するときに可視化パラメータは必要ありません。結果は図 7 のようになります。

Tutorial_api_07_mosaic.png
図 7. 水域を均一な色にするカスタム モザイク。

ここまでで、画像コレクションを最新値のコンポジットとして可視化する方法、レデューサを使用して画像コレクションをコンポジットする方法、画像のコレクションをマスキングしてモザイク化することでカスタム コンポジットを作成する方法について説明しました。次のページでは、コレクション内のすべての画像に植生指数を追加し、その指数を使用して「最も緑のピクセル」のコンポジットを作成する方法について説明します。