利用GEE(Google Earth Engine)在线处理NDVI、EVI、SAVI、NDMI等指数归一化教程!
原创
©著作权归作者所有:来自51CTO博客作者此星光明的原创作品,请联系作者获取转载授权,否则将追究法律责任
1.首先进行“去云”函数的准备
//landsat5、7 EVI指数计算
// SR数据去云
function rmCloud(image) {
var cloudShadowBitMask = (1 << 3);
var cloudsBitMask = (1 << 5);
var qa = image.select("pixel_qa");
var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
.and(qa.bitwiseAnd(cloudsBitMask).eq(0));
return image.updateMask(mask);
}
以上这一步都是最简单的操作,对于处理landsat-sr系列数据都基本用到。
2.数据的选择
//这是我自己的行政矢量边界,这回用的是山西省界
var hh= ee.FeatureCollection("users/bqt2000204051/shanxijie");
//这部分代码是进行数据的选择和EVI指数的遍历计算,我进行的是年统计
var image= ee.ImageCollection("LANDSAT/LT05/C01/T1_SR")
.filterBounds(hh)
.filterDate("1986-1-1","1987-1-1")
.map(rmCloud)
.map(function(image) {
var evi = image.expression(
'2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
'NIR': image.select('B4'),
'RED': image.select('B3'),
'BLUE': image.select('B1')
});
return image.addBands(evi.rename('EVI')).clip(hh);
})
;
print("image",image);
Map.centerObject(hh, 3);
//在这里进行自己影像的选择,这里选择第一张影像,另外,裁剪自己的边界。
var scol_clip1 =image.first().clip(hh);
//其他指数可以参照一下函数
//NDVI
function NDVI(image) {
return image.addBands(
image.normalizedDifference(["B5", "B4"])
.rename("NDVI"));
}
//NDWI
function NDWI(image) {
return image.addBands(
image.normalizedDifference(["B3", "B5"])
.rename("NDWI"));
}
//NDBI
function NDBI(image) {
return image.addBands(
image.normalizedDifference(["B6", "B5"])
.rename("NDBI"));
}
以上部分各指数的计算过程我就不一一解释了,因为指数就是波段运算的结果,自己进行公式表达就行了。
3.数据的归一化处理函数
function normalization(image,region,scale){
var mean_std = image.reduceRegion({
reducer: ee.Reducer.mean()
.combine(ee.Reducer.stdDev(),null, true),
geometry: region,
scale: scale,
maxPixels: 10e9,
// tileScale: 16
});
// use unit scale to normalize the pixel values
var unitScale = ee.ImageCollection.fromImages(
image.bandNames().map(function(name){
name = ee.String(name);
var band = image.select(name);
var mean=ee.Number(mean_std.get(name.cat('_mean')));
var std=ee.Number(mean_std.get(name.cat('_stdDev')));
var max=mean.add(std.multiply(3));
var min=mean.subtract(std.multiply(3));
var band1=ee.Image(min).multiply(band.lt(min)).add(ee.Image(max).multiply(band.gt(max)))
.add(band.multiply(ee.Image(1).subtract(band.lt(min)).subtract(band.gt(max))));
var result_band=band1.subtract(min).divide(max.subtract(min));
return result_band;
})).toBands().rename(image.bandNames());
return unitScale;
}
这一段代码来自Pyrs大神:(2条消息) Google Earth Engine笔记-影像归一化与异常值去除_Pyrs的博客-CSDN博客主要思路是通过计算均值、标准差和在3倍标准差之内的误差来剔除异常值。
3.数据的归一化处理函数
//归一化前的结果
var before_chart=ui.Chart.image.histogram(scol_clip.select(["B4","EVI"]), hh, 1000);
print(before_chart);
//让影像进行归一化函数处理后的结果
var normal_image=normalization(scol_clip,hh,1000)
print(normal_image)
//归一化后的结果
var after_chart=ui.Chart.image.histogram(normal_image.select(["B4","EVI"]), hh, 1000)
print(after_chart)
这里有一点问题,在于=ui.Chart.image.histogram()中1000代表的是像素值:
scale (Number, optional):
The pixel scale used when applying the histogram reducer, in meters.
当你的运行范围超出了最大计算量的时候,选择把自己的像素值调大,可以解决这个问题!
以上是归一化前的统计量,为了和EVI波段明显对比,我使用了一个B4波段作为参照!
这是归一化后的统计量分布图!
4.数据的下载和导出
Export.image.toDrive({
image:normal_image.select("EVI"),
description: '1986_shanxi_EVI_sr',
folder: 'hulunbeier',
scale: 1000,
region:hh
});
Map.addLayer(image, {},'EVI');