Dalia Shouman
Dalia Shouman

Reputation: 87

Convert CV::Mat To Arma::mat

I try to convert form matrix in Opencv to matrix in armadillo

I found this func in this link

but when I try to call it give me error :

  1. error C2783: 'arma::Mat cvMat2armaMat(cv::Mat &)' : could not deduce template argument for 'T3'
  2. IntelliSense: no instance of function template "cvMat2armaMat" matches the argument list

This is function :

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

}

This is function calling ( the error appear when I call func )

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

arma::mat singleImage = cvMat2armaMat (CurrentImage);

what should I do ?

Upvotes: 3

Views: 2879

Answers (2)

Patrick K
Patrick K

Reputation: 351

I can answer how to do this on VC10 and g++ but I still have a few issues to be resolved. I am new to writing templated functions. It is often necessary to convert between cv::Mat and arma::mat matrix objects since Armadillo has more complete Linear Algebra facilities. OpenCV stores it's matrices in row-major order while Armadillo stores it's matrices in column-major order which is one component of this problem. I have created the following templated functions that have been tested in VC10 and g++ 4.9 to work on both float and double type matrices:

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

This code can be run with:

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

My further questions are:

  1. Any idea what I am doing wrong? This seems like it is a case of VC10 being more permissive than g++ but what am I missing if I want to keep using the first (nicer) version with g++?

  2. In Cv_mat_to_arma_mat(...) are there any suggestions to get around the row-major order vs row-order issue without creating a temporary? cv_mat_in.t() does not alter the internal memory pointer in cv_mat_in, it is just a cv::MatExpr.

  3. Any criticism of the style, safety, or performance of these functions would be appreciated. Of course they will not work with cv::Mat's that have more than one channel.

Upvotes: 2

Adi Shavit
Adi Shavit

Reputation: 17295

You need to specify the type of arma::mat<XXX> that cvMat2armaMat() returns.
What is armaConv?
Maybe you meant this:

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

and the call is this:

auto singleImage = cvMat2armaMat<float>(CurrentImage);

or you'll need to switch on the cv::Mat type.

Upvotes: 2

Related Questions