ArcGIS 栅格函数在线调用详解

ArcGIS 栅格函数在线调用详解

导读:ArcGIS从10.0版本开始引用镶嵌数据集,并且第一次在影像中加入栅格函数(raster functions),使得影像的呈现和信息提取与GIS紧密的结合起来,简单的影像功能都可以在ArcGIS中实现(当然了,如果是专业的影像处理,还是建议在ENVI这类专业的遥感软件下进行)。ArcGIS软件向来注重一体化,因此,在桌面软件ArcMap中实现的功能都会逐渐迁移到服务器中。本文着重从桌面端功能介绍转移到服务器端及Web开发,旨在说明ArcGIS软件的栅格函数技术路线。 BY 李远祥

ArcMap中的栅格函数调用

在ArcMap中可以对任何影像格式,包括栅格数据集、栅格目录和镶嵌数据集。在菜单栏--【窗口】--【影像分析】中可以调出影像分析面板,如下图所示

影像分析面板可以实现常见的图像处理功能,如果是熟悉Photoshop等软件,那就会发现一些非常数据的名词,如对比度、亮度、透明度、锐化、平滑、交互式拉伸等。但其最大的特色是栅格函数,随着每个版本的更新,栅格函数会逐渐增加。

在【影像分析】面板中选中影像数据之后,可以找到栅格函数的入口,包含了非常多的处理函数,如下图所示

这些函数不同于ToolBox工具,Toolbox工具的特点就是每处理完一次都会生成一个新的栅格数据作为结果,整个过程会进行影像计算、重采样等,并占单独占用存储,一般处理时间比较长。栅格函数的性质是动态处理,函数与栅格数据的关系是引用关系,有点类似于PS里面的滤镜。在引用函数调用的时候不会生成新的数据,ArcMap会根据函数的设定动态对影像进行渲染,而且性能相当高。同时函数也是可以进行相互叠加的。

例如下图针对Landsat数据进行波段提取,提取第四波段。可以在栅格函数中直接使用【波段提取函数】,如下图

将波段组合设置为4,结果即马上生成一个动态的渲染图层,至显示第四波段数据,如下图所示

如果是DEM数据,栅格函数还支持如坡度、坡向、山体阴影等操作。如下图就是对DEM进行的山体阴影的操作。

imageserver 中的影像

将影像发布为影像服务,同样也支持栅格函数。影像服务发布需要ArcGIS Server 的imageserver 授权。栅格数据集、栅格目录和镶嵌数据集都支持直接发布为影像服务。在ArcMap的目录中右键选择影像,可以将其发布成影像服务,如下图:

影像服务的发布过程与一般的地图服务Mapservice的向导类似,不过在其服务设置方面有自己的特点,如下图所示:

通过rest地址访问已发布的影像服务,可以看到其影像服务的功能。其中一项就是栅格函数

影像服务的调用与传统的mapservice类似,不过采用的是 ArcGISImageServiceLayer 接口。调用代码如下

        var map;
        require([
                    "esri/map",
                    "esri/layers/ArcGISImageServiceLayer",
                    "esri/layers/ImageServiceParameters",
                    "dojo/domReady!"],
                function(Map,ArcGISImageServiceLayer,ImageServiceParameters) {
                    map = new Map("mapDiv");                                                
                    var imgParams = new ImageServiceParameters();
                    imgParams.onData = 0;
                    
                    var layerUrl = "http://localhost:6080/arcgis/rest/services/LC441821/ImageServer";
                    var imageServiceLayer = new ArcGISImageServiceLayer(layerUrl,{
                        imageServiceParameters:imgParams,
                        opacity:0.75
                    });
                    map.addLayer(imageServiceLayer);
                    map.centerAt([113.34, 23.51]);
                });

这里除了使用接口加载影像服务之外,还使用了ImageServiceParameters 接口去设置影像服务的参数。例如上述代码使用的 imgParams.onData = 0; 就是设置影像的onData 。

ImageServiceParameters 是非常重要的影像服务接口,它涉及到影像服务的多种设置,栅格函数影像函数的设置最终也会落在该接口对应的参数中。

ArcGIS JavaScript API 使用栅格函数

imageservice 支持直接在前端使用栅格函数来重新渲染影像服务。ArcGIS JavaScript API 中集成了栅格函数的调用接口--RasterFunction 。 RasterFunction 不能单独使用,需要配合ArcGISImageServiceLayer和ImageServiceParameters 接口。

目前前端能支持的栅格函数类型不是特别多,从官方的在线帮助可以看到其具体能支持的类型和数量。支持的栅格函数可以访问此处 。下图是前端支持的栅格函数

ArcGIS在10.0版本之后每一个版本都加入了新的栅格函数,如上图显示的信息。所以在前端调用栅格函数之前,先要查询一下当前的ArcGIS Server 版本是否支持对应的栅格函数。

笔者建议在使用 JavaScript API 调用栅格函数之前,先在ArcMap中走通其流程,并针对结果进行。例如前面所说的提取影像的第四波段。

下面例子是使用JS API 调用波段提取函数。

        var map;
        require([
                    "esri/map",
                    "esri/layers/ArcGISImageServiceLayer",
                    "esri/layers/ImageServiceParameters",
                    "dojo/domReady!"],
                function(Map,ArcGISImageServiceLayer,ImageServiceParameters) {
                    map = new Map("mapDiv");                    
                    var rasterFunction = new esri.layers.RasterFunction();
                    rasterFunction.functionName = "ExtractBand";
                    
                    var functionArguments = {};
                    functionArguments.BandIDs= [4]                                       
                    rasterFunction.functionArguments = functionArguments;                   
                    rasterFunction.variableName = "Raster";    
                    
                    var imgParams = new ImageServiceParameters();
                    imgParams.onData = 0;
                    imgParams.renderingRule=rasterFunction;
                    
                    var layerUrl = "http://localhost:6080/arcgis/rest/services/LC441821/ImageServer";
                    var imageServiceLayer = new ArcGISImageServiceLayer(layerUrl,{
                        imageServiceParameters:imgParams,
                        opacity:0.75
                    });
                    map.addLayer(imageServiceLayer);
                    map.centerAt([113.34, 23.51]);
                });

效果如下图所示

从代码中可以看出,关键部分是使用了RasterFunction接口,要调用什么样的函数,需要在 functionName 中设置其栅格函数名称。栅格函数的参数每个都不一样,这个就必须查看在线帮助了。例如波段提取函数名称为 ExtractBand ,在在线帮助中点击该名称,则跳转到它的参数说明和调用样例。如下图所示

通过对应的参数来定义栅格函数的参数 functionArguments ,其中关键字部分是需要对应帮助说明的每一个参数名称。

例如将该LandSat影像服务设置为假彩色显示,可以通过提取波段函数进行参数的修改,如下图所示,将波段组合修改之后

在页面端可以直接调用出来,如下图

通过上述例子可以看出,栅格函数的使用是极其简单的。Esri 官方帮助提供了非常详细的接口说明。不过碍于都是英文,所以,笔者建议是先将ArcMap切换为英文版,在英文版上进行前期的函数调用,查看结果。英文版的ArcMap中的栅格函数名称是跟JS API 中的名称是完全对应的。

栅格函数模版

前面的内容旨在说明栅格函数的桌面使用和Web端调用。通过ArcMap的操作,很多人可能已经看到,栅格函数是可以叠加使用的。这种叠加在前端API可以照搬。不过如果叠加的函数比较多,就需要编写比较长的代码。

还有一种情况,ImageServer 中提供的栅格函数前端接口没有ArcMap的那么多,如果需要调用一些桌面端具备的接口,而目前前端还没提供的栅格函数,那就需要在服务器端配置栅格函数模版。

可以看看Esri官方帮助上调用的自定义的栅格函数,其渲染效果相当不错。这种效果在前端API是无法实现的。

栅格函数模版需要在ArcMap中进行设计,其设计到栅格函数的调用和结果的渲染。

先说说前端渲染,目前ArcGIS JavaScript API 能支持的前端渲染是colorMap方式,就是类似栅格数据分类渲染,其构建方式如下

 [[0,175,240,233],[3,175,240,222]]

这种方式构建为数组,第一个数组值是栅格象元值,后面三个数值分别为RGB值。定义比较麻烦,需要对所用的象元值都给顶一个RGB值才能实现前端渲染。例如下面构建一个非常庞大的 colorMap 。

var colorMap = [[0,175,240,233],[3,175,240,222],[7,177,242,212],
          [11,177,242,198],[15,176,245,183],[19,185,247,178],[23,200,247,178],
          [27,216,250,177],[31,232,252,179],[35,248,252,179],[39,238,245,162],
          [43,208,232,135],[47,172,217,111],[51,136,204,88],[55,97,189,66],
          [59,58,176,48],[63,32,161,43],[67,18,148,50],[71,5,133,58],[75,30,130,62],
          [79,62,138,59],[83,88,145,55],[87,112,153,50],[91,136,158,46],[95,162,166,41],
          [99,186,171,34],[103,212,178,25],[107,237,181,14],[111,247,174,2],
          [115,232,144,2],[119,219,118,2],[123,204,93,2],[127,191,71,2],[131,176,51,2],
          [135,163,34,2],[139,148,21,1],[143,135,8,1],[147,120,5,1],[151,117,14,2],[155,117,22,5],
          [159,115,26,6],[163,112,31,7],[167,112,36,8],[171,110,37,9],[175,107,41,11],
          [179,107,45,12],[183,105,48,14],[187,115,61,28],[191,122,72,40],[155,117,22,5],
          [159,115,26,6],[163,112,31,7],[167,112,36,8],[171,110,37,9],
          [175,107,41,11],[179,107,45,12],[183,105,48,14],[187,115,61,28],[191,122,72,40],
          [155,117,22,5],[159,115,26,6],[163,112,31,7],[167,112,36,8],[171,110,37,9],
          [175,107,41,11],[179,107,45,12],[183,105,48,14],[187,115,61,28],[191,122,72,40],
          [195,133,86,57],[199,140,99,73],[203,148,111,90],[207,153,125,109],
          [213,163,148,139],[217,168,163,160],[223,179,179,179],[227,189,189,189],
          [231,196,196,196],[235,207,204,207],[239,217,215,217],[243,224,222,224],
          [247,235,232,235],[251,245,242,245],[255,255,252,255]];                

在栅格函数设置的时候,可以指定渲染方式,例如

functionArguments.Colormap = colorMap;

这种方式构建工作量巨大,而且没有任何的界面设计器可用。目前还没有前端接口支持拉伸方式渲染,例如桌面端的【渲染地貌函数】采用的色带配置。

这些都需要在服务器端来栅格函数模版。

首选需要在ArcMap中调用【栅格函数模版编辑器】对栅格函数进行配置。在ArcMap菜单栏【窗口】--【自定义】面板中,选择【命令】标签,输入关键字【栅格】,找到【栅格函数模版编辑器】,将其拖动到菜单的工具条任意位置即可使用

从图上可以看到,其界面与【影像】面板中调用的栅格函数的方式非常类似。但它有自己非常独特的地方,多了一个【文件】菜单,可以将设计好的影像分析流程保存下来。如下图所示

笔者做了一个例子,使用DEM数据进行地形渲染。【渲染地貌函数】并不在前端栅格函数的支持范围,其显示的渲染效果是拉伸方式,前端api同样不支持。这个例子很好的反映出服务器中栅格函数模版的重要性。

针对dem数据在【栅格函数模版编辑器】中使用【渲染地貌函数】,并且设计好结果的渲染方式。

设置好后,在【栅格函数模版编辑器】的【文件】菜单中【另存为】将其保存在rft.xml 文件。例如,笔者这里将配置好的模版另存名称为 customfun.rft.xml

此处一定要使用英文名称。因为该模版一旦被导入到imageservice中,其调用名称与文件名称对应。中文名称在调用的时候rest路径会出现一些特殊的符号,导致浏览器请求失败。所以一定要使用英文。

配置栅格函数模版可以在两种情况下进行。第一种是在影像服务发布的时候进行导入,在服务编辑器的【函数】项中设置,如下图所示,点击【管理】,在管理面板中加入一个或者多个栅格函数模版。

注意:笔者这里使用的模版存放在计算机桌面中,可以通过截图看清楚。在影像服务发布的时候指定栅格函数模版,无论栅格函数模版文件放在什么目录下,都能识别,因为arcgis server 最终会将这个模版文件拷贝到服务器能访问的目录中。

点击【确定】并发布影像服务,栅格函数模版会随着服务发布注册到对应的服务目录中。下图是从服务的属性中重新查看其模版情况,可以看到这个模版已经自动被拷贝到arcgisserver注册的目录中

另一种情况是向已经存在的影像服务注册栅格函数模版,这稍微复杂一点,要先将模版文件拷贝到arcgis server 已注册的文件目录下,不然imageserver 无法访问到对应的路径,导致模版读取失败 ,如下图

然后停止对应的影像服务,在服务属性对应的【函数】项目导入模版文件。导入后重启对应的影像服务即可。

在浏览器中通过rest访问对应的影像服务,点击 rasterFunctionInfos 项,可以查看到对应的栅格函数模板的内容

从图上可以看出,影像服务上多了一个以栅格函数模版文件名为命名的自定义函数。这个函数名相当重要,在ArcGIS JavaScript API 的调用中需要使用到。

自定义栅格函数的调用与一般的调用方式没有任何不一样的地方,只需要在rasterFunction.functionName修改函数名称即可。下面是调用自定义函数的代码例子

        var map;
        require([
                    "esri/map",
                    "esri/layers/ArcGISImageServiceLayer",
                    "esri/layers/ImageServiceParameters",
                    "dojo/domReady!"],
                function(Map,ArcGISImageServiceLayer,ImageServiceParameters) {
                    map = new Map("mapDiv");    
                    var rasterFunction = new esri.layers.RasterFunction();
                    rasterFunction.functionName = "customfun";//自定义栅格函数                    
                    rasterFunction.variableName = "Raster";                    
                    var imgParams = new ImageServiceParameters();
                    imgParams.onData = 0;
                    imgParams.renderingRule=rasterFunction;
                    
                    var layerUrl = "http://localhost:6080/arcgis/rest/services/dem/ImageServer";
                    var imageServiceLayer = new ArcGISImageServiceLayer(layerUrl,{
                        imageServiceParameters:imgParams,
                        opacity:0.75
                    });
                    map.addLayer(imageServiceLayer);
                    //map.centerAt([113.34, 23.51]);
                });

具体的效果如下图所示

利用栅格函数模版的方式可以将很多常用的栅格表达方式注册到影像服务中,非常方便快速切换影像的显示方式,而且栅格函数模版是可以复用的。

总结

栅格函数虽然在ArcGIS10.0之后的版本才提出来,并在每一个ArcGIS版本中逐步完善和增加功能。从技术路线上看,栅格函数模版的方式依然是主流的调用方式(尽管这种方式很早就在imageserver 中使用),但前端调用的接口也越来越完善,Esri也在进一步开放其前端功能。在当前影像数据获取越来越便捷和廉价的情况下,影像的使用不仅仅是停留在浏览阶段,分析功能和多种表达方式也是越来越重要了。

更多的GIS主流和非主流技术,可以持续关注CSDN的GIS制图乐园,以及微信公众号【GIS制图乐园】。BY 李远祥

你可能感兴趣的:(javascript,arcgis,函数,栅格,gis)