GEE 案例——利用哨兵-2 图像时间序列和谷歌地球引擎云计算自动绘制和监测香港海洋水质参数
目录
简介
结论
代码
结果
APP链接
引用
简介
对沿海水质的持续监测对于水资源管理和海洋生态系统的可持续性至关重要。 遥感数据(如哨兵-2 卫星图像)可提供用于时间序列分析的高分辨率观测数据,而基于云的谷歌地球引擎(GEE)平台则支持简单的图像检索和大规模处理。 本研究以香港沿岸水域为研究区域,利用 GEE (i) 查询和预处理所有与现场测量吻合的哨兵-2 观测数据;(ii) 提取光谱,利用人工神经网络建立水质参数的经验模型;(iii) 利用空间分布图、时间序列图和在线应用程序将结果可视化。 建模工作流程适用于 22 个水质参数,结果表明可以预测若干营养物质和无机成分的水平。 对叶绿素-a、悬浮固体和浊度进行了深入分析,在与独立数据集进行验证时,预测值与观测值之间具有很高的相关性。 选定的输入变量符合光学成分的光谱特征。 由于自动提取了所有可用图像以及不同年份和月份的更多观测数据,因此与同一地区的以往研究相比,结果更为可靠。 除了通过分布图和时间序列图直观显示长期的空间和时间变化外,还可以利用根据历史数据开发的模型捕捉监测期间可能出现的异常情况,包括藻类大量繁殖。 还创建了一个在线应用程序,使新用户能够通过简单的网络界面探索和分析水质趋势。 遥感图像、现场测量和云计算的综合利用为实施有效的监测计划和了解水质动态提供了新的机遇。 虽然获得的精度水平低于预期标准,但考虑到及时提供信息的成本和计算效率,本研究中展示的端到端云计算工作流程应得到进一步研究。
结论
以香港沿海水域为研究区域,本研究利用GEE进行以下工作:(i) 查询和预处理所有与现场测量相符的Sentinel-2观测数据;(ii) 提取光谱以使用人工神经网络(ANN)开发不同水质参数的经验模型;(iii) 使用空间分布图、时间序列图和在线应用程序展示结果。这些功能使新手用户能够发现、分析和可视化遥感图像中的空间和时间模式。本研究表明,Sentinel-2卫星图像、现场测量和GEE云计算平台的整合可以为提供具有成本效益和及时性的水质参数预测提供新的机会。通过分析本研究中的多个水质参数,制图结果可以帮助全面理解研究区域内水质的动态变化,提高对人类活动相关环境变化的认识,并促进合理的管理政策。当未来有更长时间的水质测量记录和可自由获取的地球观测数据可用时,可以开发更综合和稳健的预测模型,以继续为有效的水资源监测框架做出贡献。
代码
//定义研究区
var aoi = ee.Geometry.Polygon([[[113.800, 22.570],[113.800, 22.120],[114.514, 22.120],[114.514, 22.570]]]);
//影像加载
var Chla = ee.ImageCollection('users/khoyinivan/S2_Chla_ANN');
var vis = {palette: ['#2b83ba', '#abdda4', '#ffffbf', '#fdae61', '#d7191c'],
min: 0.2, max: 30.0};
var SS = ee.ImageCollection('users/khoyinivan/S2_SS_ANN');
var Tur = ee.ImageCollection('users/khoyinivan/S2_Tur_ANN');
//外界安装包
var utils = require('users/gena/packages:utils');
var text = require('users/gena/packages:text');
Map.centerObject(aoi, 11);
var bounds = aoi.bounds();
//将数据设为 8 位,这是制作视频所必需的
var Chla_video = Chla.map(function(image){
var label = ee.Date(image.get('system:time_start')).format('YYYY-MM-dd');
return image.visualize({
forceRgbOutput: true,
palette: ['#2b83ba', '#abdda4', '#ffffbf', '#fdae61', '#d7191c'],
min: 0.2, max: 30.0
}).set({label: label});
});
// 诠释
var annotations = [{position: 'left', offset: '1%', margin: '1%', property: 'label', scale: Map.getScale() * 5}];
Chla_video = Chla_video.map(function(image) {
return text.annotateImage(image, {}, bounds, annotations);
});
var Chla_list = Chla_video.toList(Chla_video.size());
/*
* 地图图层配置
*/
// 创建主要的地图
var mapPanel = ui.Map();
/*
* 面板设定
*/
// 创建一个面板,用于放置标题、介绍文本、图表和图例组件。
var inspectorPanel = ui.Panel({style: {width: '30%'}});
// 创建面板进行介绍
var intro = ui.Panel([
ui.Label({
value: 'Marine Water Quality Inspector - Time Series Estimated From Satellite Image (2015-2021)',
style: {fontSize: '20px', fontWeight: 'bold'}
}),
ui.Label('Refresh the browser if the charts cannot be shown.'),
ui.Label('Background of this app can be found in:'),
ui.Label('https://github.com/ivanhykwong/Marine-Water-Quality-Time-Series-HK').setUrl('https://github.com/ivanhykwong/Marine-Water-Quality-Time-Series-HK'),
ui.Label('Click a location to see its time series of Chlorophyll-a (μg/L).')
]);
inspectorPanel.add(intro);
// 创建面板来保存长/纬度值。
var lon = ui.Label();
var lat = ui.Label();
inspectorPanel.add(ui.Panel([lon, lat], ui.Panel.Layout.flow('horizontal')));
// 为图表和图例添加占位符。
inspectorPanel.add(ui.Label('[Chart]'));
inspectorPanel.add(ui.Label('[Legend]'));
inspectorPanel.add(ui.Label('Click a location to see its time series of other indicators.'));
inspectorPanel.add(ui.Label('[Chart-SS]'));
inspectorPanel.add(ui.Label('[Chart-TUR]'));
/*
* 图表设定
*/
// 为给定坐标生成新的 SST 时间序列图。
var generateChart = function (coords) {
// 使用点击事件中的值更新长/纬度面板。
lon.setValue('lon: ' + coords.lon.toFixed(2));
lat.setValue('lat: ' + coords.lat.toFixed(2));
// 为点击的点添加一个点。
var point = ee.Geometry.Point(coords.lon, coords.lat);
var dot = ui.Map.Layer(point, {color: '000000'}, 'clicked location');
// 将点添加为第二层,使其显示在合成层之上。
mapPanel.layers().set(1, dot);
// 根据时间序列制作图表。
var sstChart = ui.Chart.image.series(Chla, point, ee.Reducer.mean(), 50);
// 自定义图表。
sstChart.setOptions({
title: 'Chlorophyll-a: time series',
titleTextStyle: {fontSize: 16},
vAxis: {title: 'Chlorophyll-a (μg/L)'}, //, viewWindow: { min: 0, max: 30 }
hAxis: {title: 'Date', format: 'MM-yyyy', gridlines: {count: 7}},
pointSize: 5,
legend: {position: 'none'}
});
// 在固定位置添加图表,以便新图表覆盖旧图表。
inspectorPanel.widgets().set(2, sstChart);
};
/*
* 图例设定
*/
// 根据给定的调色板创建用于图例的色条缩略图。
function makeColorBarParams(palette) {
return {
bbox: [0, 0, 1, 0.1],
dimensions: '100x10',
format: 'png',
min: 0,
max: 1,
palette: palette,
};
}
// 为图例创建颜色条。
var colorBar = ui.Thumbnail({
image: ee.Image.pixelLonLat().select(0),
params: makeColorBarParams(vis.palette),
style: {stretch: 'horizontal', margin: '0px 8px', maxHeight: '24px'},
});
// 创建一个包含三个数字的图例面板。
var legendLabels = ui.Panel({
widgets: [
ui.Label(vis.min, {margin: '4px 8px'}),
ui.Label(
(vis.max / 2),
{margin: '4px 8px', textAlign: 'center', stretch: 'horizontal'}),
ui.Label(vis.max, {margin: '4px 8px'})
],
layout: ui.Panel.Layout.flow('horizontal')
});
var legendTitle = ui.Label({
value: 'Map Legend: Chlorophyll-a (μg/L)',
style: {fontWeight: 'bold'}
});
var legendPanel = ui.Panel([legendTitle, colorBar, legendLabels]);
inspectorPanel.widgets().set(3, legendPanel);
// 为给定坐标生成新的 SST 时间序列图。
var generateChart_SS = function (coords) {
// 为点击的点添加一个点。
var point = ee.Geometry.Point(coords.lon, coords.lat);
// 根据时间序列制作图表。
var sstChart = ui.Chart.image.series(SS, point, ee.Reducer.mean(), 50);
// 自定义图表。
sstChart.setOptions({
title: 'Suspended Solids: time series',
titleTextStyle: {fontSize: 16},
vAxis: {title: 'Suspended Solids (mg/L)'}, //,viewWindow: { min: 0, max: 30 }
hAxis: {title: 'Date', format: 'MM-yyyy', gridlines: {count: 7}},
pointSize: 5,
legend: {position: 'none'}
});
// 在固定位置添加图表,以便新图表覆盖旧图表。
inspectorPanel.widgets().set(5, sstChart);
};
// 为给定坐标生成新的 SST 时间序列图。
var generateChart_TUR = function (coords) {
//为点击的点添加一个点。
var point = ee.Geometry.Point(coords.lon, coords.lat);
// 根据时间序列制作图表。
var sstChart = ui.Chart.image.series(Tur, point, ee.Reducer.mean(), 50);
// 自定义图表。
sstChart.setOptions({
title: 'Turbidity: time series',
titleTextStyle: {fontSize: 16},
vAxis: {title: 'Turbidity (NTU)'}, //, viewWindow: { min: 0, max: 25 }
hAxis: {title: 'Date', format: 'MM-yyyy', gridlines: {count: 7}},
pointSize: 5,
legend: {position: 'none'}
});
// 在固定位置添加图表,以便新图表覆盖旧图表。
inspectorPanel.widgets().set(6, sstChart);
};
/*
* 地图设定
*/
// 创建一个包含滑块和标签的面板。
var uilabel = ui.Label('Chlorophyll-a time series (1=earliest)');
var DateSlider = ui.Slider({min: 1, max: 120, step: 1,
style: {stretch: 'horizontal', width:'500px', fontWeight: 'bold'},
onChange: (function(value) {
mapPanel.layers().reset();
mapPanel.layers().add(ee.Image(Chla_list.get(value - 1)), 'Chl-a');
})
});
DateSlider.setValue(120); // Set a default value.
mapPanel.layers().add(ee.Image(Chla_list.get(0)), 'Chl-a');
var uipanel = ui.Panel({
widgets: [uilabel, DateSlider],
layout: ui.Panel.Layout.flow('horizontal')
});
// 将面板添加到地图上。
mapPanel.add(uipanel);
// 在默认地图上注册一个回调,以便在点击地图时调用。
mapPanel.onClick(generateChart);
mapPanel.onClick(generateChart_SS);
mapPanel.onClick(generateChart_TUR);
// 配置地图。
mapPanel.style().set('cursor', 'crosshair');
// 使用测试点进行初始化。
var initialPoint = ee.Geometry.Point(114.10, 22.30);
mapPanel.centerObject(aoi, 11);
/*
* 初始化应用
*/
// 用包含检查器和地图的 SplitPanel 替换根目录。
ui.root.clear();
ui.root.add(ui.SplitPanel(inspectorPanel, mapPanel));
generateChart({
lon: initialPoint.coordinates().get(0).getInfo(),
lat: initialPoint.coordinates().get(1).getInfo()
});
generateChart_SS({
lon: initialPoint.coordinates().get(0).getInfo(),
lat: initialPoint.coordinates().get(1).getInfo()
});
generateChart_TUR({
lon: initialPoint.coordinates().get(0).getInfo(),
lat: initialPoint.coordinates().get(1).getInfo()
});
结果
APP链接
https://khoyinivan.users.earthengine.app/view/marine-water-quality-hk
引用
Kwong, I. H. Y., Wong, F. K. K., & Fung, T. (2022). Automatic mapping and monitoring of marine water quality parameters in Hong Kong using Sentinel-2 image time-series and Google Earth Engine cloud computing. Frontiers in Marine Science, 9, 871470. doi: 10.3389/fmars.2022.871470