当前位置:首页 > 工业控制 > 电子设计自动化

摘 要:通过运用Matlab与VC的语言和平台特性,解决了二维数组参数的传递与输出;介绍两种Matlab图像嵌入VC界面的方法,并以主成分分析为实例,讲解了相关细节与难点。同时,介绍了一种更加灵活、简便的读取Excel文件的方法。
关键词: COM组件; Matlab; VC; 二维数组; 图像嵌入

基于COM组件的Matlab与C++混合编程方式因拥有独立的运行环境和两种语言的互补优势而被众多科研人员和编程人员所接受,同时也是MathWorks公司推荐使用的混编方式。但在程序设计过程中,通常会遇到两个难点问题:(1)二维数组参数的传递与输出; (2)Matlab生成图形嵌入VC工程界面中。对于第一个问题,Bruce McKinney[1]在MSDN上指出;“如果对一维数组进行操作,则SAFEARRAY函数变的简单且易操作。但是对于多维数组,同样的操作要复杂得多”,造成这一问题的根源在于Matlab与C++对多维数组元素的存储方式不同。而在本项目开发过程中回避了这个复杂的过程,转而利用Matlab强大的数组处理功能将其解决。Matlab完善的图形处理功能是其被科研人员所推崇的原因之一,但因其图形拥有独立的窗口,严重影响了整体界面美观和用户交互体验,所以Matlab图形嵌入是混合编程中不可回避的问题。对此将通过实例介绍两种图形嵌入方法并分析说明其优缺点和相关细节。
本文示例均在Matlab R2008a和VC 6.0平台下完成,且通过调试能够正常运行。
1 Excel文件读取方法
VC平台下的Excel文件读取方式复杂难懂,但如果使用Matlab与VC的混合编程方式编写将更加简便,而且拥有较强的可扩展性。下面代码详细讲解了该过程。
(1)在Matlab平台下建立CExcelRead.m文件,代码如下:
function [output,row,col] = CExcelRead(filePath)
//filePath包含了指定文件的路径和文件名,由VC平台函数GetPathName()获取
[typ, desc] = xlsfinfo(filePath);
//xlsfinfo()可获取指定Excel文件中各个sheet工作区的名称,返回值存入名为desc的cell数组中
sheet1 = cell2mat(desc(1));
//默认打开”sheet1”(名称任意),并将其转换为字符串
output = xlsread(filePath,sheet1);
//返回该Excel文件中的数据,返回值存入output数组中
[row,col] = size(output);
//获取录入数据的行列值,返回到VC平台以供其拷贝指定内存大小的数据
output = reshape(output,row*col,1);
//将该二维数组转换为一维。这是第二部分二维数组处理的第一步
保存文件后,使用deploytool工具将其制作成名为FileOpen的COM(封装MCR),注册该控件并将相应的文件拷贝到MFC的工程中,对于基础操作此处不再赘述。
(2)在VC平台下创建名为PCA的基于对话框的MFC工程,添加一打开文件的按钮控件,ID为ID_FILE_OPEN。篇幅所限只给出部分核心代码,首先在Dlg类中添加3个私有成员变量用以保存Matlab读取的数据及行列值,即:
double *m_originData; long m_row, m_col;
在响应函数中添加如下代码
CFileDialog fileDlg(TRUE);
fileDlg.m_ofn.lpstrTitle="请选择你的excel数据";
fileDlg.m_ofn.lpstrFilter="Text Files(*.xls)*.xlsAll Files(*.*)*.*";
  if(IDOK==fileDlg.DoModal() {
  CString fileName; IFileOpenclass *pfile;
VARIANT filePath,output,rowOutput,colOutput;
//m文件的输入参数
fileName = fileDlg.GetPathName();
//获取文件路径并存于fileName中
CoInitialize(NULL); //COM初始化
HRESULT hr = CoCreateInstance(CLSID_FileOpenclass,NULL,CLSCTX_ALL,IID_IFileOpenclass,(void**)&pfile);
//新建COM实例
VariantInit(&filePath); //VARIANT数据初始化

filePath.vt = VT_BSTR; //指定filePath变量类型
//将fileName中保存的指定文件路径名保存至filePath参数中
filePath.bstrVal = fileName.AllocSysString();
pfile->CExcelRead(3,&output,&rowOutput, &colOutput,filePath);
m_row=(long) rowOutput.dblVal;
//取出行列值及录入数据
m_col = (long) colOutput.dblVal;
m_originData = (double *)malloc(sizeof(double)*m_row*m_
col); memcpy(m_originData,output.parray->pvData,m_row*m_
col*sizeof(double));
//将matlab读入数据保存到m_originData供后面程序使用
} 上述C++代码中省略了异常处理和相关的内存、COM释放代码,由于代码比较简单所以不做进一步解析。请注意,下面将省略COM初始化及实例化等相同代码。
(3) 需要重点说明的是该方法的扩展性。通常Excel文件中保存多个工作区,有时用户可能需要打开同一Excel文件中不同工作区中的数据,常规方法实现过于复杂,但对于本文介绍的方法可以通过修改添加几条语句即可实现。首先,新建一个m文件用来处理工作区的选择,代码如下:
function [sheet,col] = CSheetSelected(filePath)
[typ, sheet] = xlsfinfo(filePath);
[row,col] = size(sheet);
由于返回值是一个cell数组,所以VC平台要使用CStringArray数据结构保存返回值,并显示各工作区名称供用户选择。然后,通过人机交互将用户选择的工作区参数保存并传递至CExcelRead.m,通过在CExcelRead.m增加一个工作区选择参数,并对代码稍作修改即可。
2 二维数组参数的传递与输出[2]
下面以主成分分析为例介绍基于COM的Matlab与VC混合编程中二维数组参数处理。
(1) 主成分分析pcamat.m代码如下:
function [eigenvector,eigenvalue] = pcamat(oriData,row,column)
//在Excel读入时已经完成了二维数组输出的关键步骤,即输出时将二维数组转换为一维数组。但在VC平台接收还原为二维时要注意,Matlab数组存储方式是按列存储,而VC平台下数组是按行存储,所以转换时0~row-1为第一列,row~2*row-1为第二列,以此类推。本文输入参数oriData是一维数组,所以要将其还原为二维数组使Matlab程序能够正常运行,即下一行代码所示。
oriData = reshape(oriData,row,column);
dataSTD=std(oriData,0,1); dataMean = mean(oriData);
dataSR = (oriData-dataMean(ones(row,1),:))./dataSTD(ones(row,1),:);
[eigenvector,newdata,eigenvalue,Exa]=princomp(dataSR);
//第三行至此处均为主成分分析内容
eigenvector = reshape(eigenvector,column*column,1);
//与Excel文件读取时类似,将二维输出转换为一维数组进行输出
(2) 保存后,封装打包为COM组件,并完成注册等相关操作。在PCA工程对话框上添加一个名为PCATest的按钮控件,核心代码如下:
VARIANT oriData,row,column,eigVector,eigValue;
VariantInit(&oriData); //参数初始化

oriData.vt = VT_R8|VT_ARRAY;
//定义SAFEARRAY类型的一维数组
SAFEARRAYBOUND rgsadound[1];
rgsadound[0].lLbound = 0;
rgsadound[0].cElements = m_row*m_col;
oriData.parray = SafeArrayCreate(VT_R8,1,rgsadound);
oriData.parray->pvData = m_originData;
//完成相关设置后,将第一步读入的数据录入到oriData中,即赋给pcamat的oriData。到此完成了二维数组的传递
row.vt = VT_I4; col.vt = VT_I4;
row.lVal = m_row; col.lVal = m_col;
pca->pcamat(2,&eigVector,&eigValue,oriData,row,col);
memcpy(result, eigVector.parray->pvData,m_col*m_col*
sizeof(double));
综上,二维数组参数处理就是使用reshape()函数对输入输出数据维数进行变换来完成操作。
3 Matlab图像嵌入VC界面[3]
3.1 基于CWnd类的图像嵌入

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

通过大量的数据,训练出一个能处理此类数据的模型,使得这个模型可以根据已知的数据,准确率很高的判断出未知的数据,从而使得人类能够采取正确的方法去处理某些事情。

关键字: 机器学习 模型 图像

在监督学习中,系统会被给定一组已知输入和输出,需要学习到一种函数,使得该函数能够根据给定的输入预测出正确的输出。代表算法有线性回归、逻辑回归、决策树、深度神经网络等。

关键字: 机器学习 数据源 图像

在这一步中,需要从不同的数据源收集数据,包括结构化数据(例如数据库中的表格数据)和非结构化数据(例如文本、图像和音频)。

关键字: 机器学习 数据源 图像

作为一种解决方案和应用,其核心内容是:让人们无论任何时间、任何地点,都可以通过任何设备、任何网络,获得数据、图像和声音的自由通信。

关键字: 统一通信 图像 思科

大多数紧急事件的发生具有时间不确定性从而造成应急通信也具有时间不确定性,使人们无法预知什么时候需要应急通信。

关键字: 应急通信 语音 图像

三相电机是一种常见的电机类型,广泛应用于工业和家庭领域。在三相电机中,功率是一个非常重要的参数,它直接关系到电机的运行性能和效率。因此,正确地计算三相电机的功率对于电机的设计、选型和使用都具有重要的意义。本文将详细介绍三...

关键字: 三相电机 功率 参数

数值计算方法是一种用于解决数学问题的方法,涉及到数值近似、数值逼近、数值积分、数值微分等等。算法设计是数值计算方法的核心,它包括了数值方法的数学原理和计算机实现的算法,能够有效地解决各种数学问题。

关键字: matlab 算法设计 数值积分

自耦变压器是一种特殊的变压器,其与普通变压器最大的不同在于其具有一个共享线圈的设计。这种设计使得自耦变压器能够实现更高的效率和较小的尺寸。而要计算自耦变压器的相关参数值,则需要考虑多个因素。在本文中,我们将详细介绍如何计...

关键字: 自耦变压器 共享线圈 参数

电气系统中应用最多的就是电力变压器,由于电力变压器的种类很多,其型号的标识以及参数也有所不同,因此常常将这些型号与参数标识在变压器的铭牌上,以便于在安装和检修时进行查看。变压器的种类有很多,为了便于区别各种不同类型的变压...

关键字: 变压器 参数 型号

仿真的基本思想是利用物理的或数学的模型来类比模仿现实过程,以寻求过程和规律。它的基础是相似现象,相似性一般表现为两类

关键字: matlab 程序仿真 仿真模式
关闭
关闭