合成、遮罩和馬賽克

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 合成

您首先接觸的是取得圖片區域統計資料的縮減函式。這項措施可減少空間。將圖像集合縮減為單一圖像時,如果集合代表一段時間內的圖像,就是時間縮減。您使用的 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 套件。考慮用於圖像集合的縮減函式時,請注意輸出內容是圖像,因此輸出內容為非數值的縮減函式 (例如 histogramtoList 縮減函式) 無法用於圖像集合。

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 資料目錄中。(如要進一步瞭解 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 等人的資料集) 都會顯示,但位於水上 (或無資料) 的像素則會呈現透明,且不會納入您對 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 並不完全正確,因為其中也包含一些 nodata 像素,但在目前的製圖環境中,這沒問題。接下來,請使用「water」遮蓋「water」。這樣一來,所有水像素都會變成 1,其他所有像素則會遭到遮蓋。最後一個步驟是使用 mosaic() 合併圖片。由於 mosaic() 會處理圖片集合,因此我們會將要合併的圖片清單傳遞至圖片集合建構函式,然後呼叫 mosaic() 做為最後一個步驟。清單中的圖片順序很重要。具體來說,輸出圖片會包含輸入集合中圖片堆疊的最後一個未遮蓋像素。在本例中,這項做法可行,因為水層是集合中的最後一個 (頂端) 圖像,且只包含出現水的位置未遮蓋的像素。

請注意,集合中的圖片是視覺化圖片。當您在圖片上呼叫 visualize() 時,系統會根據您傳入的視覺化參數,將圖片轉換為 3 波段 8 位元圖片。對於 3 波段的 8 位元圖片,預設的視覺化參數就足夠了,因此將圖片加入地圖時,不需要視覺化參數。結果應如圖 7 所示。

Tutorial_api_07_mosaic.png
圖 7:自訂馬賽克,可將水域設為單一顏色。

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