这算是第一次用GEE进行实验分析。为了从稍微简单的地方入门,这里先选择提取水体和植被的实验,使用的方法也是最常见的NDWI指数和NDVI指数。
实验直接在GEE网页端的工作台上进行,所以使用的是JavaScript语法。如果要在python环境下运行,需要先配置环境,详见个人博客配置GEE谷歌地球引擎的Python环境(conda命令)_Deng__zy的博客-CSDN博客
实验范围是武汉地区,遥感数据源是哨兵二号2020年的影像数据。
首先做一些知识储备,这里提取水体使用的是NDWI指数,即 Normalized Difference Water Index,(归一化水指数),计算方法如下:
NDWI =(p(Green)-p(NIR))/(p(Green)+p(NIR))
对于哨兵二号数据源而言,带入相应波段,上述公式对应的是:
NDWI = (band3 - band8) / (band3 + band8)
这一点可以在哨兵二号的数据集介绍中查到:
现在我们理一理大致的思路:使用武汉市的矢量范围来划定相应的影像范围,然后对这些影像进行波段运算,进而得到NDWI指数的表现。接下来进行实验:
首先加载出武汉市的矢量范围和哨兵二号数据集(这里是直接加载的,所以没法复制代码):
使用如下代码查看范围:
var district = table;
var district_geometry = district.geometry();
Map.addLayer(table,{},"wuhan")
可以查看武汉市矢量范围:
接下来选择合适的数据集。理论上来说使用的影像应当经过一些预处理(如去云)。这里为了简化操作,暂时先不进行这些预处理(其实我们使用的影像已经经过了一些基本的预处理,只是大部分情况下可能不太够)。
通过如下代码导入哨兵二号2020年的影像:
//处理数据,生成数据集
var image = ee.ImageCollection('COPERNICUS/S2')
.filterBounds(district_geometry)//区域筛选
.filterDate('2020-01-01', '2020-12-30')//时间范围
.mosaic()//镶嵌为一张影像
这里要注意的是,经过区域筛选得到的影像不止一张,如果只是单纯的将这些影像导出并赋给image变量,这时的image就包含了不止一张影像,这在后续的处理中会导致一些波段计算的函数无法使用,所以一定要使用mosaic进行镶嵌。
接下来计算ndwi指数,参照之前的公式,我们可以这样计算:
var NIR = image.select('B8')
var RED = image.select('B3')
var fenmu =NIR.add(RED)
var fenzi=NIR.subtract(RED)
var ndwi =fenzi.divide(fenmu)
这相当是将ndwi指数的计算一步步做了拆解,其实GEE为我们提供了一个函数,可以一步完成上述的计算:
var ndwi = image.normalizedDifference(['B3', 'B8']);
现在我们完成了计算,需要将结果显示在图上,这时就需要设置显示模式:
var ndwiViz = {'min': -0.5, 'max': 0.5, 'palette': ['00FFFF', '0000FF']};
这里的参数设置不用一直记着,需要用的时候进行查阅即可。
最后我们使用展示函数:
Map.addLayer(ndwi, ndwiViz, 'NDWI');
得到的结果如下,这就是我们计算出的ndwi波段:
接下来设置水体掩膜,将计算出的ndwi指数阈值设为0.05,即保留ndwi大于0.05的区域:
var ndwiMasked = ndwi.updateMask(ndwi.gte(0.05));
Map.addLayer(ndwiMasked, ndwiViz, 'NDWI masked');
加载在卫星影像上看到的效果如下:
同理计算NDVI(归一化植被指数),将波段计算调整为:
var ndvi = image.normalizedDifference(['B8', 'B4']);
var ndviViz = {'min': -0.2, 'max': 0.8, 'palette': ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901', '66A000', '529400',
'3E8601', '207401', '056201', '004C00', '023B01', '012E01', '011D01', '011301']}
Map.addLayer(ndvi, {}, 'NDVI');
var ndviMasked = ndvi.updateMask(ndvi.gte(0.2));
Map.addLayer(ndviMasked, ndviViz, 'NDWI masked');
加载至卫星影像上效果如下:
其实我们还可以通过设置去云函数来筛选去除影像云层,之后再进行波段计算。具体函数如下:
function maskS2clouds(image) {
var qa = image.select('QA60');
// Bits 10和11分别是云和卷云
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
// Both flags should be set to zero, indicating clear conditions.
var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
.and(qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask).divide(10000);
}
这样我们就可以将影像加载函数修改为:
var image = ee.ImageCollection('COPERNICUS/S2')
.filterBounds(district_geometry)//区域筛选
.filterDate('2020-01-01', '2020-12-30')//时间范围
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 1))
.map(maskS2clouds)
.mosaic()
以上只是进行了初步的实验探究,对其中参数的把握还很不到位,后面会进行改正。