本快速入門指南旨在讓您快速開始使用 Earth Engine JavaScript API 進行程式設計。如要瞭解 JavaScript 的基礎知識,並透過 Earth Engine API 進行更深入的練習,請參閱教學課程。如要瞭解建議的 JavaScript 程式碼編寫風格,請參閱 Google JavaScript 風格指南。
Google Earth Engine 可讓使用者在 Google 基礎架構中儲存的地理參考圖像和向量上執行演算法。Google Earth Engine API 提供函式程式庫,可套用至資料以供顯示和分析。Earth Engine 的公開資料目錄包含大量公開圖像和向量資料集。您也可以在使用者的個人資料夾中建立私人素材資源。
如何使用這些文件
Earth Engine 說明文件適用於熟悉地理空間資料分析的使用者。這些文件的主要結構是依據資料類型。舉例來說,左側導覽面板包含重要資料類型的各個部分或頁面連結,例如 Image
、ImageCollection
、Feature
、FeatureCollection
、Geometry
、Reducer
、Chart
、Join
和 Array
。本指南僅會說明這些類型的必要資訊,協助您開始使用。另外,我們也提供機器學習、專門或特定感應器演算法 (例如 Landsat 演算法)、面向大眾的應用程式、資料 (素材資源) 管理,以及 Earth Engine 內部運作方式的重要詳細資料。在深入探討這些內容之前,請先從這裡開始!
程式碼編輯器
程式碼編輯器是互動式環境,可用於開發 Earth Engine 應用程式 (圖 1)。中間面板提供 JavaScript 程式碼編輯器。編輯器上方有按鈕,可用來儲存目前的指令碼、執行指令碼,以及清除地圖。「取得連結」按鈕會在網址列中為指令碼產生專屬網址。底部面板中的地圖包含腳本新增的圖層。頂端是資料集和地點的搜尋框。左側面板包含程式碼範例、已儲存的腳本、可搜尋的 API 參考資料,以及私密資料的資產管理工具。右側面板包含用於查詢地圖的檢查器、輸出控制台,以及長時間執行工作用的管理員。右上方的說明按鈕 程式碼編輯器指南和取得說明指南。
包含指南和其他資源的連結,可用來取得協助。詳情請參閱在 Code Editor 中開啟及執行程式碼
以下步驟說明如何開啟 Earth Engine 並執行顯示圖片的自訂指令碼。為獲得最佳效果,建議您安裝最新版 Chrome (Google 的網路瀏覽器),請參閱這篇文章。
- 前往以下網址開啟 Earth Engine 程式碼編輯器: code.earthengine.google.com。
- 前往程式碼編輯器最左側的「指令碼」分頁。您會在其中找到一系列範例指令碼,可用於存取、顯示及分析 Earth Engine 資料。
- 在「圖片集合」下方,選取「經過篩選的組合」示例。您會在中央控制台看到指令碼。按下「Run」按鈕,執行指令碼。在「經過篩選的複合圖」範例中,系統會選取與科羅拉多州和猶他州交會或位於兩州邊界內的 Landsat 7 影像。接著,系統會顯示所選圖片的真實色彩合成。範例會介紹常用的
filter()
、clip()
和Map.addLayer()
等方法。
Earth Engine 資料結構
Earth Engine 中兩種最基本的地理資料結構分別是 Image
和 Feature
,分別對應到光柵和向量資料類型。圖片由頻帶和屬性字典組成。功能由 Geometry
和屬性字典組成。由 ImageCollection
處理圖像堆疊 (例如圖像時間序列)。一組地圖項目是由 FeatureCollection
處理。Earth Engine 中的其他基本資料結構包括 Dictionary
、List
、Array
、Date
、Number
和 String
(請參閱這份教學課程,進一步瞭解基本資料類型)。請務必記住,這些都是伺服器端物件,因此無法以與用戶端 JavaScript 物件相同的方式進行操作 (瞭解詳情)。
Earth Engine 演算法
您可以透過多種方式在 API 中執行作業:
- 呼叫附加至物件的程式。
- 呼叫演算法。
- 呼叫程式碼編輯器專屬函式。
- 定義新函式。
程式碼編輯器的「Docs」分頁會列出每個 API 類別的方法。例如,Image
類別具有 add()
方法:
程式碼編輯器 (JavaScript)
var image3 = image1.add(image2);
這個方法會將 image2
的頻帶新增至 image1
的頻帶。ee.Algorithms
類別包含目前支援的演算法清單,可用於專門或特定領域的處理作業。例如,如要從輸入的數位高程模型 (DEM) 建立地形圖層:
程式碼編輯器 (JavaScript)
var terrainImage = ee.Algorithms.Terrain(dem);
Code Editor 專屬函式包括 Map
和 Export
方法,分別控制如何將圖層新增至地圖面板或匯出至 Google 雲端硬碟。您也可以使用以下方法在 JavaScript 中建立函式:
程式碼編輯器 (JavaScript)
var myFunction = function(args) { // do something return something; };
如對應章節所示,使用者定義的函式可用於建立自訂功能,或使用以下項目修改集合的元素:
程式碼編輯器 (JavaScript)
var collection2 = collection1.map(aFunction);
以下各節將說明這些概念在各種簡單用途中的應用。
'Hello world!' JavaScript
將資訊輸出至主控台是取得物件相關資訊、顯示運算的數值結果、顯示物件中繼資料或協助偵錯的基本工作。程式碼編輯器中的經典「Hello World!」範例如下:
程式碼編輯器 (JavaScript)
print('Hello world!');
將這行程式碼複製到程式碼編輯器,然後按一下「Run」。請注意,輸出內容會顯示在「控制台」分頁中,位於程式碼編輯器的右側。以下是與遙測相關的範例,可用來列印 Landsat 8 圖像的中繼資料:
程式碼編輯器 (JavaScript)
print(ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318'));
仔細檢查主控台中的輸出內容,查看 Landsat 圖像可用的中繼資料。
在地圖中新增資料
除了將資訊輸出至主控台,您也可以將資料新增至 Map
,以便視覺化地理資料。請使用 Map.addLayer()
執行這項操作。在以下範例中,系統會使用 ee.Image()
例項化 Image
(如何找到這些圖片會在稍後介紹),並透過 Map.addLayer()
將其新增至地圖,地圖會以圖片為中心:
程式碼編輯器 (JavaScript)
// Load an image. var image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318'); // Center the map on the image. Map.centerObject(image, 9); // Display the image. Map.addLayer(image);
Map.centerObject()
的第二個參數是縮放等級,數字越大,表示縮放比例越大 (越放大)。Map
函式的參數已在 API 參考資料中詳細說明,您可以透過「文件」分頁存取這些參考資料。如果圖片外觀不如預期,請使用額外的 Map.addLayer()
引數設定顯示參數。例如:
程式碼編輯器 (JavaScript)
// Load the image from the archive. var image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318'); // Define visualization parameters in an object literal. var vizParams = {bands: ['B5', 'B4', 'B3'], min: 0.02, max: 0.4, gamma: 1.3}; // Center the map on the image and display. Map.centerObject(image, 9); Map.addLayer(image, vizParams, 'Landsat 8 false color');
請注意,可視化參數是由物件文字常值定義,其中包含要顯示的頻帶清單、最小和最大反射率值,以及伽馬值。(如要進一步瞭解 Landsat 頻帶,請參閱這篇文章。如要進一步瞭解圖像視覺化功能,請參閱這篇文章。
使用 Map.addLayer()
將地圖項目和地圖項目集合新增至地圖。例如:
程式碼編輯器 (JavaScript)
var counties = ee.FeatureCollection('TIGER/2018/Counties'); Map.addLayer(counties, {}, 'counties');
尋找圖片、圖片集合和地圖項目集合
您可以搜尋 Earth Engine 資料目錄,找出圖像、圖像集合和地圖項目集。舉例來說,在影像資料集清單的搜尋欄位中輸入「Landsat 8」時,系統會顯示相關結果。(完整的 Earth Engine 資料集清單請見 Earth Engine 資料目錄)。按一下資料集名稱,即可取得簡短說明、時間可用性、資料提供者和收集 ID 相關資訊。按一下「Import」按鈕,即可在指令碼頂端自動建立「Imports」部分,並使用此集合的變數。
或者,您也可以複製集合 ID 並貼到程式碼中。舉例來說,請選擇「Landsat 8」搜尋結果的 Tier 1 TOA 結果,並複製 ID,如下所示:
程式碼編輯器 (JavaScript)
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA');
由於這項服務是收集了地球陸地表面的多張圖片,因此必須篩選才能在集合中找到個別圖片,縮小搜尋範圍。或者,您也可以使用合成和馬賽克技巧,將圖片集合縮減為單一圖片。請參閱後續章節,進一步瞭解如何篩選及合成圖像 (請參閱「減少」一節)。
您也可以透過 Data Catalog 取得地圖項目集合。雖然其呈現方式比圖片集合小,但您仍可找到國際、人口普查、流域和保護區邊界等。如要進一步瞭解如何匯入自己的向量資料集,請參閱這篇文章。
篩選和排序
為了限制結果數量,通常需要依空間和/或時間篩選資料集。舉例來說,假設您要排序 Landsat 8 場景集合,以便找出舊金山的無雲場景。首先,您必須定義感興趣的區域。這時通常會用點來表示。啟用程式碼編輯器右側的「Inspector」分頁,然後點選感興趣區域的中心附近,複製「Inspector」分頁中的座標,然後使用以下方法建構 Point
:
程式碼編輯器 (JavaScript)
var point = ee.Geometry.Point(-122.262, 37.8719);
建構開始和結束日期:
程式碼編輯器 (JavaScript)
var start = ee.Date('2014-06-01'); var finish = ee.Date('2014-10-01');
使用點和日期篩選 Landsat 8 集合,然後使用中繼資料屬性 (在檢查 Landsat 8 影像中繼資料時發現) 排序:
程式碼編輯器 (JavaScript)
var filteredCollection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA') .filterBounds(point) .filterDate(start, finish) .sort('CLOUD_COVER', true);
這個系列產品可安全列印及檢查。(如果集合含有過多圖片,則列印作業會非常緩慢、逾時或傳回錯誤)。請注意,集合中的圖片是儲存在 ImageCollection
的「features」屬性中的 List
。集合中任何圖片的 ID 都可以複製到 Image
建構函式中,如上所示。或者,取得第一張圖片 (雲層覆蓋率最低):
程式碼編輯器 (JavaScript)
var first = filteredCollection.first();
使用 filter()
並將 ee.Filter
做為引數,即可存取完整的 Earth Engine 篩選功能。(上述使用的 filterBounds()
和 filterDate()
方法是捷徑)。例如,以下程式碼會建立 Filter
,並用於篩選 FeatureCollection
,然後顯示結果:
程式碼編輯器 (JavaScript)
// Load a feature collection. var featureCollection = ee.FeatureCollection('TIGER/2016/States'); // Filter the collection. var filteredFC = featureCollection.filter(ee.Filter.eq('NAME', 'California')); // Display the collection. Map.setCenter(-119.604, 37.798, 6); Map.addLayer(filteredFC, {}, 'California');
頻帶運算
使用 Image
方法對圖片執行數學運算。這可能包括波段重組 (光譜指數)、圖像差異或數學運算,例如乘以常數。例如,計算 20 年內常態化差異植被指數 (NDVI) 圖像之間的差異:
程式碼編輯器 (JavaScript)
// This function gets NDVI from Landsat 5 imagery. var getNDVI = function(image) { return image.normalizedDifference(['B4', 'B3']); }; // Load two Landsat 5 images, 20 years apart. var image1 = ee.Image('LANDSAT/LT05/C02/T1_TOA/LT05_044034_19900604'); var image2 = ee.Image('LANDSAT/LT05/C02/T1_TOA/LT05_044034_20100611'); // Compute NDVI from the scenes. var ndvi1 = getNDVI(image1); var ndvi2 = getNDVI(image2); // Compute the difference in NDVI. var ndviDifference = ndvi2.subtract(ndvi1);
請注意,這個範例使用了使用者定義的 function
。詳情請參閱下一節。
對應 (取代 for 迴圈的做法)
使用 map()
疊代集合中的項目。(在 Earth Engine 中,For 迴圈並非正確的做法,應避免使用)。map()
函式可套用至 ImageCollection
、FeatureCollection
或 List
,並接受 function
做為引數。函式的引數是其對應的集合元素。這項功能可用於以相同方式修改集合的每個元素,例如新增。例如,下列程式碼會在 ImageCollection
中的每張圖片中新增 NDVI 頻帶:
程式碼編輯器 (JavaScript)
// This function gets NDVI from Landsat 8 imagery. var addNDVI = function(image) { return image.addBands(image.normalizedDifference(['B5', 'B4'])); }; // Load the Landsat 8 TOA data, filter by location and date. var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA') .filterBounds(ee.Geometry.Point(-122.262, 37.8719)) .filterDate('2014-06-01', '2014-10-01'); // Map the function over the collection. var ndviCollection = collection.map(addNDVI);
另一項常見的任務是將新的屬性 (或稱「屬性」或「欄位」) 新增至 FeatureCollection
中的功能。在以下範例中,新屬性是涉及兩個現有屬性的運算:
程式碼編輯器 (JavaScript)
// This function creates a new property that is the sum of two existing properties. var addField = function(feature) { var sum = ee.Number(feature.get('property1')).add(feature.get('property2')); return feature.set({'sum': sum}); }; // Create a FeatureCollection from a list of Features. var features = ee.FeatureCollection([ ee.Feature(ee.Geometry.Point(-122.4536, 37.7403), {property1: 100, property2: 100}), ee.Feature(ee.Geometry.Point(-118.2294, 34.039), {property1: 200, property2: 300}), ]); // Map the function over the collection. var featureCollection = features.map(addField); // Print a selected property of one Feature. print(featureCollection.first().get('sum')); // Print the entire FeatureCollection. print(featureCollection);
請注意,屬性值必須轉換為 ee.Number
,才能使用 add()
方法,以便系統將其視為數字。集合類型可由 map()
變更。例如:
程式碼編輯器 (JavaScript)
// This function returns the image centroid as a new Feature. var getGeom = function(image) { return ee.Feature(image.geometry().centroid(), {foo: 1}); }; // Load a Landsat 8 TOA collection. var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA') .filterBounds(ee.Geometry.Point(-122.262, 37.8719)) .filterDate('2014-06-01', '2014-10-01'); // Map the function over the ImageCollection. var featureCollection = ee.FeatureCollection(collection.map(getGeom)); // Print the collection. print(featureCollection);
請注意,從圖片群集中心建立的每個特徵都會新增屬性 (foo
)。在最後一行中,轉換會將產生的集合設為 FeatureCollection
。
減少
在 Earth Engine 中,縮減是指匯總時間、空間、頻帶、陣列和其他資料結構的資料的方式。API 中有多種方法可用於此用途。舉例來說,如要製作 ImageCollection
的合成圖,請使用 reduce()
將集合中的圖片縮減為一個 Image。簡單的範例是建立 Landsat 8 集合中雲量最少的五個影像的中位數合成影像,如下所示:
程式碼編輯器 (JavaScript)
// Load a Landsat 8 TOA collection. var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA') // Filter by date and location. .filterBounds(ee.Geometry.Point(-122.262, 37.8719)) .filterDate('2014-01-01', '2014-12-31') // Sort by increasing cloudiness. .sort('CLOUD_COVER'); // Compute the median of each pixel for each band of the 5 least cloudy scenes. var median = collection.limit(5).reduce(ee.Reducer.median());
縮減也是取得 Feature
或 FeatureCollection
定義區域中圖片統計資料的方式。假設您要計算感興趣區域內的平均像素值。請使用 reduceRegion()
來達成此目的。例如:
程式碼編輯器 (JavaScript)
// Load and display a Landsat TOA image. var image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318'); Map.addLayer(image, {bands: ['B4', 'B3', 'B2'], max: 0.3}); // Create an arbitrary rectangle as a region and display it. var region = ee.Geometry.Rectangle(-122.2806, 37.1209, -122.0554, 37.2413); Map.addLayer(region); // Get a dictionary of means in the region. Keys are bandnames. var mean = image.reduceRegion({ reducer: ee.Reducer.mean(), geometry: region, scale: 30 });
如要進一步瞭解 Reducer,請參閱 Reducer 文件。
遮罩
ee.Image
中的每個像素都具有值和遮罩,範圍從 0 (無資料) 到 1。系統會將遮罩的像素 (mask==0) 視為無資料。值為 0 < 遮罩 ≤ 1 的像素會帶有值,但會根據遮罩進行數值運算。
您可以使用遮罩將像素設為透明,或將其排除在分析範圍之外。遮罩值為零時,系統會遮蓋像素。接著繼續使用圖片差異比較範例,使用遮罩來顯示差異間隔內 NDVI 增加和減少的區域:
// This function gets NDVI from Landsat 5 imagery. var getNDVI = function(image) { return image.normalizedDifference(['B4', 'B3']); }; // Load two Landsat 5 images, 20 years apart. var image1 = ee.Image('LANDSAT/LT05/C02/T1_TOA/LT05_044034_19900604'); var image2 = ee.Image('LANDSAT/LT05/C02/T1_TOA/LT05_044034_20100611'); // Compute NDVI from the scenes. var ndvi1 = getNDVI(image1); var ndvi2 = getNDVI(image2); // Compute the difference in NDVI. var ndviDifference = ndvi2.subtract(ndvi1); // Load the land mask from the SRTM DEM. var landMask = ee.Image('CGIAR/SRTM90_V4').mask(); // Update the NDVI difference mask with the land mask. var maskedDifference = ndviDifference.updateMask(landMask); // Display the masked result. var vizParams = {min: -0.5, max: 0.5, palette: ['FF0000', 'FFFFFF', '0000FF']}; Map.setCenter(-122.2531, 37.6295, 9); Map.addLayer(maskedDifference, vizParams, 'NDVI difference');
請注意,在本範例中,NDVI 差異的遮罩會透過 updateMask()
中的陸地遮罩更新。這會將 NDVI 差異遮罩的像素遮罩設為土地遮罩,只要 NDVI 差異遮罩不為零即可。
遮蓋功能也能用於從分析中排除資料。請參考「縮減資料量」一節中的 reduceRegion()
範例。假設任務是計算加州聖克拉拉郡的季節性平均 NDVI,並排除多雲像素。以下範例說明多個概念:篩選、對應、縮減及使用雲端遮罩:
程式碼編輯器 (JavaScript)
// This function gets NDVI from a Landsat 8 image. var addNDVI = function(image) { return image.addBands(image.normalizedDifference(['B5', 'B4'])); }; // This function masks cloudy pixels. var cloudMask = function(image) { var clouds = ee.Algorithms.Landsat.simpleCloudScore(image).select(['cloud']); return image.updateMask(clouds.lt(10)); }; // Load a Landsat collection, map the NDVI and cloud masking functions over it. var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA') .filterBounds(ee.Geometry.Point([-122.262, 37.8719])) .filterDate('2014-03-01', '2014-05-31') .map(addNDVI) .map(cloudMask); // Reduce the collection to the mean of each pixel and display. var meanImage = collection.reduce(ee.Reducer.mean()); var vizParams = {bands: ['B5_mean', 'B4_mean', 'B3_mean'], min: 0.02, max: 0.4}; Map.addLayer(meanImage, vizParams, 'mean'); // Load a region in which to compute the mean and display it. var counties = ee.FeatureCollection('TIGER/2018/Counties'); var santaClara = ee.Feature(counties.filter(ee.Filter.eq('NAME', 'Santa Clara')).first()); Map.addLayer(santaClara); // Get the mean of NDVI in the region. var mean = meanImage.select(['nd_mean']).reduceRegion({ reducer: ee.Reducer.mean(), geometry: santaClara.geometry(), scale: 30 }); // Print mean NDVI for the region. mean.get('nd_mean').evaluate(function(val){ print('Santa Clara spring mean NDVI:', val); });