2.1 过滤筛选filter
过滤主要分为:空间过滤、时间过滤、属性过滤
下面例子中的ee.Filter.lt(name,value)和ee.ImageCollection().filter过滤是等价的。
过滤是在数据几何的基础上过滤的。
var point = ee.Geometry.Point(117.089, 36.744);
var start= ee.Date('2020-08-01');
var finish = ee.Date('2020-09-01');
// 云量筛选
var img = ee.ImageCollection('LANDSAT/LC08/C01/T1')
.filterBounds(point) //空间过滤filterBounds()
.filterDate(start, finish) //时间过滤filterDate()
// .sort('CLOUD_COVER', True) //云量排序
// .first()
.filter(ee.Filter.lt('CLOUD_COVER', 5)) //云量过滤,ee.Filter.lt()筛选到小于给定值的元数据。返回构造好的过滤器
var vizParams = {bands: ['B5', 'B4', 'B3'], min: 5000, max: 15000, gamma: 1.3};
Map.centerObject(img, 7);
Map.addLayer(img, vizParams, 'Landsat 8 false color');
2.2 数据整合Reducer
数据整合Reducer是在EE中按照时间、空间、波段、矩阵或其他数据结构整合数据的方法。ee.Reducer()这一大类指定了数据整合的方式。Reducer是将数据整合起来的某种简单的统计算法(如最大最小值、平均值等等),或是对数据进行更为复杂的总结(如直方图、线性回归、列表等)。依据:
1.时间:imageCollection.Reducer();
2.空间:image.ReducerReigon();image.reducerNeighborhood();
3.波段:image.reducer();
4.FeatureColection的属性空间:FeatureColection.reducerColumns()或者以"aggregate_"开头的FeatureColection的方法。
example: 实现计算NDVI感兴趣区均值的例子。源于课本
var roi = ee.Geometry.Polygon(
[[[114.62959747314449, 33.357067677774594],
[114.63097076416011, 33.32896028884253],
[114.68315582275386, 33.33125510961763],
[114.68178253173824, 33.359361757948754]]]);
Map.centerObject(roi, 9);
var image = ee.Image("LANDSAT/LC08/C01/T1_TOA/LC08_123037_20180611");
var ndvi = image.normalizedDifference(["B5", "B4"]).rename("NDVI");
var visParam = {
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, visParam, "NDVI");
Map.addLayer(roi, {color: "red"}, "roi");
var mean = ndvi.reduceRegion({
reducer: ee.Reducer.mean(), //reducer均值计算器
geometry: roi, //geometry计算区域
scale: 30 //分辨率选择:30m
}); // 这部分是最重要的
print("reduceRegion value is: ", mean);
上述例子的链接:
https://code.earthengine.google.com/039f13adeedd57a36a1d36334a69598c
**Example:**Reducer实现多时相NDVI数据中值的计算。来源于培训教材的例子
var getNDVI = function(image) {
return image.normalizedDifference(['B5', 'B4']).select(['nd'],['NDVI']);
}
var NDVIs = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filter(ee.Filter.eq('WRS_PATH',122))
.filter(ee.Filter.eq('WRS_ROW',34))
.filterDate('2019-01-01','2020-10-01')
.map(getNDVI)
var reduceNDVI2=NDVIs.reduce(ee.Reducer.median()) //在结果上使用Reducer命令,进行NDVI中值的计算
Map.addLayer(reduceNDVI2,{min:1,max:1,palette:['0000FF','00FF00']},'ndvi2');
上述例子只是进行了简单的介绍,但是,reducer的理解较为复杂。有几十个,接下来具体介绍GEE中常用的各个Reducer的意思,其他的也可以在docs中查询。下面来自于知乎。
命令 | 解释 |
---|---|
ee.Reducer.allNonZero() | 检查输入是否都是非0值,如果都是非0值,则返回1,否则0。 |
ee.Reducer.anyNonZero() | 检测输入是否包含非0值,如果包含非0值,则返回1,否则0 |
ee.Reducer.first() | 返回输入的第一个元素 |
ee.Reducer.firstNonNull() | 返回输入的第一个非null元素 |
ee.Reducer.last() | 返回输入的最后一个元素 |
ee.Reducer.lastNonNull() | 返回输入的最后一个非null元素 |
ee.Reducer.min() | 获取输入的最小值。如果输入是数值列表,获取数值的最小值;如果是影像集合,获取所有匹配波段的每一个像素的最小值;如果是单张影像,获取波段中的像素最小值。 |
ee.Reducer.max() | 获取输入的最大值。如果输入是数值列表,获取数值的最大值;如果是影像集合,获取所有匹配波段的每一个像素的最大值;如果是单张影像,获取波段中的像素最大值。 |
ee.Reducer.minMax() | 获取输入的最小值和最大值,如果输入是数值列表,获取数值的最小值和最大值;如果是影像集合,获取所有匹配波段的每一个像素的最小值和最大值;如果是单张影像,获取波段中的像素最小值和最大值 |
ee.Reducer.mode() | 获取输入的众数 |
ee.Reducer.mean() | 获取输入的均值 |
//1. ee.Reducer.allNonZero()
function allNonZero() {
//ee.Reducer.allNonZero(),
var a = ee.List([1,0,2,3]);
//输出结果为0,因为包含0
print("result1", a.reduce(ee.Reducer.allNonZero()));
var b = ee.List([1,2,3,4]);
//输出结果为1,因为全是非0值
print("result2", b.reduce(ee.Reducer.allNonZero()));
}
allNonZero();
/2.ee.Reducer.anyNonZero()
function anyNonZero() {
//ee.Reducer.anyNonZero()
var a = ee.List([1,0,2,3]);
//因为包含非0值,输出1
print("result1", a.reduce(ee.Reducer.anyNonZero()));
var b = ee.List([0,0]);
//值全为0,输出0
print("result2", b.reduce(ee.Reducer.anyNonZero()));
}
anyNonZero();
//3.ee.Reducer.first()
var roi = /* color: #d63000 */ee.Geometry.Polygon(
[[[116.11220202824006, 38.133561577393166],
[116.37569631837516, 38.1696689233409],
[116.32936651641012, 38.35173534234094],
[116.07083980910647, 38.31789056147068]]]),
l8 = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA");
function generateImage() {
Map.centerObject(roi, 10);
var img = l8.filterDate("2018-6-1", "2018-8-1")
.filterBounds(roi)
.map(ee.Algorithms.Landsat.simpleCloudScore)
.map(function(image){
image = image.updateMask(image.select("cloud").lte(20));
return image;
})
.map(function(image) {
return image.addBands(image.normalizedDifference(["B5", "B4"]).rename("NDVI"));
})
.select("NDVI")
.mosaic()
.clip(roi);
var visParam = {
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(img, visParam, "NDVI");
return img;
}
var img = generateImage();
function first() {
//ee.Reducer.first()
//list
var a = ee.List([1,2,3,4,5]);
//返回列表的第一个元素 1
print("result", a.reduce(ee.Reducer.first()));
//image
var firImg = ee.Image(l8.reduce(ee.Reducer.first()));
//返回集合中每一景影像的波段第一个像素,同时重命名波段名称
print("firImg", firImg);
}
first();
//4.ee.Reducer.firstNonNull()
function firstNonNull() {
//ee.Reducer.firstNonNull()
//list
var a = ee.List([null, 1,2,3,4,5]);
//返回第二个元素 1
print("result", a.reduce(ee.Reducer.firstNonNull()));
}
firstNonNull();
function firstNonNull() {
//ee.Reducer.firstNonNull()
//list
var a = ee.List([null, 1,2,3,4,5]);
//返回第二个元素 1
print("result", a.reduce(ee.Reducer.firstNonNull()));
}
firstNonNull();
//5.ee.Reducer.last()
function last() {
//ee.Reducer.last()
//list
var a = ee.List([1,2,3,4,5]);
//返回最后一个元素 5
print("result", a.reduce(ee.Reducer.last()));
}
last();
//6.ee.Reducer.lastNonNull()
function lastNonNull() {
//ee.Reducer.lastNonNull()
//list
var a = ee.List([0, 1,2,3,4, null]);
//返回倒数第二个元素 4
print("result", a.reduce(ee.Reducer.lastNonNull()));
}
lastNonNull();
其他详细的资料看下面第二个链接,代码都是上述第三个例子为基础:
ee.Reducer()介绍详细参考资料:
https://zhuanlan.zhihu.com/p/45335579
https://zhuanlan.zhihu.com/p/46683686
2.3 循环遍历map
循环遍历是依次对列表或者集合中每一个元素做相同的处理,在其他编程语言中是for或while,同样,gee也可以,但是由于其特殊性,推荐map。和之前的Map映射不一样。
map通常搭配函数一起使用,提取landsat最大ndvi并添加为新波段,请看下例:
var getNDVI = function(image) {
var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
return image.addBands(ndvi); //定义添加ndvi新波段的函数,.rename()是将变量更名
}
// .select(['nd'],['NDVI']) //和.rename()一个意思,是将nd更名为NDVI
var maxNDVI = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filter(ee.Filter.eq('WRS_PATH',122))
.filter(ee.Filter.eq('WRS_ROW',34))
.filterDate('2019-01-01','2020-10-01') //按照路径和block提取的数据集
.map(getNDVI)
.max() //.max()为提取ndvi为最大值的那张影像
print(maxNDVI)
Map.addLayer(maxNDVI.select('NDVI'),{min:-1,max:1,palette:['0000FF','00FF00']},'ndviDiff');
这个代码是map的另一个案例,结合了Reducer():
https://code.earthengine.google.com/9d9b72c002fe16ba406f6fe388b120c1
2.4 ee.Image().mask()
掩膜,使用一个数据度另一个数据进行裁剪,类似于ee.filterBounds():
// This function gets NDVI from Landsat 5 imagery.
var getNDVI= function(image) {
return image.normalizedDifference(['B4', 'B3']);
};
// Load two Landsat 5 images, 20 years apart.
var image1 = ee.Image('LANDSAT/LT05/C01/T1_TOA/LT05_044034_19900604');
var image2 = ee.Image('LANDSAT/LT05/C01/T1_TOA/LT05_044034_20100611');
// Compute NDVI from the scenes.
var ndvi1 = getNDVI(image1);
var ndvi2 = getNDVI(image2);
// Compute the difference in NDVI.
var ndviDifference= ndvi2.subtract(ndvi1);
// Load the land mask from the SRTM DEM.
var landMask= ee.Image('CGIAR/SRTM90_V4').mask(); //准备掩膜数据,dem陆地部分为1,水体为0,用为1的部分掩膜
// Update the NDVI difference mask with the land mask.
var maskedDifference= ndviDifference.updateMask(landMask);//掩膜
// Display the masked result.
var vizParams= {min: -0.5, max: 0.5, palette: ['FF0000', 'FFFFFF', '0000FF']};
Map.setCenter(-122.2531, 37.6295, 9);
Map.addLayer(ndviDifference, vizParams, 'ndviDifference');
Map.addLayer(landMask, vizParams, 'landMask');
Map.addLayer(maskedDifference, vizParams, 'NDVI difference');
//2.另一种掩膜,也就是大于0.1的部分作为mask进行掩膜,结果就是将NDVI大于0.1的显示出来
var mask = maskedDifference.gt(0.1)
var vegtationNDVI = maskedDifference.updateMask(mask)
Map.addLayer(mask,{min:-1,max:1,palette:['0000FF','00FF00']},'mask');
Map.addLayer(vegtationNDVI,{min:-1,max:1,palette:['0000FF','00FF00']},'NDVI');
2.5发布APP
APP是指把EE中编写的代码发布成为可在线运行的网页端应用,其他用户可以直接通过我们发布的链接地址访问、使用APP。具体操作如下:
var center = /* color: #d63000 */ee.Geometry.Point([116.387928, 40.00649]); //定义初始化地图并显示位置;
var zoom = 9; //定义初始化地图及缩放级别;
var leftMap = ui.Map();
//初始化左地图和右地图,并用linker将其联系起来;
leftMap.centerObject(center, zoom);
var rightMap = ui.Map();
rightMap.centerObject(center, zoom);
leftMap.setControlVisibility(false);
rightMap.setControlVisibility(false);
leftMap.setControlVisibility({zoomControl: true});
var linker = new ui.Map.Linker([leftMap, rightMap]);
//定义滑动界面组件,左右布局,中间显示滑动条;
var splitPanel = ui.SplitPanel({
firstPanel: leftMap,
secondPanel: rightMap,
orientation: 'horizontal',
wipe: true
});
//清空原始的地图界面内容
ui.root.clear();
ui.root.add(splitPanel);
//RGB 左地图显示
var landsat = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterDate('2017-01-01', '2018-01-01')
.median();
landsat = landsat.addBands(landsat.normalizedDifference(['B5', 'B4']).rename("NDVI"));
var vis = {bands: ['B4', 'B3', 'B2'], min: 0, max: 3000};
leftMap.addLayer(landsat, vis, "rgb");
//NDVI 右地图显示
var visNDVI = {
min: 0,
max: 1,
palette: 'FFFFFF,CE7E45,DF923D,F1B555,FCD163,99B718,74A901,66A000,529400,' +
'3E8601,207401,056201,004C00,023B01,012E01,011D01,011301'
};
rightMap.addLayer(landsat.select("NDVI"), visNDVI, 'NDVI');
但是我貌似发布不了,不知道为什么,链接:
https://code.earthengine.google.com//1fc5d33fa0121736f7fd71a2ea44501c