萍聚社区-德国热线-德国实用信息网

 找回密码
 注册

微信登录

微信扫一扫,快速登录

萍聚头条

查看: 1864|回复: 1

[电子] Matlab 和 C++ (1)

[复制链接]
发表于 2007-5-28 12:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册 微信登录

x
用了Matlab 为什么还要C++?
主要的问题是:
1)速度。
2)为了以后可以独立于Matlab
最近一直在用Matlab处理实验的图形。碰到一个问题就是速度。我们的图形是16bit灰度,一般为512(长)*512(宽)*300 - 1000(幅)的一个三维矩阵;300-1000是因为有300-1000个时间点和深度。为了内存的关系,我们不得不用short int来保存图形。图形处理中的一步是得到这些图的平均值图。一般用Matlab 的mean(pic_Array, 3)来完成。可是非常慢。所以,就用C写了一个函数。顺便贴在这里,大如果有同样的要求,可以用用。
函数叫mymean3意思是求第三维的平均。对于16bit 矩阵,速度可以提高10倍以上。
执行结果:
>>A=uint16(rand(200,200,1000)*1000);       (这一步是产生一个随机三维16bit矩阵)
>>tic;B=mean(A,3);toc                      (这一步是Matlab 求平均)
Elapsed time is 4.087521 seconds.
>> tic;C=mymean3(A);toc                    (这一步我们自己的函数求平均,怎么样快了约一个半数量级!)
Elapsed time is 0.129360 seconds.
>>sum(sum(B-C,2),1)        (这一步是一个简单的检验,证明结果和matlab一致)

ans =

0

------------------------------------------------------------
// file name: myMean3.cpp
#include "mex.h"
#include "math.h"
#define MY_START 0
//#include <windows.h>
#define MY_MAX_DIM  10

//#define MATLAB_CLASS_NAME "com.mathworks.mde.desk.MLMainFrame"
//#define MATLAB_WND_NAME "MATLAB"


/*----------------------------------------------------------------------------------------------*/
int mySqueeze(const mxArray *pInArray, int *pOutDim, int nMax){
int i,j,k,l=0;
const int *pAddr = mxGetDimensions(pInArray);
char lpString[100];

j=mxGetNumberOfDimensions(pInArray);
for(i=0;i<j;i++){
    if((k=pAddr)==1){
        //sprintf(lpString,"Dimention %d is 1, it will be queezed !",i+1);   //GetTopWindow(NULL)
        //MessageBox( FindWindow(MATLAB_CLASS_NAME, MATLAB_WND_NAME),lpString, "Squeeze One Dimention !", MB_OK|MB_ICONINFORMATION);
    }else{
        if(l<nMax)l++;
        else break;
        pOutDim[l]=k;
    }
}
return(pOutDim[0]=l);
}
/*----------------------------------------------------------------------------------------------*/
void myCalMean3(unsigned short *pInArray, int nM, int nN, int nL, double *dOutArray){
int nPlaneL= nM * nN, nSum, *pnSum, *pnSumA, i,j;
unsigned short *pB=pInArray;
double *pdOut=dOutArray;

pnSumA = pnSum = (int *)malloc(nPlaneL * sizeof (int));
if(pnSum==NULL)mexErrMsgTxt("Out of Memory");
for(i=0;i<nPlaneL;i++) *pnSumA++ = *pB++;

for(j=1;j<nL;j++){
   pnSumA = pnSum;
   for(i=0;i<nPlaneL;i++) *pnSumA++ += *pB++;
}
pnSumA = pnSum;
for(i=0;i<nPlaneL;i++)
  *pdOut++ = (double)(*pnSumA++)/nL;
free(pnSum);
}
/*----------------------------------------------------------------------------------------------*/
void myCalMean3(unsigned int *pInArray, int nM, int nN, int nL, double *dOutArray){
int nPlaneL=nM*nN;
int nSum,i,j;
unsigned int *pB=pInArray;
double *pdSum, *pdSumA, *pdOut=dOutArray;

pdSumA = pdSum = (double *) malloc(nPlaneL * sizeof (double));
if(pdSum==NULL)mexErrMsgTxt("Out of Memory");
for(i=0;i<nPlaneL;i++) *pdSumA++ = *pB++;

for(j=1;j<nL;j++){
   pdSumA = pdSum;
   for(i=0;i<nPlaneL;i++) *pdSumA++ += *pB++;
}
pdSumA = pdSum;
for(i=0;i<nPlaneL;i++)
  *pdOut++ = (double)(*pdSumA++)/nL;
free(pdSum);
}
/*----------------------------------------------------------------------------------------------*/
void myCalMean3(double *pInArray, int nM, int nN, int nL, double *dOutArray){
int nPlaneL=nM*nN;
int nSum,i,j;
double *pdSum, *pdSumA, *pdOut=dOutArray, *pB=pInArray;

pdSumA = pdSum = (double *)malloc(nPlaneL * sizeof (double));
if(pdSum==NULL)mexErrMsgTxt("Out of Memory");
for(i=0;i<nPlaneL;i++) *pdSumA++ = *pB++;

for(j=1;j<nL;j++){
   pdSumA = pdSum;
   for(i=0;i<nPlaneL;i++) *pdSumA++ += *pB++;
}
pdSumA = pdSum;
for(i=0;i<nPlaneL;i++)
  *pdOut++ = (double)(*pdSumA++)/nL;
free(pdSum);
}
/*----------------------------------------------------------------------------------------------*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int nArrayID, nArrayDim, nFun, nSize;
int i=0,j;
int pnDimCount[MY_MAX_DIM+1];
int pnDimOut[MY_MAX_DIM];

  /*  Check for proper number of arguments. */
  /* NOTE: You do not need an else statement when using
     mexErrMsgTxt within an if statement. It will never
     get to the else statement if mexErrMsgTxt is executed.
     (mexErrMsgTxt breaks you out of the MEX-file.)
  */
  if (nrhs!=1)
    mexErrMsgTxt("Using: aOut = myMean3( aIn ); aIn is 3 DIM matrix ");
  nArrayID = mxGetClassID(prhs[0]);
  nArrayDim = mySqueeze(prhs[0], pnDimCount, MY_MAX_DIM);
  for(i=0,j=1;j<=nArrayDim;j++){
    if(j==3)continue;
    pnDimOut[i++]= pnDimCount[j];
  }
  //printf("i=%d, %d, %d, %d, %d\n",i,pnDimOut[0], pnDimOut[1], pnDimOut[2], pnDimOut[3]);  // for error check only
  if(nArrayDim <3){
    mexErrMsgTxt("aIn must be an array larger than 2 dimension" );
  }
  //plhs[0] = mxCreateNumericArray( i , pnDimOut, mxDOUBLE_CLASS, mxREAL); // for array > 3
  plhs[0] = mxCreateNumericArray( 2 , pnDimOut, mxDOUBLE_CLASS, mxREAL);  // for array ==3
  switch(nArrayID){
    case mxINT16_CLASS:
    case mxUINT16_CLASS:
        myCalMean3((unsigned short *)mxGetData (prhs[0]), pnDimCount[1], pnDimCount[2], pnDimCount[3], mxGetPr(plhs[0]));
        break;
    case mxINT32_CLASS:
    case mxUINT32_CLASS:
        myCalMean3((unsigned int *)mxGetData (prhs[0]), pnDimCount[1], pnDimCount[2], pnDimCount[3], mxGetPr(plhs[0]));
        break;
    case mxDOUBLE_CLASS:
        myCalMean3((double *)mxGetData (prhs[0]), pnDimCount[1], pnDimCount[2], pnDimCount[3], mxGetPr(plhs[0]));
        break;
    default:
        printf("ClassID= %d, Name= %s, is not supported now\n", nArrayID, mxGetClassName(prhs[0]));
        mexErrMsgTxt("aIn must be INT or Double");
        break;

}

}
---------------------------------

注,以上默认的是LCC,您可以用 -o2来优化代码。
如果是用VC 或者BC编译,打"//"的语句就可以用了。这样,可以给您的c函数阿增加一个squeeze的窗口。详细可以看函数中打"//"的各行。这里的matlab class name 对应的是matlab 2006ab 2007a 的class name 主窗口是一个 com.mathworks.mde.desk.MLMainFrame class

评分

2

查看全部评分

Die von den Nutzern eingestellten Information und Meinungen sind nicht eigene Informationen und Meinungen der DOLC GmbH.
发表于 2007-5-31 23:52 | 显示全部楼层
曾经看过Mex和C的接口,不过没有仔细研究。多谢楼主!
Die von den Nutzern eingestellten Information und Meinungen sind nicht eigene Informationen und Meinungen der DOLC GmbH.
您需要登录后才可以回帖 登录 | 注册 微信登录

本版积分规则

手机版|Archiver|AGB|Impressum|Datenschutzerklärung|萍聚社区-德国热线-德国实用信息网 |网站地图

GMT+2, 2024-5-8 04:42 , Processed in 0.057063 second(s), 19 queries , MemCached On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表