提高matlab运算速度的几种方法.docx

上传人:b****4 文档编号:4417203 上传时间:2022-12-01 格式:DOCX 页数:17 大小:32.49KB
下载 相关 举报
提高matlab运算速度的几种方法.docx_第1页
第1页 / 共17页
提高matlab运算速度的几种方法.docx_第2页
第2页 / 共17页
提高matlab运算速度的几种方法.docx_第3页
第3页 / 共17页
提高matlab运算速度的几种方法.docx_第4页
第4页 / 共17页
提高matlab运算速度的几种方法.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

提高matlab运算速度的几种方法.docx

《提高matlab运算速度的几种方法.docx》由会员分享,可在线阅读,更多相关《提高matlab运算速度的几种方法.docx(17页珍藏版)》请在冰豆网上搜索。

提高matlab运算速度的几种方法.docx

提高matlab运算速度的几种方法

由于matlab是一种解释性语言,所以在matlab程序中最忌讳直接使用循环语句,如果不得已要使用for循环,可以采用以下方法提高速度。

1、使用6.5以上版本,对循环已作优化;

2、尽可能转化为矩阵运算;

3、转化为二进制执行文件运算,如使用matlab内带的编译系统或matcom以及com组件技术。

其中com组件技术最方便的就是利用combuilder来实现,这里重点介绍。

combuilder是matlab6.5才有的,也是mathworks公司推荐使用于混合编程的,这些日子进行了全方位的摸索,感觉是爽呆了,下面我们一起来揭开它的神秘面纱。

此系列分为以下几块:

1.matlab下做com组件

2.vb,c#.net实现调用

3.vc实现调用

4.打包

5.优缺点评注

其中2,3部分可以选择一个看

matlab下做com组件

com是componentobjectmodule的简称,它是一种通用的对象接口,任何语言只要按照这种接口标准,就可以实现调用它。

matlab6.5新推出来的combuilder就是把matlab下的程序做成com组件,供其他语言调用。

我们先准备两个测试文件,并copy一个图片到c盘下,起名叫1.jpg(这些你都可以改的,我这儿是为了程序方便):

第一个叫im_test.m如下:

functionim_test%这个文件不带输入与输出

I=imread('c:

\1.jpg');%因为以前带有imshow的程序用mcc编成dll后用不

%了,所以想试combuilder是否

imshow(I);%能支持这些函数

第二个叫split2rgb.m,就是前些日子Zosco发给我的那个程序,因为它用mcc编成dll后有问题,所以我在这儿继续将它进行测试,而且它也带有多个输入及输出参数,所以也正好拿来测试

在matlab的workspace下打comtool,就打开了matlabcombuilder,点击file-newproject,新建一个工程,在componentname里填上comtest,Classname里填上一个sgltest(并将自动生成classes里的comtestremove掉),complie

codein选c或c++都无所谓,将Complieroptions里的UseHandleGraphicslibrary的复选框画上,点击ok就行了。

然后点击project--Addfiles,将im_test.m和split2rgb.m添加入工程,然后点Build-ComObject,就会在comtest\distrib\文件夹下生成一个comtest_1_0.dll(它就是做好的com组件),Build时matlab已经自动将此dll在注册表中注册,为了下面能用其他编译器调用,我们还需做一个准备工作,开一个dos窗口,进入/bin/win32目录下(matlabroot为你机器上matlab安装的路径),打regsvr32mwcomutil.dll,即对mwcomutil.dll进行注册(这个dll是matlab下作的任何com组件都要用到的dll),下面我们在其他编译器下调用时就可以用了。

是不是觉得做起com组件来很简单呢,matlab下可以给com组件中的类添加成员、事件、方法等,我这儿其实是给类sgltest添加了两个方法,怎么添加成员和方法可以参看matlab的combuilder的帮助。

附录:

split2rgb.m的源代码

%%//测试文件

function[m_nHeight,m_nWidth,mOrigR,mOrigG,mOrigB]=Split2RGB(FileName)

%%//读入一个Jpg文件,

mOrigData=imread(FileName);

%mDestData=imresize(mOrigData,0.5);

imwrite(mOrigData,'c:

\2.jpg');

%%//用三个变量保存其R,G,B分量

mOrigR=mOrigData(:

:

1);

mOrigG=mOrigData(:

:

2);

mOrigB=mOrigData(:

:

3);

%%//获得图象的高度,宽度

[m_nHeight,m_nWidth]=size(mOrigR);

figure

(1);

set(gcf,'MenuBar','none')

imshow(mOrigData);

title(['OrginalImage:

',FileName],'Color','b','FontSize',14);

xlabel(['Height:

',num2str(m_nHeight),'Width:

',num2str(m_nWidth)],'Color'

'b','FontSize',12);

%%//写param文件

paraFName=[FileName(1:

length(FileName)-4),'.param'];

fid=fopen(paraFName,'w');

fwrite(fid,m_nHeight,'uint32');

fwrite(fid,m_nWidth,'uint32');

fclose(fid);

%%//写R分量文件

RFName=[FileName(1:

length(FileName)-4),'_R.rot'];

fid=fopen(RFName,'w');

fwrite(fid,mOrigR,'uint8');

fclose(fid);

%%//写G分量文件

GFName=[FileName(1:

length(FileName)-4),'_G.rot'];

fid=fopen(GFName,'w');

fwrite(fid,mOrigG,'uint8');

fclose(fid);

%%//写B分量文件

BFName=[FileName(1:

length(FileName)-4),'_B.rot'];

fid=fopen(BFName,'w');

fwrite(fid,mOrigB,'uint8');

fclose(fid);

这一部分讲vb,c#.net下怎么实现调用上一部分我们生成的comtest_1_0.dll(matlab下做的com组件),记得一定先要对mwcomutil.dll进行注册(怎么注册参看上一部分)

1.vb下实现调用

打开或新建一个vb工程,点project-Reference,在弹出来的窗口中找到comtest1.0TypeLibrary,将前面的复选框选上,点击ok,此时便将此com组件添加到工程里面去了,此时你可以用对象浏览器看到comtest下有个sgltest类,这个类里面有两个方法im_test,split2rgb,还有个MWFlags成员(这个成员是自动生成的),vb下测试代码如下:

测试im_test方法的代码:

DimstAssgltest

Setst=Newsgltest

Callst.im_test

测试split2rgb方法的代码:

DimstAssgltest

Setst=Newsgltest

DimhAsVariant,wAsVariant,rAsVariant,gAsVariant,bAsVariant,

filenameAsVariant

filename="c:

\\1.jpg"

Callst.split2rgb(5,h,w,r,g,b,filename)

可见matlab下函数的输入输出参数在com组件里全是variant型的变量,测试大获成功,结果就跟matlab下运行的一摸一样,爽

2.c#.net下实现调用

打开或新建一个c#项目(我采用的是编辑器),选中右边的解决方案资源管理器中的引用,点鼠标右键,选添加引用,在弹出来的窗口中选com,然后也找到comtest_1_0.dll,点选择,然后确定就可,此时此com组件也添加到工程里面去了,同样我们可以选择对象浏览器来看comtest及下面的sgltest类,c#测试项目如下:

测试im_test方法的代码:

comtest.sgltestClassst=newcomtest.sgltestClass();

st.im_test();

测试split2rgb方法的代码:

comtest.sgltestClassst=newcomtest.sgltestClass();

objecth=null,w=null,r=null,g=null,b=null;

objectfilename="c:

\\1.jpg";

st.split2rgb(5,refh,refw,refr,refg,refb,filename);

可见输入参数是refobject型的,而输出参数是object型的,测试同样大获成功,与matlab下运行的结果一摸一样,爽呆了。

这一部分讲vc下实现调用第一部分我们生成的comtest_1_0.dll,同样要记得先对mwcomutil.dll进行注册(怎么注册参看第一部分),vb和.net下实现对com组件的调用很简单,而vc下实现这一步我可是摸索了好几天(主要是vc用的不好)

1.先做一些准备工作,用oleviewer工具开始--程序--Microsoftvisualstudio6.0--Microsoftvisualstudio6.0Tools--OLEviewer(这个工具也可以通过在vc下点Tools--OLE/COMObjectViewer来打开,在Oleviewer工具里,在右边选择Typelibraries,将他展开,找到comtest1.0TypeLibrary,选中它,点鼠标右键,选view,便又弹出一窗口,点工具栏上的save按钮,分别将他保存为comtest_1_0.h,comtest_1_0.c(也可以存为comtest_1_0.Idl接口文件),我们就可以通过这两个文件实现对comtest_1_0.dll调用

2.vc下调用

新建或打开一个vc工程,注意,此时不用对编译器进行任何设置(而用mcc生成的dll我们么设置一大堆,我这儿只设置了Precompliedheaders,选Automaticuseofprecompliedheaders,写上stdafx.h),将comtest_1_0.h和comtest_1_0.c加入工程,并复制一个comtest_1_0.dll到工程目录下,由于comtest_1_0.dll还要用到mwcomutil.dll,所以将/extern/include/下的mwcomutil.h和mwcomtypes.h也加入工程(将这两个文件拷贝入工程路径下,如果设置了librarypath,可以不加)此时可以通过classView看到多出了_IID、IMWUtil,Isgltest类,Isgltest就是我们在matlab下建起来的sgltest类

vc下代码如下

//这几个是引入dll和头文件

#import"mwcomutil.dll"

#import"comtest_1_0.DLL"

#include"mwcomutil.h"

#include"comtest_1_0.h"

#include"comutil.h"//此文件是用来处理由char*向VARIANT类型的转换

测试im_test方法的代码:

if(FAILED(CoInitialize(NULL)))//初始化调用com

{

AfxMessageBox("unabletoinitializeCOM");

}

Isgltest*st=NULL;

//创建一个com组件,CLSID_sgltest和IID_Isgltest可以从comtest_1_0.h和comtest_

1_0.c里找到

HRESULThr=CoCreateInstance(CLSID_sgltest,NULL,CLSCTX_ALL,IID_Isgltest,(voi

d**)&st);

if(SUCCEEDED(hr))

{

st->im_test();

AfxMessageBox("succeed");

st->Release();

}

else

{

AfxMessageBox("unsucceed");

}

如果你的vc工程是consoleproject的话,上述的AfxMessageBox可改成printf或cout,测试split2rgb方法的代码(类型转换我参照visualc的精华区也转换成功了)

if(FAILED(CoInitialize(NULL)))

{

AfxMessageBox("unabletoinitializeCOM");

}

Isgltest*st=NULL;

HRESULThr=CoCreateInstance(CLSID_sgltest,NULL,CLSCTX_ALL,IID_Isgltest,(voi

d**)&st);

VARIANTm,n,r,g,b,filename;

VariantInit(&m);

VariantInit(&n);

VariantInit(&r);

VariantInit(&g);

VariantInit(&b);

VariantInit(&filename);

filename.vt=VT_BSTR;

filename.bstrVal=_com_util:

:

ConvertStringToBSTR("C:

\\1.jpg");

if(SUCCEEDED(hr))

{

st->split2rgb(5,&m,&n,&r,&g,&b,filename);

st->Release();

AfxMessageBox("succeed");

}

else

{

AfxMessageBox("unsucceed");

}

同样,运行结果与matlab下的结果一摸一样,记得我们的im_test里面可是使用了imshow阿,以前用mcc生成的程序中用它可是有错哦,爽呆了。

关于VC下用com组件及其类型的转变请参看msdn及其VisualC的精华区

combuilder系列可以结尾了

一.打包:

在matlab下的workspace里打comtool,点file-openproject将我们先前建好的comtest.cbl工程文件打开,再点component--packagecomponent就实现了打包,此时到comtest\distrib文件夹里看,生成的comtest.exe就是打包后的解压程序,双击它会解压出一些文件,再点击解压出来的_install.bat就可以实现安装(按他的步骤去做就行了)

二.优缺点评注

这几天用这个combuilder可把我给爽死了,特别是在vc下调用成功时,记得精华区里曾讲combuilder没有什么实质性的突破,我可不这么认为,它的突破可大了

1.做出来的是com,通用的,任何编译器只要支持com,就可以实现调用,想c++builder,Delphi等的,我想只要按照调用com组件去做,也能成功的

2.支持imshow等一些原来混编用不了的函数,对图形库的支持也比以前强(这些还需各位大侠共同测试)

3.实现方法简单,没有像以前混编还要设置一大堆东东

4.能够在matlab下写自己的类,并为自己的类编写成员、方法和事件,管理工程也方便(这个有点像vc、vb下管理工程一样)用的太爽了,一下子还不知道怎么写缺点了,^0^,我想缺点还需大家一起用来找出我这儿说一个缺点,感觉它的参数全是VARIANT型的,不怎么方便。

一、基本技术

-----------------------------------------------------

1)MATLAB索引或引用(MATLABIndexingorReferencing)

在MATLAB中有三种基本方法可以选取一个矩阵的子阵。

它们分别是

下标法,线性法和逻辑法(subscripted,linear,andlogical)。

如果你已经熟悉这个内容,请跳过本节

1.1)下标法

非常简单,看几个例子就好。

A=6:

12;

A([3,5])

ans=

810

A([3:

2:

end])

ans=

81012

A=[111417;...

121518;...

131619];

A(2:

3,2)

ans=

15

16

1.2)线性法

二维矩阵以列优先顺序可以线性展开,可以通过现行展开后的元素序号

来访问元素。

A=[111417;...

121518;...

131619];

A(6)

ans=

16

A([3,1,8])

ans=

131118

A([3;1;8])

ans=

13

11

18

1.3)逻辑法

用一个和原矩阵具有相同尺寸的0-1矩阵,可以索引元素。

在某个

位置上为1表示选取元素,否则不选。

得到的结果是一个向量。

A=6:

10;

A(logical([00101]))

ans=

810

A=[12

34];

B=[1001];

A(logical(B))

ans=

14

-----------------------------------------------------

2)数组操作和矩阵操作(ArrayOperationsvs.MatrixOperations)

对矩阵的元素一个一个孤立进行的操作称作数组操作;而把矩阵视为

一个整体进行的运算则成为矩阵操作。

MATLAB运算符*,/,\,^都是矩阵

运算,而相应的数组操作则是.*,./,.\,.^

A=[10;01];

B=[01;10];

A*B%矩阵乘法

ans=

01

10

A.*B%A和B对应项相乘

ans=

00

00

------------------------------------------------------

3)布朗数组操作(BooleanArrayOperations)

对矩阵的比较运算是数组操作,也就是说,是对每个元素孤立进行的。

因此其结果就不是一个“真”或者“假”,而是一堆“真假”。

这个

结果就是布朗数组。

D=[-0.21.01.53.0-1.04.23.14];

D>=0

ans=

0111011

如果想选出D中的正元素:

D=D(D>0)

D=

1.00001.50003.00004.20003.1400

除此之外,MATLAB运算中会出现NaN,Inf,-Inf。

对它们的比较参见下例

Inf==Inf返回真

Inf<1返回假

NaN==NaN返回假

同时,可以用isinf,isnan判断,用法可以顾名思义。

在比较两个矩阵大小时,矩阵必须具有相同的尺寸,否则会报错。

这是

你用的上size和isequal,isequalwithequalnans(R13及以后)。

------------------------------------------------------

4)从向量构建矩阵(ConstructingMatricesfromVectors)

在MATLAB中创建常数矩阵非常简单,大家经常使用的是:

A=ones(5,5)*10

但你是否知道,这个乘法是不必要的?

A=10;

A=A(ones(5,5))

A=

1010101010

1010101010

1010101010

1010101010

1010101010

类似的例子还有:

v=(1:

5)';

n=3;

M=v(:

ones(n,1))

M=

111

222

333

444

555

事实上,上述过程还有一种更加容易理解的实现方法:

A=repmat(10,[55]);

M=repmat([1:

5]',[1,3]);

其中repmat的含义是把一个矩阵重复平铺,生成较大矩阵。

更多详细情况,参见函数repmat和meshgrid。

-----------------------------------------------------

5)相关函数列表(UtilityFunctions)

ones全1矩阵

zeros全0矩阵

reshape修改矩阵形状

repmat矩阵平铺

meshgrid3维plot需要用到的X-Y网格矩阵

ndgridn维plot需要用到的X-Y-Z...网格矩阵

filter一维数字滤波器,当数组元素前后相关时特别有用。

cumsum数组元素的逐步累计

cumprod数组元素的逐步累计

eye单位矩阵

diag生成对角矩阵或者求矩阵对角线

spdiags稀疏对角矩阵

gallery不同类型矩阵库

pascalPascal矩阵

hankelHankel矩阵

toeplitzToeplitz矩阵

==========================================================

二、扩充的例子

------------------------------------------------------

6)作用于两个向量的矩阵函数

假设我们要计算两个变量的函数F

F(x,y)=x*exp(-x^2-y^2)

我们有一系列x值,保存在x向量中,同时我们还有一系列y值。

我们要对向量x上的每个点和向量y上的每个点计算F值。

换句话

说,我们要计算对于给定向量x和y的所确定的网格上的F值。

使用meshgrid,我们可以复制x和y来建立合适的输入向量。

然后

可以使用第2节中的方法来计算这个函数。

x=(-2:

.2:

2);

y=(-1.5:

.2:

1.5)';

[X,Y]=meshgrid(x,y);

F=X.*exp(-X.^2-Y.^2);

如果函数F具有某些性质,你甚至可以不用meshgrid,比如

F(x,y)=x*y,则可以直接用向量外积

x=(-2:

2);

y=(-1.5:

.5:

1.5);

x'*y

在用两个向量建立矩阵时,在有些情况下,稀疏矩阵可以更加有

效地利用存储空间,并实现有效的算法。

我们将在第8节中以一个

实例来进行更详细地讨论.

--------------------------------------------------------

7)排序、设置和计数(Ordering,Setting,andCountingOperatio

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 简洁抽象

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1