matlab7.0与vc++6.0混合编程(win7系统),使用com组件的方式实现vc++6.0调用matlab的小波去噪工具箱函数
最重要的须知!!!
1.matlab一定是安装matlab7.0版本。
2.vc++6.0的位置一定是安装在C:\Program Files\Microsoft Visual Studio位置。
不要尝试其他matlab版本,我已经花了整整近四天时间安装过
matlab2020b,matlab2016b,与matlab2015b与vc++6.0混合编程,均已失败告终,我装软件都装吐了,因为就拿matlab2020b来讲,压缩包,解压,及安装下来至少40G,你去细品吧(下载,卸载,安装)!!因为我是第一次用matlab与vc++6.0混合编程,如果你是大牛,期待你能带给我们惊喜。一般人的话做个阿甘吧,乖,听话!!!
安装matlab7.0,vc++6.0
安装matlab7.0就在网上随便找7.0版本下载,安装过程找度娘搜一下就有了,vc++6.0的安装就不说了。matlab7.0安装好后可能打不开,可能是兼容性问题,请百度解决方案哟,加油你可以的!!
配置环境变量
本来有一篇博客有写详尽的配置方案的,但是他们今天居然在整改,先将网址粘在这里,大家一定去看,很详细,我能成功真的多亏了这篇博客,我不是打广告啊,谁写的我也不认识, 但是又详细又好真的是爱了爱了。
https://www.cnblogs.com/cmt/p/14553189.html
大家不要去了就不回来了,过程基本上是一样的,但是后面的小波去噪部分都是我自己搞出来的。
配置环境变量
1.控制面板\系统和安全\系统\高级系统设置\环境变量\系统变量\PATH
下加上D:\matlab7.0\extern\include;D:\matlab7.0\extern\lib\win32\microsoft\msvc70;D:\matlab7.0\bin\win32;这三个路径,其中D:\matlab7.0是我电脑matlab7.0的安装路径。
2.控制面板\系统和安全\系统\高级系统设置\环境变量\系统变量\编辑
变量名:matlab
变量值:D:\matlab7.0(你的matlab7.0路径)
不要忘记点确定。
听说环境变量配置过后要关机重启才能生效,不管是不是真的我每次都重启。
让matlab7.0连上vc++6.0的编译器
1.在matlab命令行输入mbuild -setup,回车出现下图
y 回车则出现下图
选2就是你的vc++6.0路径,回车出现下图
问你是不是确定你的选择,y回车就可以,出现下图就可以了
然后还是在命令行输入mex -setup,回车出现下图
还是y回车,出现下图
选3,就是你的vc++6.0,回车出现下图
还是y回车,出现下图就成功了
以上都做好后就可以生成com组件了
生成com组件
在命令行输入comtool回车弹出下面这个框
File\New Project弹出下面这个框
给你的com组件取一个帅气的英文名(在component name下面),点击Classes的空白处,会自动生成一个类名,Project directory是生成的com组件的位置,这个需要记忆以下,待会会用,我的路径是D:\matlab7.0\work\plot,另外Compiler option下面两个都勾选,有的只有一个,就勾选一个,点OK就行,plot是我的com组件名,plotclass是我的类名,点开plotclass,选中M-files,如下图所示。
然后Project\Add Files选择你想在vc++6.0里面调用的matlab函数的路径,这里我们调用的是matlab中的wden.m函数,把这个函数的路径添加进来,如下图。
然后点击Build\Com Object就会开始生成com组件,出现下图就成功了。
到现在基本上就没有matlab什么事了。
对于wden.m函数有非常重要的事情交代
wden.m函数是matlab的工具箱函数,一共有7个输入参数,3个返回值,在matlab中调用时也可以用6个输入参数调用,因为wden.m函数内部有判断输入参数个数的代码,可根据输入参数的不同分别执行不同的代码。这么多字,看到这里是不是累了,但真的很重要,耐心看下去。这一共10各参数,生成com组件的接口是10个variant的结构体类型变量,这是一个超级超级复杂的结构体,赋值和提取值都很复杂,如果不改wden.m函数的接口就没办法完成我的功能,我把wden函数改成的1个输入参数,1个输出参数,输入参数是待滤波的数据,输出参数是滤波后的参数。这样我再vc++6.0中就只需要操作2个参数了。下面是我修改后的wden.m函数,名字是wden1.m。
function [xd] = wden1(in1)
%WDEN Automatic 1-D de-noising using wavelets.
% WDEN performs an automatic de-noising process of a 1-D
% signal using wavelets.
%
% [XD,CXD,LXD] = WDEN(X,TPTR,SORH,SCAL,N,'wname') returns
% a de-noised version XD of input signal X obtained by
% thresholding the wavelet coefficients.
% Additional output arguments [CXD,LXD] are the wavelet
% decomposition structure of de-noised signal XD.
%
% TPTR string contains threshold selection rule:
% 'rigrsure' use principle of Stein's Unbiased Risk.
% 'heursure' is an heuristic variant of the first option.
% 'sqtwolog' for universal threshold sqrt(2*log(.)).
% 'minimaxi' for minimax thresholding.
% (see THSELECT for more details).
% SORH ('s' or 'h') is for soft or hard thresholding
% (see WTHRESH for more details).
% SCAL defines multiplicative threshold rescaling:
% 'one' for no rescaling.
% 'sln' for rescaling using a single estimation
% of level noise based on first level coefficients.
% 'mln' for rescaling done using level dependent
% estimation of level noise.
% Wavelet decomposition is performed at level N and 'wname'
% is a string containing the name of desired orthogonal
% wavelet.
%
% [XD,CXD,LXD] = WDEN(C,L,TPTR,SORH,SCAL,N,'wname') returns
% same output arguments, using the same options as above, but
% obtained directly from the input wavelet decomposition
% structure [C,L] of the signal to be de-noised, at level N
% and using 'wname' orthogonal wavelet.
%
% See also THSELECT, WAVEDEC, WDENCMP, WFILTERS, WTHRESH.
% M. Misiti, Y. Misiti, G. Oppenheim, J.M. Poggi 12-Mar-96.
% Last Revision: 14-May-2003.
% Copyright 1995-2004 The MathWorks, Inc.
% $Revision: 1.10.4.2 $
% Check arguments.
%nbIn = nargin;
%switch nbIn
% case {0,1,2,3,4,5} , error('Not enough input arguments.');
% case 6 ,
x = in1; tptr = 'minimaxi'; sorh = 's';
scal = 'sln'; n = 4; w = 'sym3';
% case 7 ,
% c = in1; l = in2; tptr = in3;
% sorh = in4; scal = in5; n = in6; w = in7;
%end
if errargt(mfilename,tptr,'str'), error('*'), end
if errargt(mfilename,sorh,'str'), error('*'), end
if errargt(mfilename,scal,'str'), error('*'), end
if errargt(mfilename,n,'int'), error('*'), end
if errargt(mfilename,w,'str'), error('*'), end
%if nbIn==6
% Wavelet decomposition of x.
[c,l] = wavedec(x,n,w);
%end
% Threshold rescaling coefficients.
switch scal
case 'one' , s = ones(1,n);
case 'sln' , s = ones(1,n)*wnoisest(c,l,1);
case 'mln' , s = wnoisest(c,l,1:n);
otherwise , error('Invalid argument value.')
end
% Wavelet coefficients thresholding.
first = cumsum(l)+1;
first = first(end-2:-1:1);
ld = l(end-1:-1:2);
last = first+ld-1;
cxd = c;
lxd = l;
for k = 1:n
flk = first(k):last(k);
if tptr=='sqtwolog' | tptr=='minimaxi'
thr = thselect(c,tptr);
else
if s(k) < sqrt(eps) * max(c(flk))
thr = 0;
else
thr = thselect(c(flk)/s(k),tptr);
end
end % threshold.
thr = thr * s(k); % rescaled threshold.
cxd(flk) = wthresh(c(flk),sorh,thr); % thresholding or shrinking.
end
% Wavelet reconstruction of xd.
xd = waverec(cxd,lxd,w);
vc++6.0调用com组件
一般的调用方法
还是根据上面提到的那篇博客完成就可以。大约3.25号整改完成后就可以看了,如果不能看我再加更这一部分的内容。
调用小波去噪函数
怎么把待滤波的一维数组转换成可以调用的variant类型,并从variant类型中提取滤波后的一维数组,这一段非常重要,一维数组的类型是double类型的。
void DISPLAYTEM::OnStart()
{
// TODO: Add your control notification handler code here
plot.CreateDispatch(CLSID_waveletclass,NULL); //创立接口
COleDispatchDriver(); //连接(此句可以不写)
}
void DISPLAYTEM::OnPlot()
{
// TODO: Add your control notification handler code here
const int N=2960; //数组大小
double a[N]; //数组定义
// 赋值
for (int i=0; i<N; i++)
{
a[i]=T[i+1];
}
//char IN1[10]={'m','i','n','i','m','a','x','i'};
//char IN2[10]={'s'};
//char IN3[10]={'s','l','n'};
//long IN4 = 4;
//char IN5[10]={'s','y','m','3'};
//任意变量
VARIANT x;
VARIANT xd;
VariantInit(&x); //初始化
VariantInit(&xd); //初始化
x.vt=VT_ARRAY|VT_R8; //类型(数组,双精度型)
xd.vt=VT_ARRAY|VT_R8; //类型(数组,双精度型)
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].cElements=N; //数组所含元素数
rgsabound[0].lLbound=0; //数组上界
//创立数组
x.parray=SafeArrayCreate(VT_R8,1,rgsabound); //创立一维安全数组
xd.parray=SafeArrayCreate(VT_R8,1,rgsabound); //创立一维安全数组
//锁定数组
SafeArrayLock(x.parray);
SafeArrayLock(xd.parray);
//数组传递数据
x.parray->pvData=a;
//调用方法
plot.wden1(1,&xd,x);
//把variant的double类型数组给提取处来
long dim = SafeArrayGetDim(xd.parray);
long ubound;
long lbound;
SafeArrayGetUBound(xd.parray,dim,&ubound);
SafeArrayGetLBound(xd.parray,dim,&lbound);
double *buf;
SafeArrayAccessData(xd.parray,(void**)&buf);
for(int o=lbound;o<ubound;o++)
{
Wavelet_T[o]=buf[o];
}
x里有待滤波数组(带滤波数组开始在a数组里,是我需要处理的数据T数组中的一部分),xd里有滤波后数组(滤波后的数组存在Wavelet_T数组中),具体怎么调用的参见代码,然后我把滤波前后的数据通过mfc绘制成图表显示出来了,我滤波的是温度数据,滤波后的波动范围明显小了,如下图!