使用Matlab的编译MEX函数,对含有OpenCV的CPP代码进行编译

》程序运行环境:

XCODE_DIR : /Applications/Xcode.app/Contents/Developer

XCRUN_DIR : /usr/bin

XCODE_AGREED_VERSION : 10.1

ISYSROOT : /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk

SDKVER : 10.14

CLANG_VERSION : 10.0.0

MATLABROOT : /Applications/MATLAB_R2019b.app

ARCH : maci64

简要信息:XCode 10.1; Matlab 2019b; Clang: 10.0.0;macOS High Sierra

》使用Matlab的编译MEX函数,对含有OpenCVCPP代码进行编译,并调用。

》含有OpenCV的CPP代码normxcorr2_mex.cpp,内容如下:

#include "mex.h"
#include "cv_src/cv.h"

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <ctype.h>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {

	int i, j, oi, oj, k;

	int imw, imh;
	int tpw, tph;
	int resw, resh;

	int outw, outh; // real size of output (taking into account 'shape')
	int offw, offh;

	double* im;
	double* tp;
	double* res;

	IplImage* cvIm;
	IplImage* cvTp;
	IplImage* cvRes;

	int shapeTypeCharSize = 6;
	char* shapeTypeChar;
	int shapeType = 1; 
	/* 1, full
	   2, valid
	   3, same
	   */

	float* cvImP;
	float* cvTpP;
	float* cvResP;

	if( nrhs < 2 ) {
		mexErrMsgTxt("result = normxcorr2Mex(TEMPLATE, IMAGE)");
	} else if( !( mxIsDouble(prhs[0])&&mxIsDouble(prhs[1])) ) {
		mexErrMsgTxt("IMAGE and TEMPLATE must be of type double");
	} else if( nrhs > 2 && !mxIsChar(prhs[2]) ) {
		mexErrMsgTxt("SHAPE parameter must be a character string");
	}

	shapeTypeChar = (char*)malloc(shapeTypeCharSize);
	if( nrhs>2 ) {
		mxGetString( prhs[2], shapeTypeChar, shapeTypeCharSize );
		for( int ci=0; ci<strlen(shapeTypeChar); ci++ )
			shapeTypeChar[ci] = tolower(shapeTypeChar[ci]);

		if( !strcmp(shapeTypeChar, "full") )
			shapeType = 1;
		else if( !strcmp(shapeTypeChar, "valid") )
			shapeType = 2;
		else if( !strcmp(shapeTypeChar, "same") )
			shapeType = 3;
		else
			shapeType = 0;
	}

	free(shapeTypeChar);
	if( !shapeType )
		mexErrMsgTxt("unknown shape type");

	im = mxGetPr(prhs[1]);
	imw = mxGetN(prhs[1]);
	imh = mxGetM(prhs[1]);

	tp = mxGetPr(prhs[0]);
	tpw = mxGetN(prhs[0]);
	tph = mxGetM(prhs[0]);

	resw = imw-tpw+1;
	resh = imh-tph+1;

	if( resw<=0 || resh<=0 ) {
		mexErrMsgTxt("size(image) < size(template)");
	} 

	cvIm = cvCreateImage(cvSize(imw,imh), IPL_DEPTH_32F, 1);
	cvTp = cvCreateImage(cvSize(tpw,tph), IPL_DEPTH_32F, 1);
	cvRes = cvCreateImage(cvSize(resw,resh), IPL_DEPTH_32F, 1);

	cvImP = (float*)cvIm->imageData;
	cvTpP = (float*)cvTp->imageData;
	cvResP = (float*)cvRes->imageData;

	if( shapeType==1 ) { //full
		outw = imw+tpw-1;
		outh = imh+tph-1;
		offw = tpw-1;
		offh = tph-1;
	} else if( shapeType==2 ) { //valid
		outw = resw;
		outh = resh;
		offw = 0;
		offh = 0;
	} else if( shapeType==3 ) { // same
		outw = imw;
		outh = imh;
		offw = ceil((float)(tpw-1)/2.0f);
		offh = ceil((float)(tph-1)/2.0f);
	}

	plhs[0] = mxCreateDoubleMatrix( outh, outw, mxREAL );
	res = mxGetPr(plhs[0]);

	// we don't need to worry about alignment since we're using 32f

	k = 0;
	for( i=0; i<imw; i++ ) {
		for( j=0; j<imh; j++ ) {
			cvImP[ j*imw+i ] = im[ k ];
			k++;
		}
	}

	k = 0;
	for( i=0; i<tpw; i++ ) {
		for( j=0; j<tph; j++ ) {
			cvTpP[ j*tpw+i ] = tp[ k ];
			k++;
		}
	}

	cvMatchTemplate( cvIm, cvTp, cvRes, CV_TM_CCOEFF_NORMED );

	for( i=0, oi=offw; i<resw; i++, oi++ ) {
		for( j=0, oj=offh; j<resh; j++, oj++ ) {
			res[ oi*outh + oj ] = cvResP[ j*resw + i ];
		}
	}

	cvReleaseImage(&cvIm);
	cvReleaseImage(&cvTp);
	cvReleaseImage(&cvRes);
}

》在Matlab的命令行中使用mex normxcorr2_mex.cpp,程序出现以下错误:

Undefined symbols for architecture x86_64:

  "_cvCreateImage", referenced from:

      _mexFunction in normxcorr2_mex.o

  "_cvMatchTemplate", referenced from:

      _mexFunction in normxcorr2_mex.o

  "_cvReleaseImage", referenced from:

      _mexFunction in normxcorr2_mex.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

》解决方案:

基于参考文献【1】,

在Matlab的命令行中,输入OpenCV源代码编译后结果的Include路径,以及LIB路径,然后执行mex相关的命令,最终输出文件名以.mexmaci64结束的文件。

(1) OpenCV_INLCUDE_DIR = '-I/usr/local/Cellar/opencv@3/3.4.5_5/include -I/usr/local/Cellar/opencv@3/3.4.5_5/include/opencv -I/usr/local/Cellar/opencv@3/3.4.5_5/include/opencv2 ‘;

(2) OpenCV_LIBRARY_DIR = '-L/usr/local/Cellar/opencv@3/3.4.5_5/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_contrib -lopencv_legacy'; 

(3)eval(['mex mex normxcorr2_mex.cpp' OpenCV_INLCUDE_DIR OpenCV_LIBRARY_DIR]);  

对于Windows平台,OpenCV源代码编译后的Include路径,LIB路径,请参考文献【2】,同时文献【2】也对-I, -L参数进行了相关的解释,具体可以自己去查阅相关资料。

》由于上述过程是基于OpenCV源代码编译后的结果进行配置的,本文在这里简单介绍一下macOS, Linux环境下如何编译penCV源代码或者直接获取编译后的结果。同时还需要注意的是,根据自己的需求选择对应版本的OpenCV源代码进行编译。

1)对于macOS的用户来说,最简单的方式是在终端中输入brew install opencv@3 获取编译后的对应版本的opencv代码,(如果没有安装brew, 可以自己搜索mac环境下如何安装brew)。安装过程结束后,命令行会提醒用户该package被存放哪一个目录。

  • 一般是存放

然后通过cd 操作,获取对应LID, INCLUDE文件夹的路径。

(2)对于Linux, Unbuntu的用户,可以参考文献【3】进行OpenCV的安装与编译。

 

参考文献

【1】https://blog.csdn.net/kernlen/article/details/52513205

【2】https://blog.csdn.net/shaoxiaohu1/article/details/37744309

【3】https://github.com/kyamagu/mexopencv/wiki/Installation-%28Linux%2C-MATLAB%2C-OpenCV-3%29

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页