【问题标题】:Convert data from cv::Mat to mxArray将数据从 cv::Mat 转换为 mxArray
【发布时间】:2012-02-08 16:34:03
【问题描述】:

我想在 C++ 代码中使用“engine.h”向 Matlab 发送一个矩阵。事实是我在 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

【问题讨论】:

    标签: c++ opencv image-processing matlab-engine


    【解决方案1】:

    有一个由 Kota Yamaguchi 开发的库,位于 http://github.com/kyamagu/mexopencv 该包包含一个 C++ 类(称为 MxArray),可在 Matlab 的本机数据类型 (mxArray) 和 OpenCV 数据类型之间进行转换。该库直接支持 OpenCV 的 C++ API(Open CV 版本 2.0 及更高版本),因此无需进行额外的转换(例如从 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 函数与库中的 with MxArray.cpp 文件一起编译;你可以在 MATLAB 命令行中这样做:

        mex yourmexfile.cpp MxArray.cpp
    

    【讨论】:

    • 源代码对我来说已经足够了,我只是想做自己的功能。非常感谢,确实很有用..
    • @Jav_Rock 很高兴听到! MxArray.cpp 对我也很有帮助。考虑对此答案进行投票,以便其他人可以看到此解决方案。
    【解决方案2】:

    This thread 显示如何将CvMat 转换为mxArray。即使它不完全是您正在寻找的转换代码,它也非常接近。

    这是一个简单的转换,您应该能够调整代码以使用cv::Mat 而不是CvMat。如果你不能,一个快速的技巧是将你的cv::Mat 数据转换为CvMat,然后按原样使用下面的代码(取自我建议的链接):

    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;
    }
    

    【讨论】:

    • 谢谢。所以在 openCV 中使用 engine.h 总是很麻烦,不是吗?我期待更直接的东西,但如果没有更简单的解决方案,我会尝试这个。
    • 一个问题。你是否考虑过opencv按行存储数据,matlab按列存储?
    • 我必须坚持让您打开我建议的主题并查看那里提供的完整源代码。根据其他用户的说法,该代码有效。但如果没有,至少对你来说是一个开始。
    【解决方案3】:

    经过一番努力,我找到了一种更简单的方法来进行这种转换。我所做的是创建这样的函数:

    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);
    }
    

    【讨论】:

      猜你喜欢
      • 2017-07-12
      • 2020-02-09
      • 1970-01-01
      • 2012-12-29
      • 2014-05-07
      • 2011-06-07
      • 2016-04-13
      • 2011-10-23
      • 1970-01-01
      相关资源
      最近更新 更多