Конвертировать CV::Mat в Arma::mat

Я пытаюсь преобразовать матрицу формы в Opencv в матрицу броненосца.

Я нашел эту функцию в эта ссылка

но когда я пытаюсь вызвать его, выдает ошибку:

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

Что я должен делать ?


person Dalia Shouman    schedule 30.09.2014    source источник


Ответы (2)


Вам нужно указать тип arma::mat<XXX>, который возвращает cvMat2armaMat().
Что такое 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);

или вам нужно будет switch на типе cv::Mat.

person Adi Shavit    schedule 30.09.2014
comment
Большое спасибо, я сделал ваши предложения, все старые ошибки исчезли, но теперь эта ошибка появляется в строке возврата внутри функции: ошибка C2665: 'arma::Mat‹eT›::Mat': ни одна из 18 перегрузок не может преобразовать все типы аргументов любая помощь ? - person Dalia Shouman; 30.09.2014
comment
Что такое arma::Mat<eT>::Mat? Разве это не должно быть arma::Mat<eT>? - person Adi Shavit; 30.09.2014
comment
См. документацию по классу Mat Armadillo, особенно по расширенные конструкторы. Если вы создаете объект arma::Mat<float>, убедитесь, что cvMatIn.data на самом деле является указателем на массив чисел с плавающей запятой (т.е. float*). Если вы хотите выполнить преобразование между типами, вам потребуется вручную написать цикл for для копирования элементов из объекта cvMatIn в объект arma::Mat. - person mtall; 30.09.2014
comment
@AdiShavit Это последнее, что я делаю шаблон ‹code› класс T3› arma::Mat ‹T3› cvMat2armaMat(cv::Mat & cvMatIn) { return arma::Mat‹T3› (cvMatIn.data, cvMatIn.rows , cvMatIn.cols, false); } ‹code› cv::Mat CurrentImage = imread(путь, 0); auto singleImage = cvMat2armaMat‹float› (CurrentImage); ошибка появляется в строке возврата в func error: ошибка C2665: 'arma::Mat‹eT›::Mat': ни одна из 18 перегрузок не может преобразовать все типы аргументов. :Mat‹eT›::Mat ??!!!! - person Dalia Shouman; 30.09.2014

Я могу ответить, как это сделать на 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;
}

Мои дальнейшие вопросы:

  1. Любая идея, что я делаю неправильно? Кажется, это тот случай, когда VC10 более либерален, чем g++, но что мне не хватает, если я хочу продолжать использовать первую (более приятную) версию с g++?

  2. В Cv_mat_to_arma_mat(...) есть ли какие-либо предложения, чтобы обойти проблему порядка строк и порядка строк без создания временного? cv_mat_in.t() не изменяет указатель внутренней памяти в cv_mat_in, это просто cv::MatExpr.

  3. Будем признательны за любую критику стиля, безопасности или производительности этих функций. Конечно, они не будут работать с cv::Mat, имеющими более одного канала.

person Patrick K    schedule 23.10.2014
comment
Лучше всего явно скопировать матричные элементы из OpenCV в Armadillo (и наоборот), принимая во внимание, что строки и столбцы необходимо перевернуть. Чтобы избежать создания временных файлов и повысить эффективность, я рекомендую избегать использования операций транспонирования ни в OpenCV, ни в Armadillo. - person mtall; 24.10.2014