【问题标题】:Convert CV::Mat To Arma::mat将 CV::Mat 转换为 Arma::mat
【发布时间】:2014-09-30 10:47:42
【问题描述】:

我尝试将 Opencv 中的表单矩阵转换为犰狳中的矩阵

我在this link找到了这个函数

但是当我尝试调用它时给我错误:

  1. 错误 C2783: 'arma::Mat cvMat2armaMat(cv::Mat &)' : 无法推断出 'T3' 的模板参数
  2. IntelliSense:没有函数模板“cvMat2armaMat”的实例与参数列表匹配

这是函数:

template<class T3>
 arma::Mat <T3> cvMat2armaMat(cv::Mat & cvMatIn) 
{ 
    return armaConv (cvMatIn.data, cvMatIn.rows, cvMatIn.cols,false); 

}

这是函数调用(调用func时出现错误)

cv::Mat CurrentImage    = imread(path, 0);

arma::mat singleImage = cvMat2armaMat (CurrentImage);

我该怎么办?

【问题讨论】:

    标签: c++ opencv armadillo


    【解决方案1】:

    您需要指定cvMat2armaMat() 返回的arma::mat&lt;XXX&gt; 的类型。
    什么是armaConv?
    也许你的意思是:

    template<class T3>
    arma::Mat <T3> cvMat2armaMat(cv::Mat & cvMatIn) 
    { 
        return arma::Mat <T3> (cvMatIn.data, cvMatIn.rows, cvMatIn.cols,false); 
    }
    

    电话是这样的:

    auto singleImage = cvMat2armaMat<float>(CurrentImage);
    

    或者您需要在 cv::Mat 类型上使用 switch。

    【讨论】:

    • 非常感谢,我做了你的建议,所有旧错误都消失了,但现在这个错误出现在函数内部的返回行:错误 C2665:'arma::Mat::Mat':没有18 个重载可以转换所有参数类型有什么帮助吗?
    • 什么是arma::Mat&lt;eT&gt;::Mat?不应该是arma::Mat&lt;eT&gt;吗?
    • 查看犰狳Mat class 的文档,尤其是advanced constructors。如果您正在生成一个arma::Mat&lt;float&gt; 对象,请确保cvMatIn.data 实际上是一个指向浮点数组的指针(即float*)。如果要在类型之间进行转换,则需要手动编写 for 循环将元素从 cvMatIn 复制到 arma::Mat 对象。
    • @AdiShavit 这是我做的最后一件事 template<class t3> arma::Mat <t3> cvMat2armaMat(cv::Mat &amp; cvMatIn) { return arma::Mat<t3> (cvMatIn.data,cvMatIn.rows,cvMatIn.cols,假); } cv::Mat CurrentImage = imread(path, 0);自动 singleImage = cvMat2armaMat<float> (CurrentImage);该错误出现在 func 错误的返回行上:错误 C2665:'arma::Mat<et>::Mat':18 个重载中没有一个可以转换所有参数类型我不知道为什么 VS 编译器说它是 arma: :Mat<et>::Mat ??!!!!</et></et></float>
    【解决方案2】:

    我可以回答如何在 VC10 和 g++ 上执行此操作,但我仍有一些问题需要解决。我是编写模板函数的新手。由于犰狳拥有更完整的线性代数工具,因此经常需要在cv::Mat 和arma::mat 矩阵对象之间进行转换。 OpenCV 以行优先顺序存储它的矩阵,而 Armadillo 以列优先顺序存储它的矩阵,这是该问题的一个组成部分。我创建了以下模板函数,这些函数已在 VC10 和 g++ 4.9 中进行了测试,可用于 float 和 double 类型矩阵:

    template<typename T>
    static void Cv_mat_to_arma_mat(const cv::Mat_<T>& cv_mat_in, arma::Mat<T>& arma_mat_out)
    {
        cv::Mat_<T> temp(cv_mat_in.t()); //todo any way to not create a temporary?
    #if defined(WIN32)
        //This compiles on VC10 but not g++ 4.9 (on Debian with OpenCV 2.4.9.1 and Arma 4.320.0)
        arma_mat_out = arma::Mat<T>(temp.ptr<T>(), //<<"error: expected primary-expression before '(' token"
                                    static_cast<arma::uword>(temp.cols),
                                    static_cast<arma::uword>(temp.rows),
                                    true,
                                    true);
    #elif defined(LINUX)
        //This compiles on both but is not as nice
        arma_mat_out = arma::Mat<T>(reinterpret_cast<T*>(temp.data),
                                    static_cast<arma::uword>(temp.cols),
                                    static_cast<arma::uword>(temp.rows),
                                    true,
                                    true);
    #endif
    };
    
    //This one is fine on both 
    template<typename T>
    static void Arma_mat_to_cv_mat(const arma::Mat<T>& arma_mat_in,cv::Mat_<T>& cv_mat_out)
    {
        cv::transpose(cv::Mat_<T>(static_cast<int>(arma_mat_in.n_cols),
                                  static_cast<int>(arma_mat_in.n_rows),
                                  const_cast<T*>(arma_mat_in.memptr())),
                      cv_mat_out);
    };
    

    此代码可以运行:

    std::cout << "Testing arma::mat<->cv::Mat  <double>:" << std::endl;
    {
        arma::Mat<double> A(3,2);
        A << 1 << 2 << arma::endr
          << 3 << 4 << arma::endr
          << 5 << 6 << arma::endr;
        cv::Mat_<double> cv_A(3,2);
        M_math::Arma_mat_to_cv_mat<double>(A, cv_A);
        std::cout << "Arma_mat_to_cv_mat<double>" << std::endl;
        std::cout << A << std::endl;
        std::cout << cv_A << std::endl;
        std::cout << "Cv_mat_to_arma_mat<double>" << std::endl;
        M_math::Cv_mat_to_arma_mat<double>(cv_A, A);
        std::cout << cv_A << std::endl;
        std::cout << A << std::endl;
    }
    std::cout << "Now <float>" << std::endl;
    {
        arma::Mat<float> A(3,2);
        A << 1 << 2 << arma::endr
          << 3 << 4 << arma::endr
          << 5 << 6 << arma::endr;
        cv::Mat_<float> cv_A(3,2);
        M_math::Arma_mat_to_cv_mat<float>(A, cv_A);
        std::cout << "Arma_mat_to_cv_mat<float>" << std::endl;
        std::cout << A << std::endl;
        std::cout << cv_A << std::endl;
        std::cout << "Cv_mat_to_arma_mat<float>" << std::endl;
        M_math::Cv_mat_to_arma_mat<float>(cv_A, A);
        std::cout << cv_A << std::endl;
        std::cout << A << std::endl;
    }
    

    我的进一步问题是:

    1. 知道我做错了什么吗?这似乎是 VC10 比 g++ 更宽松的情况,但是如果我想继续使用 g++ 的第一个(更好的)版本,我错过了什么?

    2. 在Cv_mat_to_arma_mat(...) 中是否有任何建议可以在不创建临时文件的情况下解决行主要顺序与行顺序问题? cv_mat_in.t() 不会改变cv_mat_in 中的内存指针,它只是一个cv::MatExpr。

    3. 如果对这些功能的风格、安全性或性能提出任何批评,我们将不胜感激。当然,它们不适用于拥有多个频道的cv::Mat。

    【讨论】:

    • 您最好的选择是将矩阵元素从 OpenCV 显式复制到 Armadillo(反之亦然),同时考虑到行和列需要翻转。为了避免创建临时变量并提高效率,我建议避免在 OpenCV 或 Armadillo 中使用转置操作。
    猜你喜欢
    • 2020-02-09
    • 2015-01-14
    • 1970-01-01
    • 2012-12-29
    • 2014-05-07
    • 2011-06-07
    • 2016-04-13
    • 2011-10-23
    • 1970-01-01
    相关资源
    最近更新 更多