PIE-Engine实践篇|巧用map算子提高效率

2023-09-18 18:51来源:西盟科技   阅读量:16778   

扫描二维码分享

首先,地图操作员的角色

地图算子是我们在云计算平台上处理图像时常用的一种算子。它可以对集合中的每个元素进行操作,操作后返回的结果仍然是集合对象。以FeatureCollection调用地图操作符为例,其基本形式如下:

var featureCol = pie。FeatureCollection

var feature col new = feature col . map

var geometry = feature.geometry

var featureNew = pie。特写);

返回功能新;

上面的代码把featureCol中的每个特征都拿出来,然后找到每个特征的几何中心,得到一个新的向量集——feature col new。

二、map运算符与for循环的区别

当然,有些map操作也可以通过传统的for/while循环来实现,但在计算机制上有本质的不同。for循环是一个前端控制变量,顺序执行代码的循环,速度很慢,很少用在PIE-Engine中。另一方面,map在后台服务器上直接作用于集合中的元素进行循环操作,效率非常高,相当于任务的并行执行;但是在地图中一般不再使用打印、地图、导出、缩小等方法。下面比较了在集合中使用map运算符和for循环之间的区别。

对列表中的每个元素进行循环计算。

//将列表中的每个元素加1,并使用map运算符。

var list1 = pie。列表);

var list2 = list1.map

返回馅饼。number . add(1);

);

打印;

输出结果:

//将列表中的每个元素加1,并使用for循环。

var list1 = pie。列表);

var list 2 =;

for(var I = 0;我

list2.push)。添加(1)。getInfo());

打印;

输出结果:

列表集调用map操作符后,可以直接作用于其中的元素,而使用for循环需要增加很多限制才能达到同样的功能。

对FeatureCollection中的每个要素执行循环计算。

利用全国省级行政区划矢量数据计算各省面积,分别使用地图运算符和for循环进行计算。

取FeatureCollection中的每个元素,并使用map运算符计算其面积:

向上滑动阅读

var featureCol = pie。feature collection . load(# 39;NGCC/中国省界# 39;);

var feature col new = feature col . map

var name = feature.get

var geometry = feature.geometry

var area = geometry . area . divide(1000000);

feature = feature.set

feature = feature.set

返回特征;

var result = featurecolnew . reduce columns,(quot名称quot;,quotareaquot));

打印;

map . add layer;

Map.setCenter

代码链接:

地图算子用于获取中国各省的面积

取FeatureCollection中的每个元素,并使用for循环计算其面积:

向上滑动阅读

var featureCol = pie。feature collection . load(# 39;NGCC/中国省界# 39;);

打印

for(I = 0;我

var name = feature col . getat . get(quot;名称quot;);

var geometry = feature col . getat . geometry();

var area = geometry . area . divide(1000000);

打印;

map . add layer;

Map.setCenter

代码链接:

运行结果:

For循环输出各省的面积。

上面的代码使用了map运算符,2秒就可以得到结果,而for循环需要40秒,等待时间长,体现了map运算符的优势。

对ImageCollection中的每个图像进行循环计算。

获取ImageCollection中的每个元素来计算NDVI,并使用map运算符:

向上滑动阅读

var featureCol = pie。feature collection . load(# 39;NGCC/中国省界# 39;);

var Beijing = feature col . filter);

var bj geo = Beijing . getat . geometry();

var vis params =;

map . add layer;

Map.centerObject

var imageCol = pie。图像集合

。过滤日期

。过滤界限;

打印;

var imageColNDVI = imageCol.map

// NDVI计算

var img_Nir = image.select;var img _ Nir = image.select

var img_Red = image.select;var img _ Red = image.select

var img_NDVI = img_Nir.subtract.divide(img_Nir.add).rename(quot;NDVIquot;);var img _ NDVI = img _ NIR . subtract . divide(img _ NIR . add)。重命名(quotNDVIquot);

return image . add bands;

);

打印;

//NDVI绘画风格

var visParamNDVI =

最小值:-0.2,

最大:0.8,

调色板:# 39;CA7A41、CE7E45、DF923D、F1B555、FCD163、99B718、# 39;+

#39;74A901,6A000,529400,3E8601,207401,056201,004C00,# 39;+

#39;023B01,012E01,011D01,011301 # 39;

var imageNDVI = imagecolndvi . select . mosaic()。剪辑(bj geo);

map . add layer;

代码链接:

输出结果:

取ImageCollection中的每个元素计算NDVI,并采用for循环:

向上滑动阅读

var featureCol = pie。feature collection . load(# 39;NGCC/中国省界# 39;);

var Beijing = feature col . filter);

var bj geo = Beijing . getat . geometry();

var vis params = color:quot;ff0000ffquot,fill color:quot;00000000quot;

map . add layer;

Map.centerObject

var imageCol = pie。图像集合

。过滤日期

。过滤界限;

打印;

var new col =;

for(I = 0;我

var image = imageCol.getAt

var img_Nir = image.select;var img _ Nir = image.select

var img_Red = image.select;var img _ Red = image.select

var img_NDVI = img_Nir.subtract.divide(img_Nir.add)var img _ NDVI = img _ NIR . subtract . divide(img _ NIR . add)

。重命名;

image = image . add bands;

new col . push;

var newImageCol=pie。image collection . from images(new col);

打印;

//NDVI绘画风格

var visParamNDVI =

最小值:-0.2,

最大:0.8,

调色板:# 39;CA7A41、CE7E45、DF923D、F1B555、FCD163、99B718、# 39;+

#39;74A901,6A000,529400,3E8601,207401,056201,004C00,# 39;+

#39;023B01,012E01,011D01,011301 # 39;

var imageNDVI = new imagecol . select . mosaic()。剪辑(bj geo);

map . add layer;

代码链接:

上述代码的计算时间与for循环基本相同,但在使用for循环时要重新构造一个数组来存储新的ImageCollections,并且在循环结束后要重新构造一个由这些图像组成的图像集合,这是很复杂的。

因此,在遥感云计算平台中,当涉及到对集合中的各个元素进行操作时,建议使用map运算符,这样既快捷又方便。但是,如上所述,打印、映射、导出和缩小等方法不应在映射运算符中使用。如果需要对集合中的每个元素执行统计操作,可以使用for循环。下面的代码显示了如何使用for循环来计算从北京各个城区提取的建筑面积:

向上滑动阅读

var chn = pie。FeatureCollection

var Beijing = CHN . filter);

var bj geo = Beijing . getat . geometry();

var chn2 = pie。FeatureCollection

var Beijing 2 = CHN 2 . filter);

var bjgeo 2 = Beijing 2 . getat . geometry();

地图.中心对象

var vis params = color:quot;ff0000ffquot,fill color:quot;00000000quot;

map . add layer;

map . add layer;

函数rmCloud

var qa = image.select

var cloudMask = qa.bitwiseAnd(1

返回image.updateMask

var l8 =馅饼。图像集合

。过滤日期

。过滤界限

。选择)

。地图;

//计算中使用的索引

function imgCalculate函数img计算

var green = image.select

var red = image.select

var nir = image.select

var swir1 = image.select

var ndvi =)。divide(nir.add(red))。重命名(quotNDVIquot);

var mndwi = green.subtract

。除)

。重命名;

return image . add bands . add bands(MND wi);

var imgCol = l8.mapvar imgCol = l8.map

。意思是

。剪辑;

Map.addLayer , quot;imgColquot;);Map.addLayer,quotimgColquot);

var ndvi = imgCol.select;var ndvi = imgCol.select

var nonVeg = imgCol.updateMask);var non veg = img col . update mask);

Map.addLayer,quotnonVegquot);

var mndwi = imgCol.select;var Mn DWI = img col . select;

var non veg water = non veg . update mask);

Map.addLayer,quot非淡水quot;);

var non veg water 2 = non veg water . select . gt(0);

map . add layer;

var area image = non veg water 2 . pixel area . multiply(non veg water 2 . gt(0));

var area = areaImage.reduceRegion,bjGeo,30);

打印:quot,馅饼。number(area . get(quot;常量quot;)).除(1000000));

var new features =;

for(var I = 0;我

var temp = non veg water 2 . clip . geometry());

var areaImg = temp . pixel area . multiply(temp . gt(0));

var area = areaImg.reduceRegion,beijing2.getAt(i)。几何(),30);

new features . push . set(quot;areaquot,area . get(quot;常量quot;)));

北京2 =馅饼。FeatureCollection

打印;

var result = Beijing 2 . reduce columns,(quot名称quot;,quotareaquot));

打印;

代码链接:

输出结果:

第三,巧用map算子,提高计算效率。

Map operator在带来便利的同时,也将大量计算转移到后台计算服务。通常我们在图像处理中会计算多个指数,单个指数的计算公式通常会写成函数的形式,便于调用。当多个map算子一起使用时,相当于很多个循环,涉及的计算量也非常大。如何使用map运算符优化计算逻辑,提高计算效率?

以裸地指数BSI、改进的归一化差异水指数MNDWI、增强的裸地指数EBSI和去云后的建筑用地指数NDBI的计算为例,说明如何在规范层面进行优化,以减少计算量,提高计算效率。

方法一,把每个指标的计算分别写成一个函数,过滤图像后用map运算符依次调用:

向上滑动阅读

var chn = pie。FeatureCollection

var Beijing = CHN . filter);

var bj geo = Beijing . getat . geometry();

地图.中心对象

var vis params = color:quot;ff0000ffquot,fill color:quot;00000000quot;

map . add layer;

//去云端

函数rmCloud

var qa = image.select

var cloudMask = qa.bitwiseAnd(1

返回image.updateMask

//裸土指数BSI: -(B05+B02))/+(B05+B02))

功能BSI

var nir = image.select

var swir1 = image.select

var red = image.select

var blue = image.select

var bsi =。减去(nir.add(蓝色)))

. divide . add(NIR . add(blue)));

return image . add bands);

//改进的归一化差异水体指数MNDWI: /(B03+B06)

功能MNDWI

var Mn DWI = image . select . subtract(image . select(quot;B6quot))

. divide . add(image . select(quot;B6quot)))

return image . add bands);

//增强型裸土指数EBSI:/(BSI+MNDWI)

功能EBSI

var mndwi = image.select

var bsi = image.select

var ebsi =)。divide(BSI . add(Mn DWI));

return image . add bands);

//建筑用地指标NDBI: /(B06+B05)

功能NDBI

var ndbi = image . select . subtract(image . select(quot;B5quot))

. divide . add(image . select(quot;B5quot)))

return image . add bands);

//加载Landsat 8影像数据集。

var imgColl8 = pie.ImageCollectionvar imgColl8 = pie。图像集合

。过滤日期

。过滤界限

。选择)

。地图

。地图

。地图

。地图

。地图

。意思是

。剪辑;

打印;

Map.addLayer , quot;imgCol1quot;);Map.addLayer,quotimg col 1 quot;);

Map.addLayer,最小值:-0.2,最大值:0.2,quotBSIquot);

Map.addLayer,最小值:-0.2,最大值:0.2,quotNDBIquot);

Map.addLayer,,quotMNDWIquot);

Map.addLayer,最小值:0,最大值:1,quotEBSIquot);

代码链接:

上面的代码调用map操作符五次,相当于遍历过滤后的图像五次。除了云端运算,每张图片的波段运算后每增加一次计算指标,在反复读写中消耗大量计算能力,输出计算结果需要85秒,完整显示需要135秒。

依次调用多个地图计算每个指数。

方法二,将去云与指数运算封装成一个函数,在对影像进行滤波后,仅用map算子调用一次:

向上滑动阅读

var chn = pie。FeatureCollection

var Beijing = CHN . filter);

var bj geo = Beijing . getat . geometry();

地图.中心对象

var vis params = color:quot;ff0000ffquot,fill color:quot;00000000quot;

map . add layer;

var imgColl8 = pie.ImageCollectionvar imgColl8 = pie。图像集合

。过滤日期

。过滤界限

。选择);

//图像处理功能

function imgCalculate函数img计算

var qa = image.select

var cloudMask = qa.bitwiseAnd(1

image = image.updateMask

var blue = image.select

var green = image.select

var red = image.select

var nir = image.select

var swir1 = image.select

var bsi =。减去(nir.add(蓝色)))

. divide.add(nir.add(蓝色)))

。重命名;

var mndwi = green.subtract

。除)

。重命名;

var ebsi =)。divide(bsi.add(mndwi))

。重命名;

var ndbi = swir1.subtract

。除)

。重命名;

返回image.addBands.addBands(bsi)。添加波段(ebsi)

。addBands

imgColl8 = imgColl8.map.mean()。剪辑(bj geo);

打印;

Map.addLayer , quot;imgCol1quot;);Map.addLayer,quotimg col 1 quot;);

Map.addLayer,最小值:-0.2,最大值:0.2,quotBSIquot);

Map.addLayer,最小值:-0.2,最大值:0.2,quotNDBIquot);

Map.addLayer,,quotMNDWIquot);

Map.addLayer,最小值:0,最大值:1,quotEBSIquot);

代码链接:

将指数计算封装到一个函数中并调用它。

上面的代码只调用一次map操作符,从滤波后的图像中去除云并添加四个指数波段,每个场景图像只需要读写一次,大大节省了计算量,输出结果并完整显示只需要8秒。与方法1相比,计算速度提高了近10倍。

学习了这种思想之后,我们平时写代码的时候注意优化计算过程,可以提高计算效率,减少等待时间。

郑重声明:此文内容为本网站转载企业宣传资讯,目的在于传播更多信息,与本站立场无关。仅供读者参考,并请自行核实相关内容。

返回顶部
返回顶部