Я могу ответить, как это сделать на VC10 и g++, но мне еще предстоит решить несколько вопросов. Я новичок в написании шаблонных функций. Часто необходимо преобразовывать матричные объекты cv::Mat
и arma::mat
, так как Armadillo имеет более полные возможности линейной алгебры. 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;
}
Мои дальнейшие вопросы:
Любая идея, что я делаю неправильно? Кажется, это тот случай, когда VC10 более либерален, чем g++, но что мне не хватает, если я хочу продолжать использовать первую (более приятную) версию с g++?
В Cv_mat_to_arma_mat(...)
есть ли какие-либо предложения, чтобы обойти проблему порядка строк и порядка строк без создания временного? cv_mat_in.t()
не изменяет указатель внутренней памяти в cv_mat_in
, это просто cv::MatExpr
.
Будем признательны за любую критику стиля, безопасности или производительности этих функций. Конечно, они не будут работать с cv::Mat
, имеющими более одного канала.
person
Patrick K
schedule
23.10.2014