Пошаговое руководство в формате OpenCV на C++ переменные в MATLAB
Я хочу иметь возможность отправлять любые переменные OpenCV в Matlab для построения графиков и вычисления статистики удобным способом.
Я знаю, что должен использовать движок Matlab, но в интернете мало информации о том, как сделать его доступным из любой части кода, или о функциях для преобразования из CV::Mat в массивы Matlab, или о том, как работать с основными столбцами и строками в этом конкретном случае.
Я думаю, что пошаговая процедура OpenCV-to-Matlab было бы очень интересно, так как OpenCV становится действительно популярным, и Matlab очень помогает в отладке.
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); }