在GEE中,對單個Image進行可視化十分常見,但如何對ImageCollection進行可視化呢?
GEE給出了靜態和動態的方法,因此你可以將可視化的參數賦予給ImageCollection中每一個Image,也可以更高級地利用GEE提供的函數將ImageCollection以一個動畫或一系列幻燈片形式進行動態可視化,快速評估ImageCollection的內容,觀測時空變化。
我將這一部分內容分為三塊:
一、獲取無雲有序的影像集
二、可視化實現的方法
三、可視化的高級功能
當然,心急的朋友可以從第二塊內容開始閱讀~~~~
一、獲取無雲有序的影像集
我們需要根據遙感影像本身的特點和自身的需求,篩選出盡量無雲且噪聲較小的影像集作為可視化的素材,一般使用 filter(過濾)+ruduce(合成)的操作。
(1)按日期區間的合成
這里使用選擇MODIS 16天的NDVI數據作為例子,這樣操作后的集合產生的動畫噪聲較小,因為每個圖像代表20多年數據中每16天的NDVI復合圖像的中值:
//創建一個從1到365、步長為16(天)的數列,代表一年中的影像區間
var doyList = ee.List.sequence(1, 365, 16);
//導入MOSIS NDVI數據集
var ndviCol = ee.ImageCollection('MODIS/006/MOD13A2').select('NDVI');
//遍歷數列,構建影像列表
var ndviComplist = doyList.map(function(startDoy){
startDoy = ee.Number(startDoy);
//按日期范圍過濾圖像,起始日期是當前日期startDoy,結束日期是當前日期的15天后
return ndviCol
.filter(ee.Filter.calendarRange(startDoy, startDoy.add(15),
'day_of_year'))
//將過濾得到的日期區間內的所有圖像取中值,合成為一個圖像
.reduce(ee.Reducer.median());
});
//將list格式的圖像列表轉換為ImageCollection格式
var ndviCompCol = ee.ImageCollection.fromImages(ndviCompList);
(2)按季節的年際合成
但是對於Landsat影像,每個傳感器針對給定場景每16天收集一次Landsat數據,使得圖像的某些部分經常被雲遮蓋。因此,可以考慮用遮蓋雲層並合成同一季節的幾張年度圖像可以產生更加無雲的圖像。下面的例子對每年7月和8月的Landsat 5圖像取中值得到從1985年到2011年的每年的合成影像:
var lsCol = ee.ImageCollection('LANDSAT/LT05/C01/T1_SR')
.filterBounds(ee.Geometry.Point(-122.9, 43.6))
//得到每年7月-8月的影像
.filter(ee.Filter.dayOfYear(182, 243))
//給每個圖像添加"year"屬性
.map(function(img) {
return img.set('year', ee.Image(img).date().get('year'));
});
//定義一個函數以掩膜圖像中雲和陰影。
var cloudMask = function(img) {
var qa = img.select('pixel_qa');
var cloud = qa.bitwiseAnd(1 << 5).or(qa.bitwiseAnd(1 << 3));
return img.updateMask(cloud.not());
//獲取有7月-8月圖像的年份
var years = ee.List(lsCol.aggregate_array('year')).distinct().sort();
//生成年份列表以構建年度圖像合成列表。
var lsCompList = years.map(function(year) {
return lsCol
// 按年份過濾圖像集
.filterMetadata('year', 'equals', year)
//使用雲層掩膜函數
.map(cloudMask)
//對同年內的所有影像取中值合成為一個圖像
.reduce(ee.Reducer.median())
//將合成年份設置為圖像屬性。
.set('year', year);
});
//將list格式的圖像列表轉換為ImageCollection格式
var lsCompCol = ee.ImageCollection.fromImages(lsCompList);
(3)進階——使用join方法
前兩種方法是通過構建天和年的列表來逐步定義新日期以進行過濾和合成。使用join方法也可以實現這樣的操作。下面的例子,首先得到了一個Unique年份集合並使用saveall
將屬於相同年份的影像將被分到一個List對象中,在使用遍歷的方法得到每年的合成影像。
var lsCol = ee.ImageCollection('LANDSAT/LT05/C01/T1_SR')
.filterBounds(ee.Geometry.Point(-122.9, 43.6))
.filter(ee.Filter.dayOfYear(182, 243))
// 給每個圖像添加"year"屬性
.map(function(img) { return img.set('year', ee.Image(img).date().get('year')); });
//得到不重復年份的影像集,里面每個影像代表一個年份
var distinctYears = lsCol.distinct('year').sort('year');
//定義一個聯接過濾器;一對多加入“年份”屬性。
var filter = ee.Filter.equals({leftField: 'year', rightField: 'year'});
// 定義一個連接.
var join = ee.Join.saveAll('year_match');
//應用join,將“year_match”屬性添加到每個不重復年的代表圖像。
//每個圖像的“year_match”屬性是包含屬於相應年份的所有圖像,是一個List格式
var joinCol = join.apply(distinctYears, lsCol, filter);
// 定義一個函數以掩膜圖像中雲和陰影。
var cloudMask = function(img) {
var qa = img.select('pixel_qa');
var cloud = qa.bitwiseAnd(1 << 5).or(qa.bitwiseAnd(1 << 3));
return img.updateMask(cloud.not()); };
//遍歷每個不同年份的圖像集
var lsCompList = joinCol.map(function(img) {
//獲取屬於給定年份的圖像列表。
return ee.ImageCollection.fromImages(img.get('year_match'))
//使用雲層掩膜
.map(cloudMask)
//取中值
.reduce(ee.Reducer.median())
//將合成年份設置為圖像屬性
.copyProperties(img, ['year']);
});
//將list格式的圖像列表轉換為ImageCollection格式
var lsCompCol = ee.ImageCollection(lsCompList);
下面的例子根據Landsat影像的行列信息對集合進行過濾后,將使用join操作對來自同一日期的Landsat圖像進行鑲嵌。
var lsCol = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterDate('2017-01-01', '2019-01-01')
.filter('WRS_PATH == 38 && (WRS_ROW == 28 || WRS_ROW == 29)')
.map(function(img) {
var date = img.date().format('YYYY-MM-dd');
return img.set('date', date);
});
var distinctDates = lsCol.distinct('date').sort('date');
var filter = ee.Filter.equals({leftField: 'date', rightField: 'date'});
var join = ee.Join.saveAll('date_match');
var joinCol = join.apply(distinctDates, lsCol, filter);
var lsColMos = ee.ImageCollection(joinCol.map(function(col) {
return ee.ImageCollection.fromImages(col.get('date_match')).mosaic();
}));
(4)排序
按時間對集合進行排序,以確保按正確的時間順序排列,或者按您選擇的屬性排序。默認情況下,集合是按照自然順序排序,也可以使用sort方法根據影像的屬性進行排序。
//按觀察時間排序,使用system:time_start屬性
var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
.filterBounds(ee.Geometry.Point(-122.1, 37.2))
.sort('system:time_start');
//或者通過雲量來定義順序
var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
.filterBounds(ee.Geometry.Point(-122.1, 37.2))
.sort('CLOUDY_PIXEL_PERCENTAGE');
//也可以通過派生的屬性來定義,例如NDVI均值。
var aoi = ee.Geometry.Point(-122.1, 37.2).buffer(1e4);
var ndviCol = ee.ImageCollection('MODIS/006/MOD13A1')
.filterDate('2018-01-01', '2019-01-01')
.select('NDVI')
// 遍歷圖像集合以計算區域內的平均NDVI並將其作為屬性
.map(function(img) {
var meanNdvi = img.reduceRegion({
reducer: ee.Reducer.mean(),
geometry: aoi,
scale: 500});
return img.set('meanNdvi', meanNdvi.get('NDVI'));
})
// 根據NDVI均值倒敘排列
.sort('meanNdvi', false);