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


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

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

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

1 3

1 ответ:

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

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

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

C:\Program файлы (x86\MATLAB\R2010a\extern\include)

В дополнительных зависимостях следует добавить: libeng.Либ, либмекс.lib и libmx.lib .

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

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

INCLUDE_DIRECTORIES (${MATLAB_INCLUDE_DIR})

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

2.- Шаблон синглтона для уникального экземпляра Движок Matlab.

Действительно удобный способ вызова движка Matlab из любой части кода-это создание Одноэлементного шаблона. Вы можете создать " 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);
}