2013-05-08 203 views
2

我有几个存储在cv::Mat中的特征向量,其中每行都是一个特征向量(这里有几行像这样:[ x1 y1 x2 y2 x3 y3.... ])。我必须在每个特征向量上应用SVD并为此使用Eigen库。但是,在应用SVD之前,必须将特征矩阵转换为Eigen::Matrix形式。cv :: Mat转换为Eigen-Matrix并返回

后来,我必须将SVD结果转换回cv::Mat

任何人都可以请建议一个很好的方式来做到这一点?我在cv::Mat表格中需要它的原因是因为我必须将它输入到OpenCV中的神经网络中,并且只允许输入矩阵cv::Mat

谢谢!

+1

可能重复[OpenCV的CV ::垫和本征::矩阵(http://stackoverflow.com/questions/14783329/opencv-cvmat-and-eigenmatrix )。无需复制数据,请使用Eigen :: Map。看看这里的答案:http://stackoverflow.com/questions/14783329/opencv-cvmat-and-eigenmatrix/21706778#21706778 – Ela782 2015-01-27 12:04:03

回答

3

试试这个代码征到CV:

template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols> 
void eigen2cv(const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, cv::Mat& dst) 
{ 
    if (!(src.Flags & Eigen::RowMajorBit)) 
    { 
     cv::Mat _src(src.cols(), src.rows(), cv::DataType<_Tp>::type, 
      (void*)src.data(), src.stride() * sizeof(_Tp)); 
     cv::transpose(_src, dst); 
    } 
    else 
    { 
     cv::Mat _src(src.rows(), src.cols(), cv::DataType<_Tp>::type, 
      (void*)src.data(), src.stride() * sizeof(_Tp)); 
     _src.copyTo(dst); 
    } 
} 

正如你可以看到这个执行复制。用一个你不需要关心的矩阵,但你可以改变代码。要获得第一列,请使用cv::Mat::column()

尝试这些方法CV之一征:

template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols> 
void cv2eigen(const Mat& src, 
       Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst) 
{ 
    CV_DbgAssert(src.rows == _rows && src.cols == _cols); 
    if(!(dst.Flags & Eigen::RowMajorBit)) 
    { 
     Mat _dst(src.cols, src.rows, DataType<_Tp>::type, 
       dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); 
     if(src.type() == _dst.type()) 
      transpose(src, _dst); 
     else if(src.cols == src.rows) 
     { 
      src.convertTo(_dst, _dst.type()); 
      transpose(_dst, _dst); 
     } 
     else 
      Mat(src.t()).convertTo(_dst, _dst.type()); 
     CV_DbgAssert(_dst.data == (uchar*)dst.data()); 
    } 
    else 
    { 
     Mat _dst(src.rows, src.cols, DataType<_Tp>::type, 
       dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); 
     src.convertTo(_dst, _dst.type()); 
     CV_DbgAssert(_dst.data == (uchar*)dst.data()); 
    } 
} 

template<typename _Tp> 
void cv2eigen(const Mat& src, 
       Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst) 
{ 
    dst.resize(src.rows, src.cols); 
    if(!(dst.Flags & Eigen::RowMajorBit)) 
    { 
     Mat _dst(src.cols, src.rows, DataType<_Tp>::type, 
      dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); 
     if(src.type() == _dst.type()) 
      transpose(src, _dst); 
     else if(src.cols == src.rows) 
     { 
      src.convertTo(_dst, _dst.type()); 
      transpose(_dst, _dst); 
     } 
     else 
      Mat(src.t()).convertTo(_dst, _dst.type()); 
     CV_DbgAssert(_dst.data == (uchar*)dst.data()); 
    } 
    else 
    { 
     Mat _dst(src.rows, src.cols, DataType<_Tp>::type, 
       dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); 
     src.convertTo(_dst, _dst.type()); 
     CV_DbgAssert(_dst.data == (uchar*)dst.data()); 
    } 
} 


template<typename _Tp> 
void cv2eigen(const Mat& src, 
       Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst) 
{ 
    CV_Assert(src.cols == 1); 
    dst.resize(src.rows); 

    if(!(dst.Flags & Eigen::RowMajorBit)) 
    { 
     Mat _dst(src.cols, src.rows, DataType<_Tp>::type, 
       dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); 
     if(src.type() == _dst.type()) 
      transpose(src, _dst); 
     else 
      Mat(src.t()).convertTo(_dst, _dst.type()); 
     CV_DbgAssert(_dst.data == (uchar*)dst.data()); 
    } 
    else 
    { 
     Mat _dst(src.rows, src.cols, DataType<_Tp>::type, 
       dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); 
     src.convertTo(_dst, _dst.type()); 
     CV_DbgAssert(_dst.data == (uchar*)dst.data()); 
    } 
} 


template<typename _Tp> 
void cv2eigen(const Mat& src, 
       Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst) 
{ 
    CV_Assert(src.rows == 1); 
    dst.resize(src.cols); 
    if(!(dst.Flags & Eigen::RowMajorBit)) 
    { 
     Mat _dst(src.cols, src.rows, DataType<_Tp>::type, 
       dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); 
     if(src.type() == _dst.type()) 
      transpose(src, _dst); 
     else 
      Mat(src.t()).convertTo(_dst, _dst.type()); 
     CV_DbgAssert(_dst.data == (uchar*)dst.data()); 
    } 
    else 
    { 
     Mat _dst(src.rows, src.cols, DataType<_Tp>::type, 
       dst.data(), (size_t)(dst.stride()*sizeof(_Tp))); 
     src.convertTo(_dst, _dst.type()); 
     CV_DbgAssert(_dst.data == (uchar*)dst.data()); 
    } 
} 

来源:此代码是从OpenCV的本身而论,他们用它作为内部的OpenCV可以使用libeigen对国内一些任务。我不明白为什么格式转换到这样的库和Qt没有通过API公开。

+0

谢谢你的建议!你能告诉我什么是“模板”的东西吗?我还没有达到高级水平... 以及如何将cv :: Mat转换为Eigen :: Matrix ....感谢您的输入! @ypnos – learner 2013-05-08 22:28:33

+0

什么是“typename _Tp”和DataType <_Tp> 请多解释一下......它非常重要...... – learner 2013-05-08 22:30:26

+0

您需要自己学习模板。但使用此代码相当容易,不涉及模板。例如:cv :: Mat_ src; Eigen :: MatrixXf dest(src.rows,src.cols); cv2eigen(src,dest); – ypnos 2013-05-08 22:33:39

1

看一看Mapping data from Eigen to OpenCV and back文章。它描述了如何以更少的开销映射数据。在最简单的情况下,根本就没有拷贝。它还应对征表现,以及:

// Unsharp mask 
Eigen::ArrayXXd img, blur;  
eigen2cv(img) = cv::imread("lena.jpg"); 
cv::GaussianBlur(eigen2cv(img), eigen2cv(blur)); 

cv::imshow("sharpened", eigen2cv(1.5 * img - 0.5 * blur)); 
+0

你在博客中讨论的新头文件不适用于OpenCV 2.4.9。我只包含了头文件Eigen2CV.h,而g ++则引发了一系列奇怪的错误。 – mkuse 2015-03-25 15:02:00