C/C++与Matlab混合编程
2016-05-15 20:56
489 查看
由于实验室项目遗留问题,可能为了图matlab绘图方便,前面的开发人员在C++核心代码外加了一层matlab外壳,在matlab里调用C++方法,并使用matlab绘图显示。当我接手这份代码之后,在Windows上调试发现了几个难以忍受的问题,
1. matlab调用之前必须将c++代码编译成二进制文件,如此一来在matlab里就没法调试,不得不使用Visual Studio的附加进程调试,需要频繁来回切换VS和maltab;
2. 使用附加进程调试时如果C++程序崩溃,导致matlab必须重启,而matlab重启速度之慢无法忍;
3. 全速运行起来速度之慢无法忍。
综上所述,决定将代码全部移植到C++下。综合考虑,移植到C++下,可能存在以下两个问题:图像读取与转换和计算结果可视化。
下载OpenCV2.4.9 for Windows,解压到OPENCV_ROOT(自定义路径);
在VS2012里指定头文件路径为:
从
在代码中添加如下代码表明用到的库文件
加载和显示图像
创建和MATLAB版本一致的C++工程,如,我的MATLAB是x64的,就创建x64的C++工程,这样才能保证调用的动态库版本正确;
在VS2012中添加MATLAB的头文件路径,如:
在代码中调用MATLAB引擎函数,为了使用方便,我对部分引擎函数做了一些封装,如下:
4.在main函数中实例化引擎类并调用引擎方法:
1. matlab调用之前必须将c++代码编译成二进制文件,如此一来在matlab里就没法调试,不得不使用Visual Studio的附加进程调试,需要频繁来回切换VS和maltab;
2. 使用附加进程调试时如果C++程序崩溃,导致matlab必须重启,而matlab重启速度之慢无法忍;
3. 全速运行起来速度之慢无法忍。
综上所述,决定将代码全部移植到C++下。综合考虑,移植到C++下,可能存在以下两个问题:图像读取与转换和计算结果可视化。
图像加载与转换
项目是有关图像处理的,matlab提供非常便捷的图像转换和处理库,在C++下没有这些API,也不可能自己从头实现这些基础功能,自然而然选择了OpenCV这样的第三方库。下载OpenCV2.4.9 for Windows,解压到OPENCV_ROOT(自定义路径);
在VS2012里指定头文件路径为:
OPENCV_ROOT/build/include;库文件路径:
OPENCV_ROOT/build/x64/vc11/lib;
从
OPENCV_ROOT/build/x64/vc11/bin拷贝
opencv_core249d.dll,
opencv_core249.dll,
opencv_highgui249d.dll和
opencv_highgui249.dll到VS工程目录(工程为x64,x86工程);
在代码中添加如下代码表明用到的库文件
#ifdef _DUBUG #pragma comment(lib, "opencv_core249d.lib") #pragma comment(lib, "opencv_highgui249d.lib") #else #pragma comment(lib, "opencv_core249.lib") #pragma comment(lib, "opencv_highgui249.lib") #endif
加载和显示图像
#include <opencv2\highgui\highgui.hpp> int main(void){ cv::Mat img = cv::imread("test_image.jpg", CV_LOAD_IMAGE_GRAYSCALE); cv::namedWindow("imageWindow"); cv::imshow("imageWindow", img); cv::destroyWindow("imageWindow"); return 0; }
可视化
项目最终有可视化的需求,而用C++做可视化成本太高,MATLAB在这方面独特的优势。在调试阶段应该使用尽可能方便的方法验证算法,于是决定在C++中调用MATLAB引擎绘图。MATLAB引擎函数库是MATLAB提供引擎方式接口的一系列程序的集合,它允许用户用自己的C/C++语言或FORTRAN语言应用程序中对MATLAB进行调用。engine.h头文件中定义了9个引擎函数。在VS2012里调用MATLAB引擎操作方式如下:
创建和MATLAB版本一致的C++工程,如,我的MATLAB是x64的,就创建x64的C++工程,这样才能保证调用的动态库版本正确;
在VS2012中添加MATLAB的头文件路径,如:
C:\Program Files\MATLAB\R2014a\extern\include;添加库文件路径,如:
C:\Program Files\MATLAB\R2014a\extern\lib\win64\microsoft,添加可执行文件路径,如:
C:\Program Files\MATLAB\R2014a\bin\win64;
在代码中调用MATLAB引擎函数,为了使用方便,我对部分引擎函数做了一些封装,如下:
/* * MatlabEngine.h * this file is a C++ wrap of some MATLAB engine methods. * it depends on the MATLAB installed on you machine. * DATE: 2016.05.15 * AUTHOR: Lai Shaofa * EMAIL: laishaofa@gmail.com */ # ifndef _MATLAB_ENGINE_H_ # define _MATLAB_ENGINE_H_ #include <stdio.h> #include "engine.h" #pragma comment(lib, "libeng.lib") #pragma comment(lib, "libmx.lib") #define MAX_BUFFFER_SIZE (1024) class MatlabEngine { private: Engine *ep; char buffer[MAX_BUFFFER_SIZE]; public: /* * constructor: open matlab engine and set engine input/output buffer */ MatlabEngine(){ if ((ep = engOpen("")) == NULL) { fprintf(stderr, "\nCan't start MATLAB engine\n"); exit(1); } engOutputBuffer(ep, buffer, MAX_BUFFFER_SIZE); } /* * destructor: close matlab engine */ ~MatlabEngine() { engClose(ep); } /* * matCreate: create a matrix * @row: row of matrix * @col: column of matrix * NOTE: remember to call @matDestory to avoid memory leak */ mxArray* matCreate(const int32_t row, const int32_t col) { assert(row>0 && col>0); return mxCreateDoubleMatrix(row, col, mxREAL); } /* * @matDestroy: destroy a matrix to release memory * @mat: matrix to be destroyed. */ void matDestroy(mxArray* mat) { assert(mat!=NULL); mxDestroyArray(mat); mat = NULL; } /* * matPutVariable: put a variable to matlab engine with the name @matName * @matName: name of variable,it used by matlab engine to identify the @mat * @mat: matrix to be put * @src: c/c++ source data pointer * @size: size of source data */ void matPutVariable(const char* matName, const mxArray* mat, const void* src, const size_t size) { assert(matName!=NULL); assert(mat!=NULL); assert(src!=NULL && size>0); memcpy((void*)mxGetPr(mat), src, size); engPutVariable(ep, matName, mat); } /* * @matExecute: execute a matlab command in string format. * @cmd: command string. */ void matExecute(const char * cmd) { assert(cmd != NULL); engEvalString(ep, cmd); } char* matGetOutput() { return buffer; } };
4.在main函数中实例化引擎类并调用引擎方法:
#include <iostream> #include "MatlabEngine.h" using namespace std; int main(void){ MatlabEngine engine; double _x[] = { 1, 2, 3, 4, 5 }; double _y[] = {1, 4, 9, 16, 25}; mxArray* x = engine.matCreate(1, 5); mxArray* y = engine.matCreate(1, 5); engine.matPutVariable("x", x, _x, sizeof(_x)); engine.matPutVariable("y", y, _y, sizeof(_y)); engine.matExecute("plot(x, y, '-*b', 'linewidth', 1)"); engine.matExecute("grid on, axis equal"); engine.matDestroy(x); engine.matDestroy(y); return 0; }
相关文章推荐
- 解决Matlab: Invalid MEX-file
- Matlab导出eps或jpg图片的四种方法
- utilities(matlab)—— 合成数据(synthesis data)
- matlab 矢量化编程(二)—— 使用 meshgrid
- 在MATLAB下调试Caffe
- Matlab Tricks(九)—— 矩阵行/列的增广(删除)
- MATLAB中的点运算
- Matlab分析音频
- matlab中字符串支持latex
- matlab 画图的坐标设置
- MATLAB画向量图
- MATLAB画ROC曲线,及计算AUC值
- utilities(matlab)—— 图像加噪
- utilities(matlab)—— PSNR 值的计算
- 基于MATLAB的音频信号处理技术实现
- matlab、opencv护眼模式之黑色主题
- Matlab Tricks( 八)—— 将 pgm 格式文件转换为 png 格式
- MatLab2012b/MatLab2013b分类器大全(svm,knn,随机森林等)
- utilities(matlab)—— ZCA 白化
- Matlab读取excel数据,并绘图生成exe可执行文件