||
ENVI (The Environment for Visualizing Images)和IDL(Interactive Data Language)是美国ITT VIS公司的旗舰产品,是由遥感领域的科学家采用IDL开发的一套功能强大的遥感图像处理软件。其软件处理技术覆盖了图像数据的输入/输出、定标、几何校正、正射校正、图像融合、镶嵌、裁剪、图像增强、图像解译、图像分类、基于知识的决策树分类、面向对象图像分类、动态监测、矢量处理、DEM提取及地形分析、雷达数据处理、制图、三维场景构建、与GIS的整合,提供了专业可靠的波谱分析工具和高光谱分析工具。ENVI软件几乎可支持所有的UNIX系统,Mac OS X,Linux,以及PC机的Windows XP/ Vista/7/Server2008等操作系统。
ENVI具有丰富的函数接口API,完整的示例代码帮助文档。ArcGIS Engine是一套完备的嵌入式GIS 组件库和工具库,即是一个用于开发新应用程序的二次开发功能组件包。开发者可以选择集成开发环境来建立 ArcGIS Engine 应用程序,而同时开发环境又可以集成ENVI/IDL的功能,这样使得开发一个遥感与GIS一体化的程序变得非常的容易。下面以ArcGIS Engine10.0和ENVI4.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); } |
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 |
按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组件对象销毁 |
IDL命令执行,功能相当于IDL中的命令行 |
|
获取IDL中对象类的名字 |
|
GetIDLObjectVariableName |
获取IDL中对象的名称 |
GetIDLVariable |
获取IDL中变量的值 |
获取最近一次出错的错误信息 |
|
GetProcessName |
获取IDL中procedure的名称 |
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 |
VT_R8 - double |
Ø 界面创建
在“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数组传递测试
Ø 分析
添加断点,程序运行到最后,在局部变量界面中对比dataarr、objArr和objArrOri三个变量的区别(图5.4)。
图5.4 C#中数组与IDL中获取的数组
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-12-6 09:36
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社