OpenCV CV :: Mat和Eigen :: Matrix

时间:2013-02-09 00:02:41

标签: 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);

我已尝试使用cv2eigeneigen2cv,但结果cvMat完全被破坏了,我不确定为什么。尺寸是正确的,但图形完全被破坏,所以可能是每像素字节或数据大小问题?

5 个答案:

答案 0 :(得分:51)

您也可以使用

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

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

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

答案 1 :(得分: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());

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

答案 2 :(得分:25)

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

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

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

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

答案 3 :(得分:1)

Pierluigi的版本对我来说并不适用于3频道图像!经过一番调查后,我结束了以下对我有用的解决方案:

using namespace Eigen;

constexpr uint32_t height = 3;
constexpr uint32_t width = 7;

cv::Mat img(height, width, CV_32FC3, cv::Scalar(1.0f, 2.0f, 3.0f));

using MatrixXfRowMajor = Matrix<float, Dynamic, Dynamic, RowMajor>;
using C3Stride = Stride<Dynamic, 3>;
C3Stride c3Stride(width *3,3);


using cvMap = Map<MatrixXfRowMajor, Unaligned, C3Stride >;
cvMap imgC1(reinterpret_cast<float*>(img.data) + 0, img.rows, img.cols, c3Stride);
cvMap imgC2(reinterpret_cast<float*>(img.data) + 1, img.rows, img.cols, c3Stride);
cvMap imgC3(reinterpret_cast<float*>(img.data) + 2, img.rows, img.cols, c3Stride);

std::cout << imgC1 << std::endl << std::endl;
std::cout << imgC2 << std::endl << std::endl;
std::cout << imgC3 << std::endl << std::endl;

答案 4 :(得分:0)

这对我有用,

  #include <opencv2/core/eigen.hpp>

  cv::Mat image;
  image = cv::imread("/dataset/images/15207_angle_image.jpg", CV_LOA D_IMAGE_GRAYSCALE);   // Read the file
  Eigen::Matrix<float,Eigen::Dynamic, Eigen::Dynamic> eigen_mat;
  cv::cv2eigen(image, eigen_mat);
相关问题