GEE筆記:多日期滑動元件
GEE筆記:多日期滑動元件
前言
最近在進行土地覆被變化驗證的相關研究,看到了Cohen等人為LandTrendr開發的 基於Landsat時間序列影像的驗證工具:TimeSync。為了滿足自己的需要(好像TimeSync在GEE上使用還要先將影像下載到本地???),本菜雞參考大神們的程式碼,基於GEE平臺弄了一個顯示Landsat系列可以進行目視解譯驗證的工具(萌新求輕噴)。
一、GEE官方的日期滑動元件程式碼
程式碼如下(原文連結:https://developers.google.com/earth-engine/guides/ui_widgets)
// Use a DateSlider to create annual composites of this collection.
var collection = ee.ImageCollection('LANDSAT/LC08/C01/T1');
// Use the start of the collection and now to bound the slider.
var start = ee.Image(collection.first()).date().get('year').format();
var now = Date.now();
var end = ee.Date(now).format();
// Run this function on a change of the dateSlider.
var showMosaic = function(range) {
var mosaic = ee.Algorithms.Landsat.simpleComposite({
collection: collection.filterDate(range.start(), range.end())
});
// Asynchronously compute the name of the composite. Display it.
range.start().get('year').evaluate(function(name) {
var visParams = {bands: ['B4', 'B3', 'B2'], max: 100};
var layer = ui.Map.Layer(mosaic, visParams, name + ' composite');
Map.layers().set(0, layer);
});
};
// Asynchronously compute the date range and show the slider.
var dateRange = ee.DateRange(start, end).evaluate(function(range) {
var dateSlider = ui.DateSlider({
start: range['dates'][0],
end: range['dates'][1],
value: null,
period: 365,
onChange: showMosaic
});
Map.add(dateSlider.setValue(now));
});
二、多日期滑動元件
程式碼如下(示例):
程式碼看起來很長主要分為兩部分:
- 對Landsat SR影像的一些預處理(雲掩膜、波段計算等等)
- 通過日期滑動元件分別展示研究區的Lansat-5,7,8年度中值合成影像
var roi = ee.FeatureCollection("xxx");
//######################################################################################
//# Preparing #\\
//######################################################################################
//1.-------------------------------------------------------------------
// Define function to get and rename bands of interest from ETM+.
var renameETM =function(img) {
return img.select(
['B1', 'B2', 'B3', 'B4', 'B5', 'B7', 'pixel_qa', 'radsat_qa'],
['B1', 'B2', 'B3', 'B4', 'B5', 'B7', 'pixel_qa', 'radsat_qa']
);
};
// Define function to get and rename bands of interest from OLI.
var renameOLI = function(img) {
return img.select(
['B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'pixel_qa'],
['B1', 'B2', 'B3', 'B4', 'B5', 'B7', 'pixel_qa']
);
};
//2.-------------------------------------------------------------------.
//cloud mask------------------------------------------------
var cloudMaskL457 = function(image) {
var qa = image.select('pixel_qa');
// If the cloud bit (5) is set and the cloud confidence (7) is high
// or the cloud shadow bit is set (3), then it's a bad pixel.
var cloud = qa.bitwiseAnd(1 << 5)
.and(qa.bitwiseAnd(1 << 7))
.or(qa.bitwiseAnd(1 << 3))
// Remove edge pixels that don't occur in all bands
var mask2 = image.mask().reduce(ee.Reducer.min());
var maskObersaturation = image.select('radsat_qa').eq(0)
return image.updateMask(cloud.not()).updateMask(mask2.and(maskObersaturation));
};
var maskL8sr = function(image) {
// Bits 3 and 5 are cloud shadow and cloud, respectively.
var cloudShadowBitMask = 1 << 3;
var cloudsBitMask = 1 << 5;
// Get the pixel QA band.
var qa = image.select('pixel_qa');
// Both flags should be set to zero, indicating clear conditions.
var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
.and(qa.bitwiseAnd(cloudsBitMask).eq(0));
// Return the masked image, scaled to reflectance, without the QA bands.
return image.updateMask(mask);
}
//3.-------------------------------------------------------------------
//Add bands--------------------------------------------------
var addbands = function(img) {
var ndvi = img.normalizedDifference(["B4", "B3"]).rename(["NDVI"]);
var img1 = img.addBands(ndvi)
.set('system:time_start', img.get('system:time_start'));
return img1;
};
//4.-------------------------------------------------------------------
//divide-----------------------------------------------------
var divide = function(img){
img = img.select('B1', 'B2', 'B3', 'B4', 'B5','B7')
.divide(10000)
.set('system:time_start', img.get('system:time_start'));
return img;
};
//5.-------------------------------------------------------------------
// Define function to prepare OLI images.
var prepOLI = function(img) {
var orig = img;
img = renameOLI(img);
img = maskL8sr(img);
img = divide(img);
img = addbands(img);
return ee.Image(img.copyProperties(orig, orig.propertyNames()));
}
// Define function to prepare ETM+ images.
var prepETM = function(img) {
var orig = img;
img = renameETM(img);
img = cloudMaskL457(img);
//img = etm2oli(img);
img = divide(img);
img = addbands(img);
return ee.Image(img.copyProperties(orig, orig.propertyNames()));
}
//6.-------------------------------------------------------------------
var visParams = {
bands: ['B3', 'B2', 'B1'],
min: 0,
max: 0.3,
gamma: 1.4,
};
Map.centerObject(roi, 9);
var sidePanel = ui.Panel();
//######################################################################################
//# L5 part #\\
//######################################################################################
var L5 = ee.ImageCollection("LANDSAT/LT05/C01/T1_SR");
var start_1 = "1986-1-1";
var end_1 = "2011-12-31";
var showImage_1 = function(range){
print("---L5", range);
var colFilter = ee.Filter.and(
ee.Filter.bounds(roi),
ee.Filter.date(range.start(), range.end()),
//ee.Filter.lt('CLOUD_COVER', 50),
ee.Filter.lt('GEOMETRIC_RMSE_MODEL', 30),
ee.Filter.or(
ee.Filter.eq('IMAGE_QUALITY', 9),
ee.Filter.eq('IMAGE_QUALITY', 7)
)
);
// Filter collections and prepare them for merging.
var col_L5 = L5.filter(colFilter).map(prepETM).map(function(image){return image.clip(roi)});
var imgL5_med = col_L5.reduce(ee.Reducer.median())
.select(
['B1_median', 'B2_median', 'B3_median', 'B4_median','B5_median','B7_median', 'NDVI_median'],
['B1', 'B2', 'B3', 'B4', 'B5','B7', 'NDVI']);
range.start().get('year').evaluate(function(name) {
var layer_1 = ui.Map.Layer(imgL5_med, visParams, name + ' Landsat 5 composite');
Map.layers().set(0, layer_1);
});
};
showImage_1(ee.DateRange(start_1, ee.Date(start_1).advance(1, "year")));
ee.DateRange(start_1, end_1).evaluate(function(range) {
print("+++L5",range);
var dateSlider = ui.DateSlider({
start: range['dates'][0],
end: range['dates'][1],
value: start_1,
period: 365,
onChange: showImage_1,
style: {
width: "500px",
padding: "2px"
}
});
var main_panel_1 = ui.Panel({
widgets: [
ui.Label('Landsat 5 compsites 1986-2011', {fontWeight: 'bold'}),
dateSlider
],
style: {
width: "520px",
padding: "4px"
}
});
sidePanel.add(main_panel_1);
});
//######################################################################################
//# L7 part #\\
//######################################################################################
var L7 = ee.ImageCollection("LANDSAT/LE07/C01/T1_SR");
var start_2 = "1999-1-1";
var end_2 = "2019-12-31";
var showImage_2 = function(range){
print("---L7", range);
var colFilter_2 = ee.Filter.and(
ee.Filter.bounds(roi),
ee.Filter.date(range.start(), range.end()),
//ee.Filter.lt('CLOUD_COVER', 50),
ee.Filter.lt('GEOMETRIC_RMSE_MODEL', 30),
ee.Filter.or(
ee.Filter.eq('IMAGE_QUALITY', 9),
ee.Filter.eq('IMAGE_QUALITY', 7)
)
);
// Filter collections and prepare them for merging.
var col_L7 = L7.filter(colFilter_2).map(prepETM).map(function(image){return image.clip(roi)});
var imgL7_med = col_L7.reduce(ee.Reducer.median())
.select(
['B1_median', 'B2_median', 'B3_median', 'B4_median','B5_median','B7_median', 'NDVI_median'],
['B1', 'B2', 'B3', 'B4', 'B5','B7', 'NDVI']);
range.start().get('year').evaluate(function(name) {
var layer_2 = ui.Map.Layer(imgL7_med, visParams, name + ' Landsat 7 composite');
Map.layers().set(1, layer_2);
});
};
showImage_2(ee.DateRange(start_2, ee.Date(start_2).advance(1, "year")));
ee.DateRange(start_2, end_2).evaluate(function(range) {
print("+++L7",range);
var dateSlider = ui.DateSlider({
start: range['dates'][0],
end: range['dates'][1],
value: start_2,
period: 365,
onChange: showImage_2,
style: {
width: "500px",
padding: "2px"
}
});
var main_panel_2 = ui.Panel({
widgets: [
ui.Label('Landsat 7 compsites 2013-2019', {fontWeight: 'bold'}),
dateSlider
],
style: {
width: "520px",
padding: "4px"
}
});
sidePanel.add(main_panel_2);
});
//######################################################################################
//# L8 part #\\
//######################################################################################
var L8 = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR");
var start_3 = "2013-1-1";
var end_3 = "2019-12-31";
var showImage_3 = function(range){
print("---L8", range);
var colFilter = ee.Filter.and(
ee.Filter.bounds(roi),
ee.Filter.date(range.start(), range.end()),
//ee.Filter.lt('CLOUD_COVER', 50),
ee.Filter.lt('GEOMETRIC_RMSE_MODEL', 30),
ee.Filter.or(
ee.Filter.eq('IMAGE_QUALITY', 9),
ee.Filter.eq('IMAGE_QUALITY_OLI', 9)
)
);
// Filter collections and prepare them for merging.
var col_L8 = L8.filter(colFilter).map(prepOLI).map(function(image){return image.clip(roi)});
var imgL8_med = col_L8.reduce(ee.Reducer.median())
.select(
['B1_median', 'B2_median', 'B3_median', 'B4_median','B5_median','B7_median', 'NDVI_median', ],
['B1', 'B2', 'B3', 'B4', 'B5','B7', 'NDVI']);
range.start().get('year').evaluate(function(name) {
var layer_3 = ui.Map.Layer(imgL8_med, visParams, name + ' Landsat 8 composite');
Map.layers().set(2, layer_3);
});
};
showImage_3(ee.DateRange(start_3, ee.Date(start_3).advance(1, "year")));
ee.DateRange(start_3, end_3).evaluate(function(range) {
print("+++L8",range);
var dateSlider = ui.DateSlider({
start: range['dates'][0],
end: range['dates'][1],
value: start_3,
period: 365,
onChange: showImage_3,
style: {
width: "300px",
padding: "2px"
}
});
var main_panel_3 = ui.Panel({
widgets: [
ui.Label('Landsat 8 compsites 2013-2019', {fontWeight: 'bold'}),
dateSlider
],
layout: "flow",
style: {
width: "520px",
padding: "4px"
}
});
sidePanel.add(main_panel_3);
});
ui.root.add(sidePanel);
最終的效果圖:
總結
-
通過這個元件可以很方便的利用Landsat時間序列影像進行目視解譯驗證,未來希望可以加上驗證點的某引數時間序列折線圖(比如在GEE中匯入一個FeatureCollection, 通過點選某個點就可以顯示時間序列NDVI折線圖)。
-
不知道大家除了TimeSync和GE之外還知道其他可以利用時間序列遙感影像驗證的工具嘛?
最後,希望大家能夠多與我交流指出錯誤,我會虛心接受!!!
相關文章
- Vue無限滑動周選擇日期的元件Vue元件
- 移動端左滑右滑元件元件
- CSS 小結筆記之滑動門技術CSS筆記
- vue-concise-slider vue滑動元件VueIDE元件
- C#滑動拼圖驗證碼實現筆記C#筆記
- vue元件筆記Vue元件筆記
- Vue.js 滑動拼圖驗證碼實現筆記Vue.js筆記
- vue移動端側滑皮膚元件Vue元件
- iSlider移動端原生滑動元件原始碼解讀IDE元件原始碼
- React筆記:元件(3)React筆記元件
- iOS 一個滑動選擇控制元件iOS控制元件
- GEE filter by bandsFilter
- GEE呼叫Sentinel-2 MSI L2A資料集 示例程式碼解析筆記筆記
- Flutter 實現webview與原生元件組合滑動FlutterWebView元件
- 如何用 vue 製作一個探探滑動元件Vue元件
- ❤️❌ 如何用vue製作一個探探滑動元件Vue元件
- 元件包開發筆記元件筆記
- React學習筆記-元件React筆記元件
- Ansible 多機自動化工具 初學筆記筆記
- 寫了個移動端可滑動(慣性滑動&回彈)Vue導航欄元件 ly-tabVue元件
- 日期元件初始化元件
- TensorFlow筆記-07-神經網路優化-學習率,滑動平均筆記神經網路優化
- ROG筆記本切換效能模式後,Win11 亮度滑動條失效筆記模式
- 鴻蒙第三方元件——SwipeCaptcha滑動拼圖驗證元件鴻蒙元件APT
- 基於Vue元件化的日期聯動選擇器Vue元件化
- react父子元件,兄弟元件,爺爺到孫子元件筆記React元件筆記
- Android側滑(右滑、下拉)返回控制元件 - SwipeBackLayoutAndroid控制元件
- Flutter學習筆記(10)--容器元件、圖片元件Flutter筆記元件
- 多執行緒筆記執行緒筆記
- Jdk8 新日期工具類 Api 學習筆記JDKAPI筆記
- 【記錄】KgCaptcha滑動拼圖驗證碼GCAPT
- Flutter學習筆記(12)--列表元件Flutter筆記元件
- Flutter學習筆記(9)--元件WidgetFlutter筆記元件
- vue學習筆記(六) ----- vue元件Vue筆記元件
- Hadoop 入門筆記—核心元件 YARNHadoop筆記元件Yarn
- Hadoop 入門筆記—核心元件 MapRuduceHadoop筆記元件
- Hadoop 入門筆記—核心元件 HDFSHadoop筆記元件
- [MAUI]模仿iOS多工切換卡片滑動的互動實現UIiOS