方便的編程技巧:MEX編程筆記(一)

C++編程相比於matlab具有更高的效率,更適用於工程上的應用。matlab比較適合做數據分析,調試方便,語言簡潔。爲了更好的利用這兩種工具,MEX混合編程是不可或缺的一項技能。本篇博客主要是記錄我自己的一個小小的混合編程實踐項目。

 

  1. 環境配置(MATLAB+Visual studio)

首先matlab需要安裝C++的編譯器,可以選擇windows 自帶的,如果你裝了visualstudio的話(安裝的時候,記得選擇C++選項以及C++相關的包),建議直接選用visual studio的。使用mex -setup 命令來爲matlab建立相關的環境。相關的博文可以參考https://blog.csdn.net/zaishuiyifangxym/article/details/81669673

                       

由於工作需要,我在C++程序中可能需要用到opencv等視覺相關的庫,所以在安裝了visual studio之後,還需要配置一下opencv的環境。這裏可以參見我的另外一篇博文:https://mp.csdn.net/postedit/84975188。同時還需要把matlab自帶的MEX文件庫包含到路徑中去:

         包含目錄:     C:\Program Files\MATLAB\R2017b\extern\include
                                C:\Program Files\MATLAB\R2017b\extern\include\win64

         庫目錄 :       C:\Program Files\MATLAB\R2017b\extern\lib\win64\microsoft

         但是,這並不算完,我們需要在創建的工程中,建立一個混編的C++文件

 

 

     2. MEX編程起步

配置好環境之後,就可以來着手編程了,其實要掌握這項技能很簡單,把握好以下兩點:

  •    MEX編程語法
  •    編譯方法

 a. MEX中用過mexFunction 代替了C++中的main函數

#include "mex.h"
#include <opencv/cv.h>
#include <opencv/cxcore.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include "stdio.h"
#include <iostream>
//nlhs是輸出的參數個數,plhs爲左邊指數指針,nrhs爲右邊輸入參數的個數,prhs爲輸入參數的指針
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
{

}

四個參數分別用來輸出和輸入數據: nlhs 輸出參數個數,plhs 輸出參數指針 (nrhs和prhs是輸入參數相關的)。

注意: 我們對輸出和輸入參數的操作都是通過指針的方式進行的。而且默認的傳遞的數據都是double類型的矩陣,矩陣不同於C語言中的按行存儲,這裏傳入的矩陣是按列來存儲的,所以訪問格式上會與我們常用的方式有所區別:

	uchar *pData = (uchar *)mxGetPr(prhs[1]);//prhs[1]是第二個輸入參數,同時強轉爲uchar

	// 複製數據
	cv::Mat im(rows, cols, CV_8U);
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			im.at<uchar>(i, j) = pData[rows*j + i];//按列訪問數據
		}
	}

常用的一些函數:

short rows = mxGetM(prhs[1]);//矩陣的行
short cols = mxGetN(prhs[1]);//矩陣的寬度
double *label= (double *)mxGetPr(prhs[0]);//獲取數據的指針


//定義輸出的變量
mwSize dim[2] = { im.cols,im.rows };//定義輸出的尺寸變量
plhs[0] = mxCreateNumericArray(2, dim, mxUINT8_CLASS, mxREAL);//創建
memcpy(mxGetPr(plhs[0]), im.data, sizeof(uchar)*im.cols*im.rows);//拷貝數據

 

b.編譯

如果沒有使用第三方庫的話,直接在matlab裏面使用mex  **.cpp就可以進行編譯了,但是比如我使用了opencv,那麼就需要自己寫一個編譯文件,包含所需要用的庫和頭文件:

cd D:\專業學習\程序代碼\mex\test\src
OpenCV_INLCUDE_DIR = '-ID:\opencv\opencv\build\include -ID:\opencv\opencv\build\include\opencv -ID:\opencv\opencv\build\include\opencv2 ';
OpenCV_LIBRARY_DIR = '-LD:\opencv\opencv\build\x64\vc12\lib -lopencv_core2413 -lopencv_imgproc2413 -lopencv_highgui2413 -lopencv_contrib2413 -lopencv_legacy2413';  
%對於庫的包含,不懂的可以看一看doc mex,裏面有寫
eval(['mex matlabcvline.cpp ' OpenCV_INLCUDE_DIR OpenCV_LIBRARY_DIR]);  

最後附上一個例程,以供自己複習

1.mex文件:

#include "mex.h"
#include "stdio.h"
#include <opencv/cv.h>
#include <opencv/cxcore.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <iostream>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[])
{
	//實現a+b
	//plhs輸出參數,prhs輸入參數
	//double *a = mxGetPr(prhs[0]);
	//double *b = mxGetPr(prhs[1]);
	//plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
	//double *c = mxGetPr(plhs[0]);
	//*c = *a + *b;
	printf("hello my first mex.cpp\n");
	cv::VideoCapture cam(0);
	cv::Mat im;
	cam >> im;
	cv::imshow("im", im);
	cv::waitKey(1);
	//cam.release();
}

2. 編譯文件

cd D:\專業學習\程序代碼\mex\test\src
OpenCV_INLCUDE_DIR = '-ID:\opencv\opencv\build\include -ID:\opencv\opencv\build\include\opencv -ID:\opencv\opencv\build\include\opencv2 ';
OpenCV_LIBRARY_DIR = '-LD:\opencv\opencv\build\x64\vc12\lib -lopencv_core2413 -lopencv_imgproc2413 -lopencv_highgui2413 -lopencv_contrib2413 -lopencv_legacy2413';  
%對於庫的包含,不懂的可以看一看doc mex,裏面有寫
eval(['mex test.cpp ' OpenCV_INLCUDE_DIR OpenCV_LIBRARY_DIR]);  

3. matlab調用文件

clc;
clearvars;
close all;
addpath('D:\專業學習\程序代碼\mex\test\src\');%mex文件
while 1 
test;
end

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章