PIE-Engine实践 | NDVI、矢量面积批量计算...巧用map算子提高效率
PIE-Engine 遥感云计算平台上集成了海量遥感数据、强大的算力和丰富的算子,使得大规模尺度长时间序列的遥感数据分析可以在线快速完成,其中一大利器便是map算子。本期我们来详细介绍map算子的作用,它和传统for循环的区别,以及如何巧用map算子优化代码,提高计算效率。
一、 map算子的作用
map算子是我们在云计算平台上处理影像时常用的算子,可以对集合(List、FeatureCollection、ImageCollection)中的每一个元素进行操作,操作完成返回的结果仍是一个集合对象。以FeatureCollection调用map算子为例,其基本形式如下:
var featureCol = pie.FeatureCollection('NGCC/CHINA_PROVINCE_BOUNDARY');
var featureColNew = featureCol.map(function (feature) {
var geometry = feature.geometry();
var featureNew = pie.Feature(geometry.centroid());
return featureNew;
})
上述代码取出featureCol 中的每一个feature,然后求取各feature的几何中心,得到一个新的矢量集合-featureColNew。
二、map算子和for循环的区别
当然,有些map操作用传统的for/while循环也可以实现,但二者在计算机制上有本质区别,for循环是在前端控制变量的循环,且是顺序执行代码,效率比较慢,一般在PIE-Engine里很少用。而map则是在后台服务器上直接作用于集合中的元素进行循环操作,执行效率很快,相当于“并行执行任务”, 但在map里一般不再用 print、Map、Export 以及Reducer等方法。下面分别对比在集合中使用map算子和for循环的不同之处。
针对List中的每个元素进行循环计算
//对List中的每个元素加1,采用map算子
var list1 = pie.List([1,2,3,2]);
var list2 = list1.map(function (value) {
return pie.Number(value).add(1);
});
print("list2",list2);
输出结果:
//对List中的每个元素加1,采用for循环
var list1 = pie.List([1,2,3,2]);
var list2 = [];
for(var i = 0;i<list1.length().getinfo();i++){< span="">
list2.push(pie.Number(list1.get(i)).add(1).getInfo());
}
print("list2",list2);
输出结果:
List集合调用map算子后便可直接作用于其中的元素,而采用for循环则还需要增加诸多限制,才能实现相同的功能。
针对FeatureCollection中的每个Feature进行循环计算
利用中国省级行政区划矢量数据计算每个省的面积,分别采用map算子和for循环进行计算。
(1)取FeatureCollection中的每个元素并计算其面积,采用map算子:
代码链接:
https://engine.piesat.cn/engine-share/shareCode.html?id=cbe5f4f5efca4b5faa8344b0ab325c04
▲采用map算子获取中国各省的面积
(2)取FeatureCollection中的每个元素并计算其面积,采用for循环:
代码链接:
https://engine.piesat.cn/engine-share/shareCode.html?id=4198d136975841269e367aec1ae47e70
运行结果:
▲for循环输出各省面积
上述代码采用map算子,2秒即可出结果,而for循环则需要40秒,等待时间较长,从而体现map算子的优势。
针对ImageCollection中的每个Image进行循环计算
(1)取ImageCollection中的每个元素计算NDVI,采用map算子:
代码链接:
https://engine.piesat.cn/engine-share/shareCode.html?id=4ec895ce6e3b411daab877713ca81f45
输出结果:
(2)取ImageCollection中的每个元素计算NDVI,采用for循环:
代码链接:
https://engine.piesat.cn/engine-share/shareCode.html?id=ef81bdf97c8d45809c3101f5f8dee4c4
上述代码采用map算子和for循环的计算时间基本相同, 但在使用for循环时要重新构造一个存放新的image集合的数组,并在循环结束后重新构造一个由这些image组成的ImageCollection,在步骤上较为复杂。
因此,在遥感云计算平台中,涉及到对集合中的每个元素进行操作时,推荐使用map算子,快速且便利。但前述提到,在map算子中不宜再用 print、Map、Export 以及Reducer等方法,如果需要对集合中的每个元素进行统计操作,则可用for循环代替,以下代码展示了使用for循环统计北京各城区提取的建筑区面积:
代码链接:
https://engine.piesat.cn/engine-share/shareCode.html?id=bf885222bf584f33aaa96c2a0093c03d
输出结果:
三、巧用map算子,提高计算效率
map算子带来便利的同时,也将大量的计算转移给了后台计算服务。通常我们在影像处理时会计算多个指数,单个指数的计算公式通常会写成函数的形式方便调用。多个map算子共同使用时,相当于多次循环,所涉及到的运算量也很大,怎样使用map算子才能优化计算逻辑,提高计算效率呢?
下面以去云后计算裸土指数BSI、改进的归一化差异水体指数MNDWI、增强型的裸土指数EBSI、建筑用地指数NDBI等4个指数的计算为例,来说明如何在代码级别进行优化来减少计算量从而提高计算效率。
方法1,将每个指数的计算单独写成函数,在筛选完影像后依次用map算子调用:
代码链接:
https://engine.piesat.cn/engine-share/shareCode.html?id=402cadc45985400c8650620b9d93bad9
上述代码共调用了5次map算子,相当于对筛选后的影像进行了5次遍历,除去云操作外,每一次都是对每景影像进行波段运算完后添加计算后的指数,将大量的算力消耗在了重复读取和写入上,输出计算结果用时85秒,完整显示用时135秒。
▲依次调用多个map计算每个指数
方法2,将去云及指数运算封装成一个函数,在筛选完影像后仅用map算子调用一次:
代码链接:
https://engine.piesat.cn/engine-share/shareCode.html?id=ce08fdb1cca147acb6ae6da7629fb49f
▲将指数计算封装到一个函数中调用
上述代码仅调用了1次map算子,对筛选后的影像进行了去云操作以及4个指数波段的添加,仅需对每景影像读取写入一次,大大节省了算力,只用8秒即可输出结果并完整显示,相比于方法1,计算速度提升近10倍。
学会了这种思路后,平常我们在编写代码时,注意将计算过程优化,就可以提高计算效率,减少等待时间。
【PIE-Engine注册地址】
https://engine.piesat.cn
扫描二维码即刻体验
新用户首次注册送惊喜大礼包
我们欢迎不同行业、不同背景、不同使用习惯的你,成为我们的用户。
如果你对于这款产品有着不同的看法、建议,以及在使用过程中遇到问题,除了查看在线帮助文档和教程外,还可以通过本文留言区或以下方式联系我们:
【联系电话】400-890-0662
【QQ交流群】604179645
【联系邮箱】engine-support@piesat.cn