【问题标题】:how to initialize a Eigen Matrix from an opencv cv::Mat, or from an array which is row-major?如何从 opencv cv::Mat 或从行优先的数组初始化特征矩阵?
【发布时间】:2013-10-01 11:53:31
【问题描述】:

我发现 Eigen 的 Matrix 是默认列优先的,这就像 MATLAB,但是如何从 cv::Mat 初始化 Eigen::MatrixXd?以下代码是我的测试。但是没有一个可以成功编译。有人可以给我一些建议吗?或其他一些链接?谢谢。

    cv::Mat A_M=cv::Mat(rows, cols, CV_64FC1);
    double *A=(double *)A_M.data();
    typedef Map<MatrixXd> MapMat;
    MapMat A_eigen(A,m,n);

    Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> A_eigen;
    Eigen::Map<Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> >(A,m,n) = A_eigen;

更新:

    double *A=(double *)A_M.data();//m*n
    double *B=(double *)B_M.data();//n*p
    double *C=(double *)C_M.data();//m*p
    //regular Eigen Matrix
    Eigen::MatrixXd A_eigenMat;
    Eigen::MatrixXd B_eigenMat;
    Eigen::MatrixXd C_eigenMat;
    Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > A_mappedMat (A, m, n);
    Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > B_mappedMat (B, n, p);
    Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > C_mappedMat (C, m, p);
    // Eigen handles the conversion from row major to column major
    A_eigenMat = A_mappedMat;
    B_eigenMat = B_mappedMat;
    C_eigenMat = C_mappedMat;

    // multiplication
    C_eigenMat=A_eigenMat*B_eigenMat;

然后,当我输出 M_C 时,它的结果是错误的。似乎 C_eigenMat 没有将数据复制到 M_C.data 中。

【问题讨论】:

    标签: c++ eigen


    【解决方案1】:

    来自Conversion between OpenCV and Eigen的示例:

    cv::Mat_<float> a = Mat_<float>::ones(2,2);
    Eigen::Matrix<float,Dynamic,Dynamic> b;
    cv2eigen(a,b);
    

    已经回答on SO:

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

    还有一个SO post

    【讨论】:

    • 非常感谢这么快的回复!和正确的答案。
    • @NicolasZhong - 很高兴为您提供帮助)
    • @MikroDel 我可以添加一个相关的小问题吗?看起来正在使用 Eigen 动态矩阵。这很方便,但它会显着影响性能速度吗?在这种情况下,矩阵是图像大小,例如640x480?谢谢!
    【解决方案2】:

    MikroDel 的答案使用 OpenCV 的功能,但 cv2eigen 包含数据的副本,如果您只想映射数据指针,这不是最佳选择。使用Eigen::Map&lt;&gt; 通常是更好的选择。我修改了你的代码,这个例子有效:

    int main(int argc, char *argv[]) {
      int rows = 4, cols = 3;
      cv::Mat A_M=cv::Mat::eye(rows, cols, CV_64FC1);
      A_M.at<double>(0,2) = 10;
      double *A=(double *)A_M.data;
      //regular Eigen Matrix
      Eigen::MatrixXd eigenMat;
    
      Eigen::Map<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> > mappedMat (A,rows, cols);
      // Eigen handles the conversion from row major to column major
      eigenMat = mappedMat;   
    
      std::cout << A_M << std::endl;
      std::cout << eigenMat << std::endl;
      return 0;
    }
    

    【讨论】:

    • 谢谢,这就是我真正的意思。
    • 谢谢,这就是我真正的意思。但我已经用给出的代码 MikroDel 进行了测试,没有错误。而且我没有查看cv2eigen的源码,如果这个函数需要复制数据,效率非常低。你的回答真的是我想做的。我不想复制数据,只是让 Eigen 使用 Mat::data() 缓冲区。所以它应该节省内存使用。
    • cv2eigen 函数似乎没有数据副本。我已经测试了你给定的代码,似乎eigenMatC_MxP=eigenMatA_MxN * eigenMatB_NxP 有错误的结果。有什么问题吗?
    • cv2eigen 在transpose() 调用(或convertTo(),取决于选项)中确实有一个数据副本。请粘贴您使用的导致错误结果的代码。
    • 我无法在没有看到代码的情况下尝试修复代码,请在此处粘贴(或更新问题)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多