在本文中,将探讨如何利用地球引擎云计算平台发布一个具有分屏功能的网络应用。地球引擎提供了大量的卫星图像用于分析和展示,并且支持网络应用的发布。讨论的网络应用是分屏面板,它是地球引擎中可用的用户界面之一。该网络应用由左右两侧的两个面板组成,每个面板显示相同区域的不同图像。换句话说,两个图像被叠加并分别仅在左侧和右侧显示。默认情况下,每个面板中的图像各占一半。
这两个面板并没有完全显示,而是被一个分隔器从中间分开。分隔器可以向左或向右拖动。当分隔器向左拖动时,两个面板都会被调整大小。左侧面板的大小会变小,显示图像的区域也会相应减少。另一方面,右侧面板上的图像将显示更多的图像区域,替换分隔器经过的区域。
分屏面板对于比较两张图像特别有用,尤其是在图像的某些特定点上。之前,写过关于另一个地球引擎网络应用的文章,该应用具有链接的多个面板。链接的多个面板与分屏面板类似,也可以用来比较两张或更多的图像。链接的多个面板并排显示两张或更多的图像,但不重叠。
为了说明,可以想象将两个相同区域的地图并排放置,这就是链接的多个面板。这两个地图不重叠。如果在第一个多个面板上指向一个位置,需要仔细在另一个地图上找到相同的位置,因为它们不重叠。相比之下,分屏面板就像将一张地图放在另一张地图的上方,显示完全相同的区域。分屏面板叠加两张图像的优势在于,可以比在链接的多个面板上更容易地比较两张图像中的特定点。稍后将看到示例。
比较不同日期的图像。那么,使用分屏面板比较同一地点的两张图像有什么用呢?本文将描述两个用途。第一个用途是比较不同日期的同一地点。卫星图像确实经常用于监测。下图比较了2019年11月和2020年6月中爪哇的农作物状况。
代码的结果是发布在这个网络应用中的。下图是网络应用结果的截图。左侧图像显示了2019年11月的图像。许多区域以棕色显示,这意味着这些区域已经被收割。收割的土地以棕色显示,代表土壤或开阔地。右侧图像显示了2020年6月的土地覆盖情况,当时作物已经重新种植。拖动分隔器向左和向右,并检查许多区域的颜色从棕色变为绿色。这表明了农作物的状况。一些区域甚至被洪水淹没(深蓝色)。
分屏面板也适用于将图像分析结果输出与输入图像进行比较。为了演示,将使用监督机器学习处理一张图像。下面是一个代码示例,训练一个机器学习模型来预测2019年11月的土地覆盖类型分为三类:农作物/植被、开阔地/定居点和水体。这个过程从用土地覆盖类型标记一些区域开始训练机器学习。用于这项任务的机器学习算法是梯度提升树。然后,该模型可以预测其余区域的土地覆盖类型。
在获得机器学习预测后,可能希望将机器学习输出与输入图像叠加并逐区域进行比较。为了实现这一点,使用分屏面板。请再次查看这个发布的网络应用。它仍然与之前的网络应用相同。但这次,转到右侧面板并查看图层。检查“LandCover Nov 2019”。
现在,可以轻松地将机器学习分析结果与输入数据进行比较。通常,应该发现大多数农作物或植被被分类为绿色,开阔地/土壤或定居点为棕色,水体为蓝色。当然,可以像任何网络GIS一样放大、缩小和平移面板。
以下是运行网络应用的代码。代码从导入卫星图像开始,并标记一些区域的土地覆盖类型作为训练数据集。
// 分屏面板比较不同日期的图像和机器学习结果
// 加载Landsat 8集合
var landsat = ee.ImageCollection('LANDSAT/LC08/C01/T1');
var image = ee.Algorithms.Landsat.simpleComposite({
collection: landsat.filterDate('2019-11-01', '2019-11-30'),
asFloat: true
});
// 用于预测的特征/波段。
var bands = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7'];
// 标记训练数据
var polygons = ee.FeatureCollection([
ee.Feature(geometry0, {'class': 0}), // 裸地或定居点
ee.Feature(geometry1, {'class': 1}), // 农作物或植被
ee.Feature(geometry2, {'class': 2}), // 水体
]);
// 从训练多边形中提取像素的数字编号
var training = image.sampleRegions({
// 获取训练多边形
collection: polygons,
// 设置属性名称
properties: ['class'],
// 设置图像的空间分辨率
scale: 30
});
此代码对训练数据集执行梯度提升机器学习,并预测整个区域的土地覆盖类型。
// 构建GradientTreeBoost分类器
var trained = ee.Classifier.smileGradientTreeBoost(8).train(training, 'class', bands);
// 加载2019年11月的图像
var Nov = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2019-11-01', '2019-11-30')
.median();
// 裁剪图像
var Nov = Nov.clip(geometry);
// 对卫星图像进行分类
var classified = Nov.select(bands).classify(trained);
// 裁剪分类
var classified = classified.clip(geometry);
// 加载2020年6月的图像
var Jun = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterDate('2020-06-01', '2020-06-30')
.median();
// 裁剪图像
var Jun = Jun.clip(geometry);
以下代码在左侧显示2019年11月的图像。它还显示了2020年6月的图像和机器学习预测结果在右侧。最后,创建了一个带有中间分隔符的分屏面板。
// 显示2019年11月的合成图像
Map.addLayer(Nov , {bands: ['B6', 'B5', 'B4'], max: 0.7}, "Image Nov2019", true);
// 分屏面板
// 地图2
var map2 = ui.Map();
// 显示2020年6月的合成图像
map2.addLayer(Jun , {bands: ['B6', 'B5', 'B4'], max: 0.7}, "Image Jun2020", true);
// 显示2019年11月的分类结果
map2.addLayer(classified,
{min: 0, max: 2, palette: ['#964b00','#00FF00','#0000FF']},
'LandCover Nov 2019', false);
// 链接两个面板
var linker = ui.Map.Linker([ui.root.widgets().get(0), map2]);
// 创建分屏面板
var splitPanel = ui.SplitPanel({
firstPanel: linker.get(0),
secondPanel: linker.get(1),
orientation: 'horizontal',
wipe: true,
style: {stretch: 'both'}
});
// 将分屏面板设置为ui根
ui.root.widgets().reset([splitPanel]);
// 设置视图中心
linker.get(0).setCenter(110.4411, -6.9112, 11);
以下代码创建了地图图例,用于解释土地覆盖类别符号。
// 添加地图图例
var legend = ui.Panel({
style: {
position: 'bottom-right',
padding: '8px 15px'
}
});
var legend2 = ui.Label({
value: '土地覆盖',
style: {
fontWeight: 'bold',
fontSize: '18px',
margin: '0 0 4px 0',
padding: '0'
}
});
legend.add(legend2);
// 创建图例内容
var content = function(colour, label) {
// 创建彩色框
var box = ui.Label({
style: {
backgroundColor: colour,
// 设置框的高度和宽度
padding: '9px',
margin: '0 0 4px 0'
}
});
// 创建标签
var labels = ui.Label({
value: label,
style: {margin: '0 0 4px 6px'}
});
return ui.Panel({
widgets: [box, labels],
layout: ui.Panel.Layout.Flow('horizontal')
});
};
// 设置图例颜色
var classColour = ['#00FF00','#964b00','#0000FF'];
// 设置图例标签
var labelName = ['农作物或植被','土壤/开阔地/定居点','水体'];
// 组合图例颜色和标签
for (var i = 0; i < 3; i++) {
legend.add(content(classColour[i], labelName[i]));
}
// 添加图例
map2.add(legend);
// 添加信息
var info = ui.Panel({
style: {
position: 'bottom-center',
padding: '8px 15px'
}
});
var info2 = ui.Label({
value: '2019年11月的图像(左侧)和2020年6月的图像或2019年11月的土地覆盖类别(右侧)的分屏面板',
style: {
fontSize: '16px',
margin: '0 0 3px 0',
padding: '0'
}
});
info.add(info2);
map2.add(info);