合成、遮罩和馬賽克

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

這張合成圖的問題之一是雲層太多。您可以縮減 ImageCollection,而不是只擷取集合中的最後一個像素 (將集合新增至地圖時,Earth Engine 會隱含呼叫 mosaic()) (進一步瞭解如何縮減圖片集合)。

使用 Reducer 進行合成

您在取得圖片區域統計資料時,首次接觸到歸納器。這是「空間」縮減。如果圖片集合代表一段時間內的圖片,將圖片集合縮減為圖片就是「時間」縮減。您使用的 Reducer 類型會定義 Earth Engine 處理重疊像素的方式。Landsat 8 每 16 天會造訪地球上的同一個地點。也就是說,在 6 個月的期間內,大約會有 12 張圖片 (如果場景重疊,則會更多)。地圖上的每個像素都來自一疊像素,其中一個像素來自顯示的集合中的每個圖片。

只要將集合新增至地圖,系統就會選取最新的像素,也就是堆疊中最新圖片的像素。您可以使用 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() 方法。與篩選方法類似,這是圖片集合上更通用的 reduce() 方法的捷徑,該方法接受 ee.Reducer() 作為引數。如要查看所有 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 中都會變成透明。

舉例來說,假設您想遮蓋中位數合成影像中的所有水像素。您可以使用 Hansen 等人 (2013 年) 描述的資料集建立水體遮罩,該資料集位於 Earth Engine Data Catalog 中。(如要進一步瞭解 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 等人的資料集) 都會顯示,但位於水域 (或無資料) 的像素會變成透明,並從您對 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() 會將所有零轉換為一,並將所有非零轉換為零。將該變數稱為 water 並不完全正確,因為其中也包含一些無資料像素,但在目前的製圖情境中,這樣做是可行的。接下來,請使用「water」遮蓋「water」。這樣一來,圖片中的所有水體像素都會是 1,其他部分則會遮蓋。最後一個步驟是使用 mosaic() 合併圖片。由於 mosaic() 適用於圖片集合,因此我們會將要合併的圖片清單傳遞至圖片集合建構函式,然後呼叫 mosaic() 做為最後一個步驟。清單中的圖片順序很重要。具體來說,輸出圖片會包含輸入集合中圖片堆疊的最後一個未遮蓋像素。在這個例子中,這種做法可行,因為水層是集合中的最後一張 (頂層) 圖片,且只包含水出現位置的未遮罩像素。

請注意,集合中的圖片是視覺化圖片。對圖片呼叫 visualize() 時,系統會根據您傳入的視覺化參數,將圖片轉換為 3 波段、8 位元的圖片。預設視覺化參數適用於 3 頻帶、8 位元圖片,因此將圖片新增至地圖時,不需要視覺化參數。結果應如圖 7 所示。

Tutorial_api_07_mosaic.png
圖 7. 自訂鑲嵌,讓水域呈現統一顏色。

到目前為止,您已瞭解如何將圖片集合視覺化為近期值合成影像、使用減縮器合成圖片集合的方法,以及透過遮蓋和拼接圖片集合來製作自訂合成影像的方法。在下一頁中,您將瞭解如何為集合中的每張圖片新增植被指數,並使用該指數建立「最綠像素」合成影像。