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

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');

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

Reducer を使用した合成

画像領域の統計情報を取得するために、最初にリデューサーを紹介しました。これは空間的な削減でした。画像コレクションを 1 つの画像に縮小することは、コレクションが時間の経過に伴う画像を表す場合、時間的縮小です。使用する 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() メソッドのショートカットです。Earth Engine のすべてのリデューサーの一覧については、コードエディタの [Docs] タブの ee.Reducer パッケージをご覧ください。画像コレクションのレデューサを検討する際は、出力が画像であることに注意してください。たとえば、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 データカタログにある 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_2015');

// 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 らのデータセットに基づく)上のすべてのピクセルは表示されますが、水上(または 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 と呼ぶのは完全に正しいわけではありませんが、現在の地図作成のコンテキストでは問題ありません。次に、「水」をそれ自体でマスクします。これにより、すべての水ピクセルが 1 で、それ以外のすべてがマスクされた画像が生成されます。最後のステップでは、mosaic() を使用して画像を結合します。mosaic() は画像コレクションで動作するため、結合する画像のリストを画像コレクション コンストラクタに渡し、最後のステップとして mosaic() を呼び出します。このリスト内の画像の順序は重要です。具体的には、出力画像には、入力コレクション内の画像スタックの最後にマスクされていないピクセルが含まれます。この場合、水レイヤはコレクション内の最後の(最上位の)画像であり、水が存在するマスクされていないピクセルのみが含まれているため、この処理は機能します。

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

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

この時点で、画像コレクションを最近の値の合成として視覚化する方法、リデューサーを使用して画像コレクションを合成する方法、画像のコレクションをマスクしてモザイク処理することでカスタム合成を作成する方法について説明しました。次のページでは、コレクション内のすべての画像に植生指標を追加し、その指標を使用して「最も緑の多いピクセル」の合成画像を作成する方法について説明します。