OpenCV CV :: Mat和Eigen :: Matrix

Yer*_*aze 27 opencv eigen

是否有可逆的方式将OpenCV cv::Mat对象转换为Eigen::Matrix

例如,某种做法:

cv::Mat cvMat;
Eigen::Matrix eigMat;
camera->retrieve(cvMat);

// magic to convert cvMat to eigMat
// work on eigMat
// convert eigMat back to cvMat

imshow("Image", cvMat);
Run Code Online (Sandbox Code Playgroud)

我已经尝试使用cv2eigeneigen2cv,但由此产生的cvMat完全是错位的,我不知道是什么原因.尺寸是正确的,但图形完全被破坏,所以可能是每像素字节或数据大小问题?

小智 54

你也可以使用

void eigen2cv(const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Mat& dst)
Run Code Online (Sandbox Code Playgroud)

void cv2eigen(const Mat& src, Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst)
Run Code Online (Sandbox Code Playgroud)

来自#include <opencv2/core/eigen.hpp>.


Pie*_*igi 27

您应该考虑使用Eigen :: Map来包装OpenCV矩阵,以便由Eigen SDK直接使用.这允许您在OpenCV分配的矩阵上应用Eigen中实现的几乎所有功能

特别是你只需要实例化一个提供指向cv :: Mat缓冲区的指针的Eigen :: Map:

//allocate memory for a 4x4 float matrix
cv::Mat cvT(4,4,CV_32FC1); 

//directly use the buffer allocated by OpenCV
Eigen::Map<Matrix4f> eigenT( cvT.data() ); 
Run Code Online (Sandbox Code Playgroud)

有关Eigen :: Map的更多信息,请查看 Eigen Tutorial:Map Class

  • 多通道图像通常存储为交错阵列(例如RGBRGBRGB ...).根据你想用它们做什么,你可以考虑将每个单一通道映射到一个不同的Eigen :: Map,利用stride参数:`cv :: Mat cvT(4,4,CV_32FC3); //一个3通道浮点矩阵Eigen :: Map <Matrix4f,RowMajor,Stride <3,1 >> red(cvT.data); Eigen :: Map <Matrix4f,RowMajor,Stride <3,1 >> green(cvT.data +1); Eigen :: Map <Matrix4f,RowMajor,Stride <3,1 >> blue(cvT.data +2);` (13认同)
  • 使用cvT.data()对我不起作用,给出了编译器错误.我在下面发布了一个关于如何操作的答案,包括如何为任意大小的矩阵执行此操作以及从Eigen到OpenCV的反向转换. (3认同)
  • @lubosz使用`cv_mat.ptr <float>()`会好得多.请注意,我认为您将行主要数据映射到列主要矩阵 - 我认为您的结果可能是错误的,它将是转置.我想你需要`Eigen :: RowMajor`. (2认同)

Ela*_*782 26

您可以在Eigen和OpenCV之间映射任意矩阵(无需复制数据).

你必须要注意两件事:

  • Eigen默认为列主存储,OpenCV存储行主要.因此,在映射OpenCV数据时使用Eigen :: RowMajor标志.

  • OpenCV矩阵必须是连续的(即ocvMatrix.isContinuous()必须为真).如果您在创建矩阵时一次性为矩阵分配存储空间就是这种情况(例如,如下面的示例中所示,或者矩阵是Mat W = A.inv()等操作的结果;)

例:

Mat A(20, 20, CV_32FC1);
cv::randn(A, 0.0f, 1.0f); // random data

// Map the OpenCV matrix with Eigen:
Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> A_Eigen(A.ptr<float>(), A.rows, A.cols);

// Do something with it in Eigen, create e.g. a new Eigen matrix:
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> B = A_Eigen.inverse();

// create an OpenCV Mat header for the Eigen data:
Mat B_OpenCV(B.rows(), B.cols(), CV_32FC1, B.data());
Run Code Online (Sandbox Code Playgroud)

对于多通道矩阵(例如图像),您可以像Pierluigi在评论中所建议的那样使用'Stride'!