将CV::Mat转换为Arma::mat

3

我尝试将OpenCV中的矩阵转换为Armadillo中的矩阵。

我在这个链接中找到了这个函数。

但是当我尝试调用它时,出现了以下错误:

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

}

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

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

arma::mat singleImage = cvMat2armaMat (CurrentImage);

what should I do ?

2个回答

2

我可以回答如何在VC10和g ++上完成此操作,但我仍有一些问题需要解决。我是写模板函数的新手。通常需要在cv :: Matarma :: mat矩阵对象之间进行转换,因为Armadillo具有更完整的线性代数功能。OpenCV将其矩阵存储在行主序中,而Armadillo将其矩阵存储在列主序中,这是问题的一个组成部分。我已创建了以下模板函数,在VC10和g ++ 4.9上进行了测试,可用于floatdouble类型的矩阵:

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


1
你最好的选择是将矩阵元素从OpenCV显式地复制到Armadillo(反之亦然),同时考虑到需要翻转行和列。为了避免创建临时变量并提高效率,我建议在OpenCV或Armadillo中都避免使用转置操作。 - mtall

2

您需要指定 cvMat2armaMat() 返回的 arma::mat<XXX> 的类型。
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


非常感谢,我采纳了您的建议,所有旧错误都已经消失了。但是现在,在函数返回行内出现了以下错误:error C2665: 'arma::Mat<eT>::Mat' : none of the 18 overloads could convert all the argument types请问有什么帮助吗? - Dalia Shouman
arma::Mat<eT>::Mat是什么?难道不应该是arma::Mat<eT>吗? - Adi Shavit
请查看Armadillo的Mat类文档,特别是高级构造函数。如果您正在生成一个arma::Mat<float>对象,请确保cvMatIn.data实际上是指向浮点数数组(即float*)的指针。如果您想在不同类型之间进行转换,您需要编写一个手动的for循环来将元素从cvMatIn复制到arma::Mat对象中。 - mtall
@AdiShavit 这是我最后做的事情<code> template<class T3> arma::Mat <T3> cvMat2armaMat(cv::Mat & cvMatIn) { return arma::Mat<T3>(cvMatIn.data, cvMatIn.rows, cvMatIn.cols,false); } <code> cv::Mat CurrentImage = imread(path, 0); auto singleImage = cvMat2armaMat<float>(CurrentImage);在函数的返回行出现错误 错误信息如下:error C2665: 'arma::Mat::Mat' : none of the 18 overloads could convert all the argument types我不知道为什么VS编译器会说它是arma :: Mat <eT> :: Mat ?? !!!! - Dalia Shouman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接