GEE学习笔记 二十七:零碎知识
详细信息
今天记录一下最近工作中遇到的一些问题。
1.remap函数:生成新的图像包含一个波段(remapped),同时可以替换所筛选的数据,原先的图像不会被修改。
Maps from input values to output values, represented by two parallel lists. Any input values not included in the input list are either set to defaultValue if it is given, or masked if it isn't. Note that inputs containing floating point values might sometimes fail to match due to floating point precision errors.
/**
将wuming这张图片中是0,...,9的数据的位置替换数据为100,…,109,同时生成一个
新的图像,这张图像只包含被替换的元素,这张新的图像只有一个波段remapped,原
始图像不会被修改。
**/
var image = wuming.remap([0,1,2,3,4,5,6,7,8,9],
[100,101,102,103,104,105,106,107,108,109]);
Map.centerObject(image, 8);
Map.addLayer(wuming.updateMask(wuming.eq(27)), {palette:"00ff00"}, "mask");
Map.addLayer(image, {palette:"ff0000"}, "wuming");
2.getInfo函数:获取数据真实内容,参数可以不传(同步方式执行)或者参数传入回调函数(异步方式执行)。同步方式执行会直接锁定整个GEE平台以及其它执行代码,直到这个getInfo函数执行完毕,这种方式最大缺点就是数据相关代码都是在客户端直接执行,非常容易造成客户端假死现象。GEE官方对于这个方法适用建议是要非常谨慎,能不用尽量不用,逼不得已最好使用异步方式调用这个方法。
不推荐的同步方式
//synchronization
var a = ee.List([1,2,3,4]);
var b = a.getInfo();
var len = b.length;
for (var i=0; i<len; i++) {
print(b[i]);
}
print(a.toString());
推荐的异步方式
//asynchronization
var a = ee.List([1,2,3,4]);
a.getInfo(function(value) {
var len = value.length;
for (var i=0; i<len; i++) {
print(value[i]);
}
});
print(a.toString());
3.关于同步以及异步问题在GEE中可以理解为客户端执行和服务器端执行,关于这个问题问题官方的文档中有详细解释参考文档,这里我简单说一下我个人对此的理解。
刚开始接触GEE时候对GEE讲解的客户端(也就是你运行GEE平台的浏览器)、服务端(GEE的后台)完全非常纳闷,当使用一段时间后就有点明白了。简单点讲比如你要声明一个参数字符串,如果你使用的是普通的JavaScript语法声明,那么这个变量可以直接在客户端执行,就是客户端类型;而如果你想要将这个字符串放倒GEE服务器执行,则需要使用 ee.String(xxx) 声明的对象,然后客户端传给服务器执行。
为什么要这么做?两个字原因效率,服务器端可以异步并发执行相关代码,如果在客户端执行那么会出现程序阻塞客户端假死等不必要的麻烦。下面通过文档中展示的例子详细说一下服务端和客户端执行代码的区别。
文档例子解释:
var str1 = "this is normal javascript str";
//输出字符串类型是string
print(typeof str1);
var str2 = ee.String("this is gee string object");
//输出字符串类型是object
print(typeof str2);
//需要显示ee.String对象内容
print(str2);
//客户端对象也就是普通的JavaScript对象可以直接使用普通JavaScript方法,而服务端对象只能使用GEE内部封装的方法。
print("normal js string length: " + str1.length);
print("gee string object length method: ", str2.length());
//将ee.String对象变为普通的string对象,这种方式非常不推荐只有在逼不得已情况下使用
var str3 = str2.getInfo();
print(typeof str3);
print("str3 length: " + str3.length);
//循环,普通方式使用for客户端执行,gee方式使用map服务器端执行
var arr11 = [11,12,13];
var arr12 = [];
for (var i = 0; i<arr11.length; i++) {
arr12.push(arr11[i] + 1);
}
print("arr11+1: ", arr12);
var arr21 = ee.List([15,16,17]);
var arr22 = arr21.map(function(value) {
return ee.Number(value).add(1);
});
print("arr21+1: ", arr22);
输出结果:
这里只是展示了string、list对象,其实还有number、dict等都是存在这类区别,在实际使用中我们最好都使用服务器端方式。下面一个是实际使用的例子:
//获取影像列表id例子
var s2 = ee.ImageCollection("COPERNICUS/S2");
var roi = ee.Geometry.Point([116.3671875, 36.4566360115962]);
var s2Imgs = s2.filterDate("2017-11-1", "2017-12-1")
.filterBounds(roi);
//客户端形式,容易造成客户端奔溃
var colList = s2Imgs.toList(100);
var n = colList.size().getInfo();
for (var i = 0; i < n; i++) {
var img = ee.Image(colList.get(i));
var id = img.id();
print("client select images ids is:", id);
}
//推荐方式
var computedIds = s2Imgs.reduceColumns(ee.Reducer.toList(), ['system:index'])
.get('list');
computedIds.evaluate(function(ids) {
print("server select images ids is: ", ee.List(ids));
});
输出结果:
4.GEE的scale决定于输出的影像,而不是输入的影像