Ubuntu 下matlab與 opencv混合編程

     一直想學習mex接口函數,可惜之前沒有用到過,於是沒特別在意。這次因爲跑別人的code,感覺還是搞出一個matlab wrapper,這樣會比較方便。但是這個涉及到mex混編以及調用opencv的問題。

於是乎,裏面涉及到很很多多的問題,包括配置的問題,編譯的問題,參數傳遞的問題,等等。但是,一旦你能掌握他,你就相當於結合了MATLAB的優點(容易上手,快速編程,不需要考慮定義變量)和C的優點(計算速度快)。

首先給出幾個學習mex文件的鏈接:

www.cnblogs.com/lidabo/archive/2012/08/24/2654148.html

http://blog.csdn.net/njust_qhzt/article/details/8249008

http://www.cnblogs.com/Key-Ky/p/4233581.html

基本格式

#include "mex.h"

void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{

}

四個參數分別用來輸出和輸入數據: nlhs 輸出參數個數,plhs 輸出參數指針 (nrhs和prhs是輸入參數相關的)。同時如果涉及到了opencv的編譯,一般還要include "mxArray。h"

注意: 我們對輸出和輸入參數的操作都是通過指針的方式進行的。(這點很容易理解,因爲我們的計算結果是需要傳遞給MATLAB的,實際上我們傳遞的不是數據,而是指針。MATLAB可以通過這些指針,訪問內存中的數據。)

mex文件本質上是接口文件,於是就涉及到數據的輸入和輸出,也就是從MATLAB傳數據給c和從c傳數據給MATLAB。

操作輸入數據(matlab->c)

對輸入數據進行操作,需要通過MEX函數mxGetPr 得到數據的指針地址。 mxGetM 和 mxGetN 得到矩陣數據的行和列 (返回整數)。對於實矩陣,我們可以定義 double *M; 來對實矩陣數據操作。如:

double *M;

int m,n;

// 指針指向第一個參數的數據地址

M = mxGetPr(prhs[0]);

m = mxGetM(prhs[0]);

n = mxGetN(prhs[0]);

   1.輸入的如果是單個常數,就可以用

    int x

   x = mxGetScalar(prhs[0]);//該函數獲取matlab傳遞過來的數值;
   2. 如果是矩陣(向量也算在內):

   dataCursor = mxGetPr(prhs[0]);//得到輸入矩陣的第一個元素的指針

  intmrows = mxGetM(prhs[0]);   //獲得矩陣的行
  intncols = mxGetN(prhs[0]);   //獲得矩陣的列
  這樣就可以獲得矩陣的指針dataCursor進行進一步的操作,下面將給出一個詳細額例子。
  特殊情況,如果傳的是image,image本身也是矩陣,但是可能是三維的,於是可以用mxArray的函數實現傳遞。
  3.如果是字符串:
  
  char*input_buf;
  input_buf = mxArrayToString(prhs[0]);//使用mxArrayToString將mxArray轉換爲c、c++字符串

需要注意的是,MATLAB矩陣數據的存儲順序是"從上到下,從左到右"的,這點和Fortran是一樣的。也就是說對於MATLAB的m x n的矩陣A。 A(1,1) 就是 *M,A(2,1) 就是 *(M+1) ,以此類推,A(i,j) 就是 *(M + m*(j-1) + (i-1)).

注意: MATLAB的指標從1開始,C的指標從0開始.

操作輸出數據

 對於輸出數據,我們需要首先分配內存空間,有專門的mex函數可以使用,如:

 plhs[0] = mxCreateDoubleMatrix(m,n, mxREAL); //生成m x n 的實矩陣。

 此外還有mxCreateNumericMatrix(m,n,mxREAL);。具體參考上面的第三個鏈接

 同輸入數據一樣,要對輸出數據操作,我們也需要一個指向數據的指針變量,如

 double *A;

 A = mxGetPr(plhs[0]);

然後我們就可以把數值付給A。

下面是個幾個例子

1.矩陣傳入和傳出

#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
double *inData;
double *outData;
int M,N;
int i,j;

 

inData=mxGetPr(prhs[0]); //獲取輸入的第一個參數指針
M=mxGetM(prhs[0]);
N=mxGetN(prhs[0]);

plhs[0]=mxCreateDoubleMatrix(M,N,mxREAL); //構建一個輸出用的矩陣
outData=mxGetPr(plhs[0]);  //指針
for( i=0;i <M;i++)

   for(j=0;j <N;j++

    outData[j*M+i] =inData[(N-1-j)*M+i];
}

2.同樣是矩陣傳入和傳出

#include "mex.h"
 
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
    double*dataCursor;  //指向第一個輸入變量的指針
    vector<vector<double> > parms; //利用c++的vector定義矩陣
 
    dataCursor = mxGetPr(prhs[0]);//得到輸入矩陣的第一個元素的指針
    intmrows = mxGetM(prhs[0]);   //獲得矩陣的行
    intncols = mxGetN(prhs[0]);   //獲得矩陣的列
    printf("%d_%d\n", mrows, ncols); //打印行和列
     
    parms.resize(mrows); //初始化
    for(inti = 0; i < mrows; i++){
        parms[i].resize(ncols); //每一個一維數組元素都初始化一個向量,於是得到一個矩陣
    }
 
    for(inti = 0; i < mrows; i++){
        for(intj = 0; j < ncols; j++){
            parms[i][j] = dataCursor[j * mrows + i];//拷貝矩陣的元素到vector of vector
        }
    }
 =================================================================
下面講講涉及到opencv的情況,如果直接傳圖片到c,那麼可以直接用cv::Mat image = MxArray(plhs[0]).toMat();
那麼得到的image就是Mat格式的,而不是vector格式的。如果想從Mat轉vector格式,可以用 im[i*w+j] =  image.at<float>(i,j);
實現轉化,注意是float,不是double,因爲opencv和c的精度是不等價的。









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章