轻松将 OpenCV C++变量发送到 Matlab 的分步指南

A step by step guide to easily send OpenCV C++ variables to Matlab

本文关键字:Matlab OpenCV C++ 变量      更新时间:2023-10-16

我希望能够将任何OpenCV变量发送到Matlab,以便以舒适的方式绘制图形和计算统计数据。

我知道我必须使用 Matlab Engine,但是关于如何使其从代码的任何部分访问,或者关于从 CV::Mat 转换为 Matlab 数组的函数,或者如何处理列主和行大在这种特定情况下,网络上几乎没有帮助。

我认为OpenCV-to-Matlab的分步过程将非常有趣,因为OpenCV正变得非常流行,并且Matlab对调试有很大帮助。

逐步将数据从 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( 需要矩阵实验室 )

INCLUDE_DIRECTORIES( ${MATLAB_INCLUDE_DIR})

CMake 将为您设置路径并链接所需的库。通过使用环境变量,可以使项目独立于用户。这就是我总是使用CMake的原因。

2.- Matlab 引擎唯一实例的单例模板。

从代码的任何部分调用 Matlab 引擎的一种非常舒适的方法是创建一个 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);
}