将数据从 cv::Mat 转换为 mxArray

发布于 2024-12-26 06:22:15 字数 475 浏览 3 评论 0原文

我想使用 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

I want to send a Matrix to Matlab using "engine.h" in c++ code. The fact is that I have the data inside a cv::Mat, and I need to sent a mxArray. I tried to use this expression but it doesn´t work:

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

Anybody knows the correct way to do the conversion? Any help would be apreciated. Thanks.

EDIT

I found this way:
https://stackoverflow.com/a/8848711/744859

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅暮の光 2025-01-02 06:22:15

有一个由 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 函数与库中的 MxArray.cpp 文件一起编译;您可以在 MATLAB 命令行中执行此操作:

    mex yourmexfile.cpp MxArray.cpp

There is a library developed by Kota Yamaguchi at
http://github.com/kyamagu/mexopencv
The package contains a C++ class (called MxArray) that converts between Matlab's native data type (mxArray) and OpenCV data types. The library directly supports C++ API for OpenCV (Open CV version 2.0 and higher), so there's no need to do an extra conversions (e.g. from cvMat to cv::Mat or from IplImage to cv::Mat). Sample usage:

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

That's it. Make sure to compile your mex function together with MxArray.cpp file from the library; you can do so in MATLAB command line:

    mex yourmexfile.cpp MxArray.cpp
请远离我 2025-01-02 06:22:15

此帖子展示了如何转换CvMatmxArray。尽管它并不完全是您正在寻找的转换代码,但它非常接近。

这是一个简单的转换,您应该能够调整代码以使用 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;
}

This thread shows how to convert a CvMat to mxArray. Even though it's not exactly the conversion code you are looking for, it's pretty close.

This is a simple conversion and you should be able to adjust the code to work with cv::Mat instead of CvMat. If you can't, a quick hack is to convert your cv::Mat data to CvMat and then use the code below as is (taken from the link I suggested):

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;
}
老娘不死你永远是小三 2025-01-02 06:22:15

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

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

I found a simpler method to do this convertion after some effort. What I do is creating a function like this:

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文