Пошаговое руководство по простой отправке переменных OpenCV C++ в Matlab

Я хочу иметь возможность отправлять любые переменные OpenCV в Matlab, чтобы строить графики и рассчитывать статистику удобным способом.

Я знаю, что должен использовать Matlab Engine, но в Интернете мало информации о том, как сделать его доступным из любой части кода, или о функциях, конвертирующих из массивов CV::Mat в Matlab, или о том, как работать со столбцами. -майор и мажор в этом конкретном случае.

Я думаю, что пошаговая процедура OpenCV-to-Matlab была бы очень интересной, поскольку OpenCV становится действительно популярным, а Matlab очень помогает для отладки.

1 ответ

Решение

Пошаговая отправка данных из OpenCV в Matlab

1.- Включение и связывание библиотек

Необходимые заголовки для работы с Matlab Engine - это "engine.h" и "mex.h". Путь включения будет примерно таким:

c: \ Program Files (x86 \ MATLAB \ R2010a \ extern \ include)

В дополнительные зависимости вы должны добавить: libeng.lib, libmex.lib и libmx.lib.

Самый простой способ настроить проект - использовать CMake, так как вам просто нужно написать строки

find_package(требуется Matlab)

INCLUDE_DIRECTORIES ($ {MATLAB_INCLUDE_DIR})

CMake установит пути для вас и свяжет необходимые библиотеки. Используя переменные окружения, вы делаете проект независимым от пользователя. Вот почему я всегда использую CMake.

2.- Шаблон Singleton для уникального экземпляра Matlab Engine.

Действительно удобный способ вызова Matlab Engine из любой части кода - это создание шаблона Singleton. Например, вы можете создать "matlabSingleton.h" и написать что-то вроде этого.

#include "engine.h";
#include "mex.h";

class MatlabWrapper
{
private:
    static MatlabWrapper *_theInstance;     ///< Private instance of the class
    MatlabWrapper(){}               ///< Private Constructor
    static Engine *eng; 
public:
        static MatlabWrapper *getInstance()         ///< Get Instance public method
    {
        if(!_theInstance) _theInstance = new MatlabWrapper();   // If NULL, create it
        return _theInstance;                    
    }
public:
        static void openEngine();
        void initializeVariable(const string vName) const;
        // ... other functions ...
};

Тогда в "matlabSingleton.cpp" вы должны написать

#include "matlabSingleton.h"

MatlabWrapper *MatlabWrapper::_theInstance = NULL;  ///< Initialize instance as NULL    
Engine *MatlabWrapper::eng=NULL;

void MatlabWrapper::openEngine()
{
    if (!(eng = engOpen(NULL))) 
    {
        cerr << "Can't start MATLAB engine" << endl;
        exit(-1);
    }       
}
void MatlabWrapper::initializeVariable(const string vName) const
{
    string command = vName + "=0";
    engEvalString(eng, command.c_str());
}

3.- Использование движка Matlab из вашего основного кода.

Есть много способов сделать это, но я обычно определяю функцию initializeMatlab() где я инициализирую переменные (переменные Matlab), я буду позже использовать. Вам не нужно создавать класс MatlabWrapper, потому что при первом вызове getInstance() он будет создан. В следующий раз, когда вы вызовете getInstance, он будет просто возвращен. Вот для чего синглетон.

void initializeMatlab(){
   MatlabWrapper::getInstance()->initializeVariable("whatever1"); //class is created
   MatlabWrapper::getInstance()->initializeVariable("whatever2"); //instance of the class returned
}

4.- Отправка матрицы OpenCV в Matlab

На этом я и столкнулся с большими трудностями. Это простая функция просто для отправки матрицы в Matlab для пошаговой отладки. Он перезаписывается каждый раз.

void MatlabWrapper::cvLoadMatrixToMatlab(const Mat& m, const string name)
{
    int rows=m.rows;
    int cols=m.cols;        

    string text;
    mxArray *T=mxCreateDoubleMatrix(cols, rows, mxREAL);          

    double *buffer=(double*)mxGetPr(T);
    for(int i=0; i<rows; i++){    
        for(int j=0; j<cols; j++){
            buffer[i*(cols)+j]= (double)m.at<float>(i,j);      
        }
    }   
    engPutVariable(eng, name.c_str(), T);
    text = name + "=" + name + "'";                    // Column major to row major
    engEvalString(eng, text.c_str());
    mxDestroyArray(T);
}
Другие вопросы по тегам