開始使用GEE
這篇引導(dǎo)旨在為大家使用JavaScript語言的API提供一個快速路徑,如果想要JavaScript的詳細介紹或是得到API更加深入的使用,可以看這里,如果想要關(guān)于JavaScript代碼風(fēng)格的建議,則可以看谷歌對于JS編碼的指導(dǎo)
GEE允許用戶對儲存在Google基礎(chǔ)框架上的地理配準(zhǔn)圖(Georeferrenced Imagery)和矢量(Vector)運行一些算法,API提供了很多的功能,可以在圖像上有所運用,既可以做顯示,又可以做分析。這里有一份GEE的公開數(shù)據(jù)清單,它包含了大量開源可用的圖像和矢量數(shù)據(jù)集,大家也可以在個人文件夾里放一些自己的數(shù)據(jù)。

代碼編輯器(Code Editor)是一個用于開發(fā)GEE程序的交互式環(huán)境,界面就如Fig.1所示,中間的部分是一個JavaScript的代碼編輯頁面,編輯器上面有一些按鈕,可以用來執(zhí)行保存腳本、運行代碼、清空頁面等操作。還有一個Get Link按鈕,可以在地址框(Address Bar)里生成一個唯一性的URL。底部的展示面板展示了正在運行的腳本所加入的所有圖像層(Layer),頂部還有一個搜索欄(Search Box),可以搜索數(shù)據(jù)集,也可以搜索某個地點,隨人所愿。左邊有一個實例代碼的展示區(qū),可以用來存放腳本或是在里面找API或是在資產(chǎn)庫(Asset)里檢索自己的私人文件。右部有一個對檢查器(Inspector)、一個輸出面板(Output Console),還有一個對于任務(wù)管理器(Manager),幫助按鈕在右上方,里面有指向指導(dǎo)文檔的鏈接還有其他文件??梢詮?a target="_blank">代碼編輯器指導(dǎo)和幫助文檔中得到更多信息。
打開,并在代碼編輯器中Run起來
我們演示一下如何打開GEE的并執(zhí)行一下顯示圖像的腳步,如果想得到最好的效果,推薦安裝最新的Chrome。
- 打開GEE代碼編輯器如果你還沒注冊,那就用Google賬戶注冊一個。
- 代碼編輯器最左邊有一個腳本(Scripts)選項卡,可以在那里找到一組腳本實例,你可以訪問、展示并且在GEE中運行它們。
- 在圖像集(Image Collection)下,選擇過濾復(fù)合(Filtered Composite),你就能在中控臺(Center Console)上看到一個腳本,點一下運行(Run)按鈕,就會選擇科羅拉多州和猶他州相交位置一定范圍內(nèi)Landsat-7衛(wèi)星的圖像,它的顯示使用真彩色合成的,這個例子會展示一下
filter()、clip()和Map.addLayer()等基本的功能。
GEE數(shù)據(jù)結(jié)構(gòu)
GEE中兩個最基本的數(shù)據(jù)結(jié)構(gòu)是Image和ImageCollection(這兩個東西會經(jīng)常用,也很好理解,不譯),二者分別代表了光柵圖像(Raster)和矢量圖(Vector)。Image容納里波段(Band)信息和一個特性(Properties)組成的字典,Feature則是由幾何信息和特征字典組成。一個圖像的堆??梢员徽蠟橐粋€ImageCollection,特征的集合則可以被整合為FeatureCollection,GEE中還有一些基本的數(shù)據(jù)結(jié)構(gòu),有Dictionary、Data、Number和String等,重要的是記住這些數(shù)據(jù)結(jié)構(gòu)都是面向服務(wù)器端的,這就意味著,除非你特意要求,你的瀏覽器不會知道你的腳本的任何信息。而你的特意要求會從Google傳遞到代碼編輯器,如果信息Size比較大,速度就會稍微慢一點。
GEE的計算方法
有好幾種調(diào)用API的方法,包括:
- 調(diào)用對象自己的方法;
- 調(diào)用算法;
- 使用代碼編輯器中特有的的函數(shù);
- 定義一些新函數(shù);
代碼編輯器列表中的文檔(Docs)里有各個API類的使用方法(Method),舉個例子,在Image類里,有一個方法是這樣用的:
var image3 = image1.add(image2);
這個方法把image2的波段添加到image1里,ee.Algorithms類包括一個特定算法的列表,想從輸入的DEM中創(chuàng)建一個圖層,可以這樣做:
var terrainImage = ee.Algorithms.Terrain(dem);
代碼編輯器還有一些特殊的函數(shù),包括Map還有其他的導(dǎo)出方法,能夠把選中的圖道導(dǎo)出到Google Drive中。在代碼編輯器里,可以這樣創(chuàng)建函數(shù):
var myFunction = function(args) {
// do something
return something;
};
想要使用定義好的函數(shù)去創(chuàng)造一個Collection,可以這樣做:
var collection2 = collection1.map(aFunction);
在GEE中,靜態(tài)的方法叫做Class(像是ee.Image),被寫作
Image.staticMethod()而在類的實例中被調(diào)用的放大被寫作image.instanceMethod(),小寫的image意思是這是一個名叫image的變量,是ee.Image的一個實例。
使用JavaScript打印‘Hello World!’
把特定的信息打印到輸出面板上,是得到一個東西的信息的基本方法,展示一些數(shù)據(jù)性的結(jié)果,或是展示一個元數(shù)據(jù)(Metadata),或是一些Debug用的幫助信息,都可以這樣做。在代碼編輯器打印'Hello World!'是這樣實現(xiàn)的:
print('Hello World!')
把這行代碼Copy到代碼編輯中,運行一下,就能在輸出面板中看到我們想要的東西。對于一個遙感實例,下面的操作可以看一些Landsat 8衛(wèi)星圖像的一些元數(shù)據(jù):
print(ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318'));
展示面板上就能看到這顆衛(wèi)星的一些圖像了。
往Map里增加一些數(shù)據(jù)
想要在展示面板上顯示一些信息,尤其是一些可視化的信息,就要用到Adding操作,使用Map.addLayer()函數(shù)達成這一目的。下面的例子里,我們先用ee.Image()加載了一張Image,然后使用Map.addLayer()函數(shù)增加了一些東西,然后,地圖就被居中顯示。
// Load an image.
var image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318');
// Center the map on the image.
Map.centerObject(image, 9);
// Display the image.
Map.addLayer(image);
Map.centerObject()函數(shù)的第二個參數(shù)代表了縮放等級,越大的數(shù)字代表了越大的區(qū)域。如果對圖像的顯示效果不滿意,可以對函數(shù)的一些參數(shù)做一些修改:
var image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318');
// Define visualization parameters in an object literal.
var vizParams = {bands: ['B5', 'B4', 'B3'], min: 5000, max: 15000, gamma: 1.3
// Center the map on the image and display.
Map.centerObject(image, 9);
Map.addLayer(image, vizParams, 'Landsat 8 false color');
我們還可以使用這個函數(shù)增加一些feature或者featureCollection,代碼如下:
var counties = ee.FeatureCollection('TIGER/2016/Counties');
Map.addLayer(counties, {}, 'counties');
找到你想要的數(shù)據(jù)
images、 image collections 和 feature collections都可以在GEE的數(shù)據(jù)清單里找到,在搜索欄中輸入Landsat 8就可以找到這顆衛(wèi)星,其他的也類似。完整的數(shù)據(jù)集的清單,可以在這里找到,點擊數(shù)據(jù)集的名字,可以查看一些基本信息,包括數(shù)據(jù)來源、ID等等。點擊導(dǎo)入(Import)按鈕,可以把這個數(shù)據(jù)集加入進來,自動地,代碼的頭部就會出現(xiàn)對應(yīng)的一行import代碼。
也可以把數(shù)據(jù)集的ID復(fù)制到代碼中來使用這個數(shù)據(jù)集:
var collection = ee ImageCollection(LANDSAT/LC08/C01/T1 )
一個Collection是來自地表的多層圖像組成的,找到一個Collection里單張的圖像要用到過濾器(Filter),也可以使用復(fù)合(Composite)和鑲嵌(Mosaick)把一個圖像的Collection削減到單張圖像。對于過濾器、復(fù)合之類的詳細信息,可以看對應(yīng)部分的文檔。
過濾和分類
我們經(jīng)常需要根據(jù)空間和(或)時間對圖像集進行過濾,主要目的是限制結(jié)果的數(shù)量,舉個例子,想知道舊金山的Landsat 8數(shù)據(jù)中沒有云霧遮擋的部分,就需要這樣做。首先,我們需要定義一個ROI,一個點通常就足夠了,點一下代碼編輯器右邊的檢查(Inspector)按鈕,就會看到你的ROI的信息,復(fù)制下來,然后就可以使用這個點了:
var point = ee.Geometry.Point(-122.262, 37.8719);
開始日期和結(jié)束日期應(yīng)該這樣設(shè)置:
var start = ee.Date('2014-06-01');
var finish = ee.Date('2014-10-01');
使用這個點和起止時間,就可以對圖像進行過濾了。
當(dāng)然,也可以把一些元數(shù)據(jù)進行修改,做到更好的過濾:
var filteredCollection = ee.ImageCollection('LANDSAT/LC08/C01/T1')
.filterBounds(point)
.filterDate(start, finish)
.sort('CLOUD_COVER', true);
這個Collection可以很安全地被展示并檢查,當(dāng)然,如果Collection中圖像數(shù)量太多,可能會很慢,可能會時間超限,甚至可能返回一個error。可以把Collection視為一個列表,使用下面的方法觀察第一張圖:
var first = filteredCollection.first();
自己可以創(chuàng)建一些過濾器,操作如下:
// 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.addLayer(filteredFC, {}, 'California');
可以在編輯器上的Get Link按鈕獲得運行代碼的一個唯一URL,方便分享或再次使用。
在Band上執(zhí)行一些數(shù)學(xué)操作
使用Image里的方法做一些數(shù)學(xué)性的操作,包括波段重組、圖像區(qū)分或是其他數(shù)學(xué)的運算,舉個例子,計算一下NDVI在20年間的變化:
// 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/C01/T1_TOA/LT05_044034_19900604');
var image2 = ee.Image('LANDSAT/LT05/C01/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);
這里使用了用戶自己定義的函數(shù),其他的函數(shù)在下一部分介紹。
重復(fù)測繪工作(拒絕循環(huán)程序)
使用map()函數(shù)做重復(fù)測繪,不要用循環(huán)。這個函數(shù)可以用在ImageCollection、FeatureCollection或是一個list里。示例代碼把NDVI增加到ImageCollection里的每一張圖像上:
// This function gets NDVI from Landsat 8 imagery.
var addNDVI = function(image) {
return image.addBands(image.normalizedDifference(['B5', 'B4']));
};
// Load the Landsat 8 raw data, filter by location and date.
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1')
.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);
另一個共同的任務(wù)是把一些東西增加到特征中,下面的實例就這樣做了:
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}),
]);
可以像下面這樣吧Collection的類型修改掉:
// 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 collection.
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1')
.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,對每一個圖像的中心它都被創(chuàng)建了。最后一行里我們把結(jié)果變成了一個FeatureCollection。
縮合
在GEE中,縮合是一種通過時間、空間、波段、數(shù)組或者其他數(shù)據(jù)結(jié)構(gòu)將數(shù)據(jù)聚合在一起的一種方式,在API中,實現(xiàn)這一目的有多種方式。舉個例子,如果想聚合成一個ImageCollection,可以使用reduce()函數(shù)將一個collection中的圖像聚合成一張。這里有一個代碼示例,把早就載入的Landsat-8衛(wèi)星數(shù)據(jù)進行聚合,聚合的內(nèi)容是至少五張無云的圖像:
// Load a Landsat 8 collection.
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1')
// 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 scene
var median = collection.limit(5).reduce(ee.Reducer.median());
縮合也是一種得到區(qū)域內(nèi)圖像統(tǒng)計信息的操作,這個任務(wù)是把感興趣的區(qū)域內(nèi)的像素點逐個進行處理,使用reducRegion()函數(shù)完成這一操作:
// Load and display a Landsat TOA image.
var image = ee.Image('LANDSAT/LC08/C01/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
});
關(guān)于縮合的具體信息,請看它的文檔。
蒙版
在ee.Image中的每一個像素,都是既包含了值,有包含了一個范圍從0到1取值的蒙版的實體,如果蒙版為0,那么就代表這個點完全被擋住了,GEE直接當(dāng)做沒有數(shù)據(jù)來處理,當(dāng)蒙版取0到1之間其他值時,就把它當(dāng)作參與數(shù)值計算的一個權(quán)值。
用戶可以使用蒙版操作做像素轉(zhuǎn)換或者排除它們,如上文所述,蒙版設(shè)置為0時意味著這個像素點被擋住了,繼續(xù)看使用蒙版操作的代碼實例:
// This function gets NDVI from Landsat 5 imagery.
var getNDVI = function(image) {
eturn image.normalizedDifference(['B4', 'B3']);
};
// Load two Landsat 5 images, 20 years apart.
var image1 = ee.Image('LANDSAT/LT05/C01/T1_TOA/LT05_044034_19900604');
var image2 = ee.Image('LANDSAT/LT05/C01/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中的蒙版,它用updataMask()函數(shù)做過一次更新。
蒙版操作對于把一些數(shù)據(jù)從分析范圍排除出去也是很重要的操作,在它的文檔可以看到更多實例。
下面的例子做了多種操作:過濾、重復(fù)測繪、縮合還有云層蒙版之類的:
// 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 i
var collection = ee.ImageCollection('LANDSAT/LC08/C01/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, max: 0.5};
Map.addLayer(meanImage, vizParams, 'mean');
// Load a region in which to compute the mean and display it.
var counties = ee.FeatureCollection('TIGER/2016/Counties');
var santaClara = ee.Feature(counties.filter(ee.Filter.eq('NAME', 'Santa Clara'),
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);
});