LearningENVI&IDL分享 http://blog.sciencenet.cn/u/dongyanqing Learning ENVI&IDL

博文

ENVI/IDL与ArcGIS Engine一体化开发的实现

已有 8254 次阅读 2011-6-16 13:41 |系统分类:科研笔记| ENVI, ArcGISEngine, 遥感与GIS一体化, COM_IDL_CONNECT

ENVI/IDLArcGIS Engine一体化开发的实现

 

ENVI (The Environment for Visualizing Images)IDL(Interactive Data Language)是美国ITT VIS公司的旗舰产品,是由遥感领域的科学家采用IDL开发的一套功能强大的遥感图像处理软件。其软件处理技术覆盖了图像数据的输入/输出、定标、几何校正、正射校正、图像融合、镶嵌、裁剪、图像增强、图像解译、图像分类、基于知识的决策树分类、面向对象图像分类、动态监测、矢量处理、DEM提取及地形分析、雷达数据处理、制图、三维场景构建、与GIS的整合,提供了专业可靠的波谱分析工具和高光谱分析工具。ENVI软件几乎可支持所有的UNIX系统,Mac OS XLinux,以及PC机的Windows XP/ Vista/7/Server2008等操作系统。

ENVI具有丰富的函数接口API,完整的示例代码帮助文档。ArcGIS Engine是一套完备的嵌入式GIS 组件库和工具库,即是一个用于开发新应用程序的二次开发功能组件包。开发者可以选择集成开发环境来建立 ArcGIS Engine 应用程序,而同时开发环境又可以集成ENVI/IDL的功能,这样使得开发一个遥感与GIS一体化的程序变得非常的容易。下面以ArcGIS Engine10.0ENVI4.8为例,开发一个一体化的示例程序。

1.     新建项目

启动Visual Studio2008,项目类型选择Visual C#-ArcGIS-Extending ArcObjects,模版选择MapControl Application,解决方案设置为ArcGISEngineUsingENVI(图1.1)。

1.1 新建项目

2.     添加引用

在解决方案的“引用”上单击右键,弹出菜单中选择[添加引用](图2.1),在添加引用界面中,选择COM界面列表中的COM_IDL_connectLib1.0 Type Library(图2.2),如果安装了多个IDL版本可能会存在多个同名的组件。

2.1 项目添加引用

2.2 选择COM_IDL_CONNECT组件

同样方式添加“ESRI.ArcGIS.DataSourceRaster”和“ESRI.ArcGIS.Geodatabase”组件(图2.3)。

2.3 添加相关引用

3.     代码编写 1) C#代码

在解决方案的MapForm.cs中,最上面引用部分,添加引用代码。

//添加自定义引用

using ESRI.ArcGIS.DataSourcesRaster;

using ESRI.ArcGIS.Geodatabase;

添加新菜单[栅格预处理]-[重采样](图3.1),双击[重采样]编写代码。

private void enviToolStripMenuItem_Click(object sender, EventArgs e)

  {

     //初始化ENVI

     COM_IDL_connectLib.COM_IDL_connectClass oComIDL = new COM_IDL_connectLib.COM_IDL_connectClass();

     oComIDL.CreateObject(0, 0, 0);

     //文件打开

     OpenFileDialog pOpenFile = new OpenFileDialog();

     pOpenFile.Title="打开栅格文件";

     //文件选择

     if (pOpenFile.ShowDialog() == DialogResult.OK)

     //打开显示栅格文件

     OpenRaster(pOpenFile.FileName);

     //调用ENVI进行栅格放大*2处理示例

     SaveFileDialog pSaveFile = new SaveFileDialog();

     pSaveFile.Title = "输出放大后影像";

     if (pSaveFile.ShowDialog() == DialogResult.OK)

         {

         //执行重采样

         oComIDL.ExecuteString(".compile '" + System.IO.Directory.GetCurrentDirectory() + @"object_envi_resize__define.pro'");

         oComIDL.ExecuteString(@"s = obj_new('object_envi_resize','"+pOpenFile.FileName+"','"+pSaveFile.FileName+"')");

         oComIDL.ExecuteString("s.EXECUTERESIZE,2,2,0");

         oComIDL.ExecuteString("Obj_destroy,s");

         //加载放大后影像

         OpenRaster(pSaveFile.FileName);

      }

   }

}

3.1 添加重采样功能菜单

继续编写该按钮功能中调用的OpenRaster函数。

//定义栅格打开函数

  private void OpenRaster(string rasterFileName)

  {

      //文件名处理

      string ws = System.IO.Path.GetDirectoryName(rasterFileName);

      string fbs = System.IO.Path.GetFileName(rasterFileName);

      //创建工作空间

      IWorkspaceFactory pWork = new RasterWorkspaceFactoryClass();

      //打开工作空间路径,工作空间的参数是目录,不是具体的文件名

      IRasterWorkspace pRasterWS = (IRasterWorkspace)pWork.OpenFromFile(ws, 0);

      //打开工作空间下的文件,

      IRasterDataset pRasterDataset = pRasterWS.OpenRasterDataset(fbs);

      IRasterLayer pRasterLayer = new RasterLayerClass();

      pRasterLayer.CreateFromDataset(pRasterDataset);

      //添加到图层控制中

      m_mapControl.Map.AddLayer(pRasterLayer as ILayer);

}

2) IDL代码

IDL的功能代码以对象类的方式调用了重采样功能,其中ENVI的初始化和重采样分别是类的两个方法。

;重采样执行功能

;输入放缩比例和采样方法

PRO Object_ENVI_Resize::EXECUTEResize,$

    xfactor, yfactor,method

  COMPILE_OPT idl2, hidden 

  ;打开文件

  ENVI_OPEN_FILE, self.INFILENAME, R_FID=fid

  IF (fid EQ -1) THEN RETURN

  ;查询文件基本信息

  ENVI_FILE_QUERY, fid, dims=dims, nb=nb

  pos  = LINDGEN(nb)

  ;重采样处理

  ENVI_DOIT, 'resize_doit', $

    fid=fid, pos=pos, dims=dims, $

    interp=1, rfact=1./[XFACTOR,YFACTOR], $

    method = METHOD,$

    out_name=self.OUTFILENAME   

END

;对象的析构函数

PRO Object_ENVI_Resize::CLEANUP

  COMPILE_OPT idl2, hidden

  ;关闭ENVI二次开发模式

  ;需要注意,COM组件调用该功能的时候,必须设置如下参数:

  ; ENVI主菜单的File-Preference-Miscellaneous

  ; 设置 Exit IDL on Exit from ENVI'NO'

  ENVI_BATCH_EXIT

END

;ENVI初始化方法

FUNCTION Object_ENVI_Resize::initEnvi

  CATCH, error_status

  IF Error_status NE 0 THEN BEGIN

    RETURN,-1

    CATCH, /CANCEL

  ENDIF

  ;ENVI二次开发模式初始化

  ENVI,/Restore_Base_Save_Files

  ENVI_BATCH_INIT

  RETURN,1 

END

;对象初始化函数

;包含两个参数:输入和输出文件名。

FUNCTION Object_ENVI_Resize::INIT,$

    inFileName ,outFileName

  COMPILE_OPT idl2

  ;文件名参数

  self.INFILENAME = inFileName

  self.OUTFILENAME = outFileName

  ;初始化ENVI

  INITFALG = self->INITENVI()

  RETURN, INITFALG 

END

;类定义

PRO OBJECT_ENVI_RESIZE__DEFINE

  ;类定义结构体

  void = {Object_ENVI_Resize, $

    inFileName : '', $

    outFileName : '' $

    }

END

4.     运行项目

F5对解决方案进行调试运行,点击菜单[栅格预处理]-[重采样],先后选择待处理栅格文件和定义采用后输出文件名,程序调用ENVI重采样函数进行重采样处理(图4.1),并将处理前后栅格文件显示在左侧图层列表中(图4.2)。

4.1 AE中调用ENVI的重采样功能

4.2 重采样前后对比

5.     组件方法与参数传递 1) 概述

COM_IDL_CONNECT组件提供的方法见下表。

方法名称

功能描述

Abort

中断运行中当前的IDL某个方法

CreateObject

IDL组件对象的初始化

CreateObjectEx

可传参数的IDL组件对象初始化

DestroyObject

IDL组件对象销毁

ExecuteString

IDL命令执行,功能相当于IDL中的命令行

GetIDLObjectClassName

获取IDL中对象类的名字

GetIDLObjectVariableName

获取IDL中对象的名称

GetIDLVariable

获取IDL中变量的值

GetLastError

获取最近一次出错的错误信息

GetProcessName

获取IDLprocedure的名称

SetIDLVariable

创建IDL下的变量

SetProcessName

设置包含IDL对象的程序名称

 

组件与C#进行数据传递的基本数据类型见下表。

IDL类型

ActiveX类型

IDL_TYPE_BYTE

UT_UI1 – unsigned char

IDL_TYPE_BYTE

VT_I1 - signed char

IDL_TYP_INT

VT_I2 - signed short

IDL_TYP_LONG

VT_I4 - signed long

IDL_TYP_FLOAT

VT_R4 - float

IDL_TYP_DOUBLE

VT_R8 - double

2) 应用示例

Ø  界面创建

在“UsingCOM_IDL_CONNECT”的基础上,新添加一按钮,属性参数中设置Name为“exchange”,Text为“参数传递”(图5.1)。

5.1 添加“参数传递”按钮

Ø  代码编写

IDL下对变量和数组进行处理的函数复制到当前C#工程的Debug目录下。

PRO EXCHANGEVAR,var = var

  tmp = DIALOG_MESSAGE(StrTrim(var,2),/infor, $

    title ='IDL Show Dialog_Message')

  var = StrTrim(var,2)+' com from IDL'

END

 

PRO EXCHANGEARR,arr,oriArr= oriArr

  tmp = DIALOG_MESSAGE(STRING(arr),/infor,$

    title ='IDL Show Dialog_Message')

  oriArr = arr

  arr = arr+3

EN

双击界面中的“参数传递”按钮来编写操作代码,具体如下。

//新建COM_IDL_CONNECT对象

COM_IDL_connectLib.COM_IDL_connect oComIDL = new COM_IDL_connectLib.COM_IDL_connect();

//对象初始化

oComIDL.CreateObject(0, 0, 0);

//定义变量

string varInt = "C# using IDL";

//定义IDL下的变量var,初始值为varInt

oComIDL.SetIDLVariable("var", varInt);           

//编译IDL功能源码

oComIDL.ExecuteString(".compile '"+Application.StartupPath.ToString()+"\exchangevar.pro'");

oComIDL.ExecuteString("exchangevar,var = var");

//获取IDL下的var变量

object objVar = oComIDL.GetIDLVariable("var");

MessageBox.Show(objVar.ToString());

//定义数组

int[,] dataarr = new int[3, 2] { { 6, 4 }, { 12, 9 }, { 18, 5 } };

//定义IDL下的变量var,初始值为varInt

oComIDL.SetIDLVariable("arr", dataarr);

//编译IDL功能源码

oComIDL.ExecuteString(".compile '" + Application.StartupPath.ToString() + "\ExchangeArr.pro'");

oComIDL.ExecuteString("ExchangeArr, arr,oriArr = oriArr");

//获取IDL下变量arr

object objArr = oComIDL.GetIDLVariable("arr");

object objArrOri = oComIDL.GetIDLVariable("oriArr");

//弹出第一个元素的值

MessageBox.Show("C#中的数组值为:" + ((Array)objArr).GetValue(0, 0));

 

运行项目后点击按钮“参数传递”,依次弹出界面(图5.2和图5.3)。

5.2变量传递测试

5.3数组传递测试

Ø  分析

添加断点,程序运行到最后,在局部变量界面中对比dataarrobjArrobjArrOri三个变量的区别(图5.4)。


5.4 C#中数组与IDL中获取的数组

 

 



https://wap.sciencenet.cn/blog-344887-455924.html

上一篇:为什么有些教授可以称之为“叫兽”
下一篇:ENVI二次开发综述与常用源代码分享

0

该博文允许注册用户评论 请点击登录 评论 (1 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2021-12-8 09:46

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部