2023-09-18 18:51:22 来源:西盟科技 阅读量:11688
首先,地图操作员的角色
地图算子是我们在云计算平台上处理图像时常用的一种算子。它可以对集合中的每个元素进行操作,操作后返回的结果仍然是集合对象。以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倍。
学习了这种思想之后,我们平时写代码的时候注意优化计算过程,可以提高计算效率,减少等待时间。