2012-01-12 27 views
7

Matlabに行列を送るには、C++コードで "engine.h"を使用します。実際には、私はcv :: Matの中にデータを持っているので、mxArrayを送信する必要があります。私はこの表現を使用しようとしましたが、うまくいきません:cv :: MatからmxArrayにデータを変換する

cv::Mat _priorP; 
_priorP = Mat::eye(13, 13, CV_32FC1); 
mxArray *mat; 
mat = mxCreateDoubleMatrix(13, 13, mxREAL); 

memcpy(mxGetPr(mat),_priorP.data, 13*13*sizeof(double)); 

変換を行う正しい方法は誰も知っていますか?どんな援助も感謝します。ありがとう。 https://stackoverflow.com/a/8848711/744859

答えて

4

This threadCvMatmxArrayに変換する方法を示しています。

EDIT私はこの方法を見つけました。探しているコンバージョンコードと正確に同じではありませんが、かなり近いです。

これは単純な変換であり、CvMatの代わりにcv::Matで動作するようにコードを調整する必要があります。あなたができない場合は、迅速なハックがCvMatにごcv::Matデータを変換してから(私が提案したリンクから取られる)として以下のコードを使用することです:

mxArray* CvMat_to_new_mxArr (const CvMat* mat) 
{ 
    const int TYPE = cvGetElemType (mat); 

    // 2-d image 
    if (CV_64FC1 == TYPE) { 
    return helper_2dcvmat_to_mat<CV_64FC1> (mat); 
    } 
    else if (CV_32FC1 == TYPE) { 
    return helper_2dcvmat_to_mat<CV_32FC1> (mat); 
    } 
    else if (CV_32SC1 == TYPE) { 
    return helper_2dcvmat_to_mat<CV_32SC1> (mat); 
    } 
    else if (CV_16SC1 == TYPE) { 
    return helper_2dcvmat_to_mat<CV_16SC1> (mat); 
    } 
    else if (CV_16UC1 == TYPE) { 
    return helper_2dcvmat_to_mat<CV_16UC1> (mat); 
    } 
    else if (CV_8UC1 == TYPE) { 
    return helper_2dcvmat_to_mat<CV_8UC1> (mat); 
    } 
    else if (CV_8SC1 == TYPE) { 
    return helper_2dcvmat_to_mat<CV_8SC1> (mat); 
    } 

    //Multi-dimensional arrays not supported, yet. 
    /* 
    // 3-d image 
    else if (CV_64FC3 == TYPE) { 
    return helper_rgbimage_to_mat<IPL_DEPTH_64F> (img); 
    } 
    else if (CV_32FC3 == TYPE) { 
    return helper_rgbimage_to_mat<IPL_DEPTH_32F> (img); 
    } 
    else if (CV_8UC3 == TYPE) { 
    return helper_rgbimage_to_mat<IPL_DEPTH_8U> (img); 
    } 
    */ 

    // unsupported conversion, return null mxArray 
    return mxCreateDoubleMatrix(0,0,mxREAL);  
} 


template<int TYPE> 
mxArray* helper_2dcvmat_to_mat (const CvMat* mat) 
{ 
    void* pBeg; 
    int pitch; 
    cvGetRawData(mat, (uchar**)&pBeg,&pitch); 

    CvSize size = cvGetSize (mat); 
    const mxClassID cid = cvm_traits<TYPE>::CID; 
    mxArray* pArrOut = 
    mxCreateNumericMatrix(size.height,size.width,cid,mxREAL); 
    void* pBegOut = mxGetData(pArrOut); 

    typedef mc_traits<cid>::CT T; 
    pix_iterator_2d<T,eRowWise> it_src1(static_cast<T*>(pBeg), 
    size.width,size.height,pitch); 
    pix_iterator_2d<T,eRowWise> it_src2(static_cast<T*>(pBeg), 
    size.width,size.height,pitch); 
    it_src2.end(); 
    pix_iterator_2d<T,eColWise> it_dest(static_cast<T*>(pBegOut), 
    size.width,size.height); 

    std::copy (it_src1,it_src2,it_dest); 

    return pArrOut; 
} 
+0

ありがとうございました。ですから、open.cVでengine.hを使うのはいつも面倒ですね。私はより直接的なものを期待していましたが、もっと簡単な解決法がない場合、私はこれを試してみます。 –

+1

1つの質問。 opencvが列ごとに行とmatlabによってデータを格納することを検討していますか? –

+1

私が提案したスレッドを開き、そこにある**完全なソースコードを見てください。他のユーザーによると、そのコードは動作します。しかし、そうでなければ、少なくともあなたのためのスタートです。 – karlphillip

3

私はこのconvertionを行うための簡単な方法を見つけましたいくつかの努力の後。私がやっていることは、このような関数を作成します

void arithmetic::cvLoadMatrixToMatlab(Engine *ep, const Mat& m, string name) 
{ 
    int rows=m.rows; 
    int cols=m.cols; 
    //Mat data is float, and mxArray uses double, so we need to convert. 
    mxArray *T=mxCreateDoubleMatrix(cols, rows, mxREAL); 
    double *buffer=(double*)mxGetPr(T); 
    for(int i=0; i<rows; i++){ 
     for(int j=0; j<cols; j++){ 
      buffer[i*(cols)+j]= (double)m.at<float>(i, j); 
     } 
    } 

    //memcpy((char*)mxGetPr(T), (char*)m.data, rows*cols*sizeof(double)); 
    engPutVariable(ep, name.c_str(), T); 
    name=name+"="+name+"'";     // Column major to row major (mat=mat') 
    engEvalString(ep, name.c_str()); 

    mxDestroyArray(T); 
} 
9

パッケージは、MATLABのネイティブデータ型の間の変換(のmxArrayと呼ばれる)C++クラス(のmxArray)が含まれてい http://github.com/kyamagu/mexopencv でコタ・山口によって開発されたライブラリがありますし、 OpenCVデータ型。ライブラリはOpenCV(Open CVバージョン2.0以上)用のC++ APIを直接サポートしているため、cvMatからcv :: Mat、またはIplImageからcv :: Matへの追加のコンバージョンを行う必要はありません。使用例:

#include "mexopencv.hpp" // include the library 
#include "highgui.h"  

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{ 
    cv::Mat image; 
    image = imread("filename"); // read an image from file 
    plhs[0] = MxArray(image); // convert from cv::Mat to mxArray 
} 

これはそれです。 mex関数を一緒にコンパイルしてください。 MxArray.cppファイルをライブラリからコンパイルしてください。 MATLABコマンドラインで行うことができます。

mex yourmexfile.cpp MxArray.cpp 
+0

ソースコードがあれば十分です。自分の機能を作りたいだけです。ありがとう、非常に役に立つ.. .. –

+1

@Jav_Rock聞いてうれしい! MxArray.cppも私にとってとても役に立ちました。他の人がこの解決策を見ることができるように、この回答をアップ投票することを検討してください。 – Alexey

+3

ええ私はすでにそれをやった! –