2013-05-08 121 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