matlab opencv C++ mex
2016-06-16 16:10
453 查看
前言:前面写过一篇 “Matlab OpenCV混合编程” 提到了三种方法。其他两种方法用起来比较方便,但速度就上不去,至少在我的电脑跑的感觉是这样。这一个星期一直在用mex cpp的方法,可参考了网上很多博客,但按照他们的方法来,并修改相应的路径就是出不来结果。现在记录下遇到的问题和“解决方法”,但也有一些想不明白的地方。
VS2013
matlab2015a 64位
opencv2.4.9
参考连接去配置就好,注意改成自己相应的地址跟版本号,链接中提到,如果找不到opencv_core249d.dll等类似的文件,就重启下电脑,或者按照链接中的第六步去做。
如果要用相对路径的话,可以参考链接2
问题:找不到各种头文件,如“highgui.hpp”
解决思路和方法:
一般加入的都是这三个路径
...\opencv\build\include
...\opencv\build\include\opencv
...\opencv\build\include\opencv2
注意看opencv和opencv2下面的头文件
如果引用头文件 “cv.h”, "highgui.h", "cxcore.h"等都没问题,因为这些 ".h" 的头文件直接就在opencv中,但如果直接#include "highgui.hpp" 则会出现找不到头文件的问题
因为“highgui.hpp” 文件是在opencv2中highgui文件夹下面,这时候应该改成#include "opencv2\highgui\highgui.hpp" 。
其他相应的头文件而根据上面的例子去改吧。
参考文献:
http://blog.csdn.net/poem_qianmo/article/details/19809337
http://blog.csdn.net/ggz631047367/article/details/37914681
b)另外,有不少教程说修改mexopt.bat文件,但新版本matlab没有这个文件了,虽然也可以通过在matlab的命令窗口执行 “fullfile(prefdir,'mexopts.bat')”命令来找到mexopt.bat的路径,但被另外一个文件替代了。这个路径是被隐藏起来的。
c)后面参考了其他的博客等,都能编译出文件来,但总是出不来结果。后面看到文献[3] ,虽然也出不来结果,但猜测了一下,再修改就没问题了。下面直接给出make文件的写法再来说明自己遇到的坑
% This cppmake.m is for MATLAB
% Function: compile c++ files which rely on OpenCV for Matlab using mex
% Matlab and C++ mixed programming(dependent on opencv library)
% First step(before exeuting this program): use "mex -setup" to choose your c/c++ compiler
clear all;
clc;
% Get the architecture of this computer
is_64bit = strcmp(computer,'MACI64') || strcmp(computer,'GLNXA64') || strcmp(computer,'PCWIN64');
%----------------------------------------------------------------------------------------------
%% The configuration of compiler
% You need to modify this configuration according to your own path of OpenCV
% Notice: if your system is 64bit, your OpenCV must be 64bit!
out_dir='./';
CPPFLAGS = ' -O -DNDEBUG -I.\ -IC:\opencv\build\include -IC:\opencv\build\include\opencv -IC:\opencv\build\include\opencv2'; % your OpenCV "include" path
LDFLAGS = ' -LC:\opencv\build\x64\vc12\lib'; % your OpenCV "lib" path
LIBS = ' -lopencv_calib3d249d -lopencv_contrib249d -lopencv_core249d -lopencv_features2d249d -lopencv_flann249d -lopencv_gpu249d -lopencv_highgui249d -lopencv_imgproc249d -lopencv_legacy249d -lopencv_ml249d -lopencv_nonfree249d -lopencv_objdetect249d -lopencv_photo249d -lopencv_stitching249d -lopencv_ts249d -lopencv_video249d -lopencv_videostab249d';
%LIBS = ' -lopencv_calib3d249 -lopencv_contrib249 -lopencv_core249 -lopencv_features2d249 -lopencv_flann249 -lopencv_gpu249 -lopencv_highgui249 -lopencv_imgproc249 -lopencv_legacy249 -lopencv_ml249 -lopencv_nonfree249 -lopencv_objdetect249 -lopencv_photo249 -lopencv_stitching249 -lopencv_ts249 -lopencv_video249 -lopencv_videostab249';
if is_64bit
CPPFLAGS = [CPPFLAGS ' -largeArrayDims'];
end
% add your files here!!
compile_files = {
%the list of your code files which need to be compiled
% 'RGB2Gray.cpp'
% 'OpenImage.cpp'
};
%----------------------------------------------------------------------------------------------
%% compiling
for k = 1 : length(compile_files)
str = compile_files{k};
fprintf('compilation of: %s\n', str);
str = [str ' -outdir ' out_dir CPPFLAGS LDFLAGS LIBS];
args = regexp(str, '\s+', 'split');
mex(args{:});
end
fprintf('Congratulations, compilation successful!!!\n');
相应的修改CPPFLAGS变量中opencv的路径
根据系统和编译器的版本修改LDFLAGS变量中的路径,说明:如果是64位系统则是x64,否则x86,vc12表示用的是VS2013
注意:这里提供了两个LIBS,可以看到一个是带d后缀的,一个是不带d后缀的,这两个都可以mex成功,不会报错,但有一个可以出来你要的结果,一个不行。很多博主都直接写不带d后缀的,直到看到文献[3] ,我的问题才迎刃而解,非常感谢!当然,你可以需要的就是不带d的。
我用的是带d后缀的那个LIBS,下面有个OpenImage.cpp的例子,如果我用不带d的,可以显示一个窗口,但里面确实灰色的,没有内容。而用带d的却可以
理解:目前还不是很确切知道原因,但猜测
a)我本来在VS中就是按照默认的采用debug的编译模式,这个可能会比较高,因为其他博主都能出来结果
b)CPPFLAGS变量中"-DNDEBUG"属性是采用debug
说明:上面的LIBS不一定需要所有的链接库,zouxy博客中就加入了几个链接库,我把LIBS修改成自己对应的opencv版本并加上d后缀,也是可以mex通过,并出来结果。但都写上去是没错的,以后也省了很多麻烦。
参考文献:
[1] http://blog.csdn.net/zouxy09/article/details/20553007
[2] http://zhidao.baidu.com/link?url=lLjCzivibkNLNYyn6Gx_oDXvnwNo7qprW02Fj_kaBmYP2XOv1oJvww_nJD4UJFMen7vIgZ5R83LYgBu6fR4BZqy3lt3NtKCQotmpNtfEC63&hideOtherAnswer=true&newAnswer=1
[3] http://www.cnblogs.com/lukylu/p/3966871.html
(a)IplImage 转化为 Mat
通过以下两种方式:
Mat mtx = iplImg;; //(1)
//Matmtx(iplImg); // IplImage* ->Mat 共享数据 //(2)
(b)Mat类转IplImage:Mat类有个IplImage成员函数
通过以下两种方式即可转化:
IplImage ipl_img(image); //(1)
//IplImage ipl_img = image; //(2)
文献2中还给出了CvMat和Mat格式的转化
(c)将CvMat类型转换为Mat类型与IplImage的转换类似,可以选择是否复制数据。Mat::Mat(const CvMat* m, bool copyData=false);(d)将Mat类型转换为CvMat类型与IplImage的转换类似,不复制数据,只创建矩阵头。例:// 假设Mat类型的imgMat图像数据存在CvMat cvMat = imgMat;
// Mat -> CvMat
参考文献:
[1] http://blog.csdn.net/lichengyu/article/details/24272349
[2] http://www.cnblogs.com/zcftech/archive/2013/04/10/3013027.html
RGB2Gray.cpp 文件:可以传递参数的例子
接下来是OpenImage.cpp文件:不需要传递参数,这里是读图片显示图片
最后是matlab编写make.m文件,以上的文件名字都可以改的
说明:只要修改相应的opencv的路径和版本,写好自己的cpp文件,放到compile_files中即可。
a) 不能读取绝对路径中的图片文件,需要在同一路径中,而VS中是可以的;
b) cpp文件中,imread不能读取图片文件,不知道是不是跟matlab中imread混淆,纯属猜测
c) 不是给定图片名参数,而是传递通过matlab读取的图像信息,需要修改程序
d) ......
系统及软件配:
windows7:64位VS2013
matlab2015a 64位
opencv2.4.9
1、路径等相关配置
这里自行搜索怎么添加 opencv 的系统路径,以及在VS配置相关路径,这里提供一个参考的链接1吧参考连接去配置就好,注意改成自己相应的地址跟版本号,链接中提到,如果找不到opencv_core249d.dll等类似的文件,就重启下电脑,或者按照链接中的第六步去做。
如果要用相对路径的话,可以参考链接2
问题:找不到各种头文件,如“highgui.hpp”
解决思路和方法:
一般加入的都是这三个路径
...\opencv\build\include
...\opencv\build\include\opencv
...\opencv\build\include\opencv2
注意看opencv和opencv2下面的头文件
如果引用头文件 “cv.h”, "highgui.h", "cxcore.h"等都没问题,因为这些 ".h" 的头文件直接就在opencv中,但如果直接#include "highgui.hpp" 则会出现找不到头文件的问题
因为“highgui.hpp” 文件是在opencv2中highgui文件夹下面,这时候应该改成#include "opencv2\highgui\highgui.hpp" 。
其他相应的头文件而根据上面的例子去改吧。
参考文献:
http://blog.csdn.net/poem_qianmo/article/details/19809337
http://blog.csdn.net/ggz631047367/article/details/37914681
2、mex
a)之前在windows编译 tld 的源程序,本来想在tld上面直接改的,发现有问题;b)另外,有不少教程说修改mexopt.bat文件,但新版本matlab没有这个文件了,虽然也可以通过在matlab的命令窗口执行 “fullfile(prefdir,'mexopts.bat')”命令来找到mexopt.bat的路径,但被另外一个文件替代了。这个路径是被隐藏起来的。
c)后面参考了其他的博客等,都能编译出文件来,但总是出不来结果。后面看到文献[3] ,虽然也出不来结果,但猜测了一下,再修改就没问题了。下面直接给出make文件的写法再来说明自己遇到的坑
% This cppmake.m is for MATLAB
% Function: compile c++ files which rely on OpenCV for Matlab using mex
% Matlab and C++ mixed programming(dependent on opencv library)
% First step(before exeuting this program): use "mex -setup" to choose your c/c++ compiler
clear all;
clc;
% Get the architecture of this computer
is_64bit = strcmp(computer,'MACI64') || strcmp(computer,'GLNXA64') || strcmp(computer,'PCWIN64');
%----------------------------------------------------------------------------------------------
%% The configuration of compiler
% You need to modify this configuration according to your own path of OpenCV
% Notice: if your system is 64bit, your OpenCV must be 64bit!
out_dir='./';
CPPFLAGS = ' -O -DNDEBUG -I.\ -IC:\opencv\build\include -IC:\opencv\build\include\opencv -IC:\opencv\build\include\opencv2'; % your OpenCV "include" path
LDFLAGS = ' -LC:\opencv\build\x64\vc12\lib'; % your OpenCV "lib" path
LIBS = ' -lopencv_calib3d249d -lopencv_contrib249d -lopencv_core249d -lopencv_features2d249d -lopencv_flann249d -lopencv_gpu249d -lopencv_highgui249d -lopencv_imgproc249d -lopencv_legacy249d -lopencv_ml249d -lopencv_nonfree249d -lopencv_objdetect249d -lopencv_photo249d -lopencv_stitching249d -lopencv_ts249d -lopencv_video249d -lopencv_videostab249d';
%LIBS = ' -lopencv_calib3d249 -lopencv_contrib249 -lopencv_core249 -lopencv_features2d249 -lopencv_flann249 -lopencv_gpu249 -lopencv_highgui249 -lopencv_imgproc249 -lopencv_legacy249 -lopencv_ml249 -lopencv_nonfree249 -lopencv_objdetect249 -lopencv_photo249 -lopencv_stitching249 -lopencv_ts249 -lopencv_video249 -lopencv_videostab249';
if is_64bit
CPPFLAGS = [CPPFLAGS ' -largeArrayDims'];
end
% add your files here!!
compile_files = {
%the list of your code files which need to be compiled
% 'RGB2Gray.cpp'
% 'OpenImage.cpp'
};
%----------------------------------------------------------------------------------------------
%% compiling
for k = 1 : length(compile_files)
str = compile_files{k};
fprintf('compilation of: %s\n', str);
str = [str ' -outdir ' out_dir CPPFLAGS LDFLAGS LIBS];
args = regexp(str, '\s+', 'split');
mex(args{:});
end
fprintf('Congratulations, compilation successful!!!\n');
相应的修改CPPFLAGS变量中opencv的路径
根据系统和编译器的版本修改LDFLAGS变量中的路径,说明:如果是64位系统则是x64,否则x86,vc12表示用的是VS2013
注意:这里提供了两个LIBS,可以看到一个是带d后缀的,一个是不带d后缀的,这两个都可以mex成功,不会报错,但有一个可以出来你要的结果,一个不行。很多博主都直接写不带d后缀的,直到看到文献[3] ,我的问题才迎刃而解,非常感谢!当然,你可以需要的就是不带d的。
我用的是带d后缀的那个LIBS,下面有个OpenImage.cpp的例子,如果我用不带d的,可以显示一个窗口,但里面确实灰色的,没有内容。而用带d的却可以
理解:目前还不是很确切知道原因,但猜测
a)我本来在VS中就是按照默认的采用debug的编译模式,这个可能会比较高,因为其他博主都能出来结果
b)CPPFLAGS变量中"-DNDEBUG"属性是采用debug
说明:上面的LIBS不一定需要所有的链接库,zouxy博客中就加入了几个链接库,我把LIBS修改成自己对应的opencv版本并加上d后缀,也是可以mex通过,并出来结果。但都写上去是没错的,以后也省了很多麻烦。
参考文献:
[1] http://blog.csdn.net/zouxy09/article/details/20553007
[2] http://zhidao.baidu.com/link?url=lLjCzivibkNLNYyn6Gx_oDXvnwNo7qprW02Fj_kaBmYP2XOv1oJvww_nJD4UJFMen7vIgZ5R83LYgBu6fR4BZqy3lt3NtKCQotmpNtfEC63&hideOtherAnswer=true&newAnswer=1
[3] http://www.cnblogs.com/lukylu/p/3966871.html
3、IplImage or Mat 和 cvLoadImage or imread
在混合编程中,可能会遇到跟我一样的问题,就是imread读取不了图片,但cvLoadImage可以。这时候为了处理方便,或者不改动其他现有的程序,可能就需要进行类型转化了。(a)IplImage 转化为 Mat
通过以下两种方式:
Mat mtx = iplImg;; //(1)
//Matmtx(iplImg); // IplImage* ->Mat 共享数据 //(2)
(b)Mat类转IplImage:Mat类有个IplImage成员函数
通过以下两种方式即可转化:
IplImage ipl_img(image); //(1)
//IplImage ipl_img = image; //(2)
文献2中还给出了CvMat和Mat格式的转化
(c)将CvMat类型转换为Mat类型与IplImage的转换类似,可以选择是否复制数据。Mat::Mat(const CvMat* m, bool copyData=false);(d)将Mat类型转换为CvMat类型与IplImage的转换类似,不复制数据,只创建矩阵头。例:// 假设Mat类型的imgMat图像数据存在CvMat cvMat = imgMat;
// Mat -> CvMat
参考文献:
[1] http://blog.csdn.net/lichengyu/article/details/24272349
[2] http://www.cnblogs.com/zcftech/archive/2013/04/10/3013027.html
4、例子
下面给出两个 cpp 程序,和相应的matlab编译文件,RGB2Gray.cpp 文件:可以传递参数的例子
// Interface: read image file name given and convert to gray and return to Matlab // Author : jeff // Date : 2016-06-16 //说明:修改至zouxy http://blog.csdn.net/zouxy09/article/details/20553007 #include "opencv2/opencv.hpp" #include "mex.h"<span style="white-space:pre"> </span>//matlab编译必要的头文件 using namespace cv; /******************************************************* Usage: [imageMatrix] = RGB2Gray('imageFile.jpeg'); Input: a image file OutPut: a matrix of image which can be read by Matlab **********************************************************/ void exit_with_help() { mexPrintf( "Usage: [imageMatrix] = DenseTrack('imageFile.jpg');\n" ); } static void fake_answer(mxArray *plhs[]) { plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL); } void RGB2Gray(char *filename, mxArray *plhs[]) { IplImage *img = cvLoadImage(filename); // read the image Mat image = img; //IplImage格式转化为Mat格式,使得下面的程序不需要修改 if(image.empty()) { mexPrintf("can't open input file %s\n", filename); fake_answer(plhs); return; } // convert it to gray format Mat gray; if (image.channels() == 3) cvtColor(image, gray, CV_RGB2GRAY); else image.copyTo(gray); // convert the result to Matlab-supported format for returning int rows = gray.rows; int cols = gray.cols; plhs[0] = mxCreateDoubleMatrix(rows, cols, mxREAL); double *imgMat; <span style="white-space:pre"> </span>imgMat = mxGetPr(plhs[0]); for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) *(imgMat + i + j * rows) = (double)gray.at<uchar>(i, j); return; } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if(nrhs == 1) { char filename[256]; mxGetString(prhs[0], filename, mxGetN(prhs[0]) + 1); if(filename == NULL) { mexPrintf("Error: filename is NULL\n"); exit_with_help(); return; } RGB2Gray(filename, plhs); } else { exit_with_help(); fake_answer(plhs); return; } }
接下来是OpenImage.cpp文件:不需要传递参数,这里是读图片显示图片
#include "opencv2\opencv.hpp" //#include <highgui.h> <span style="white-space:pre"> </span>//这个头文件跟下面的头文件任意一个都可以,highgui.h是在opencv文件夹下的,这里如果写成highgui.hpp就会找不到头文件 #include "opencv2\highgui\highgui.hpp"<span style="white-space:pre"> </span>//highgui.hpp是在这个路径下面,因为前面系统的路径加入是的opencv2,所以要通过这个方式调用下面的highgui.hpp #include <iostream> using namespace cv; #include "mex.h" void openimage() { IplImage *src = cvLoadImage("yourImageName.jpg");<span style="white-space:pre"> </span>//<span style="font-family: Arial, Helvetica, sans-serif;">//这里将yourImageName.jpg和 .cpp文件放在同一个文件夹下</span> cvNamedWindow("yourWindowName",CV_WINDOW_AUTOSIZE); cvShowImage("yourWindowName",src); cvWaitKey(0); cvDestroyWindow("yourWindowName"); cvReleaseImage(&src); } void mexFunction(int nlhs,mxArray *plhs[],int nrhs, const mxArray *prhs[]) { openimage(); }
最后是matlab编写make.m文件,以上的文件名字都可以改的
%// This make.m is for MATLAB %// Function: compile c++ files which rely on OpenCV for Matlab using mex %// Author : jeff %// Date : 2016-06-16 %// 说明:修改来源 http://blog.csdn.net/zouxy09/article/details/20553007 和 http://www.cnblogs.com/lukylu/p/3966871.html %% Please modify your path of OpenCV %% If your have any question, please contact Zou Xiaoyi % Notice: first use "mex -setup" to choose your c/c++ compiler clear all; clc; %------------------------------------------------------------------- %% get the architecture of this computer is_64bit = strcmp(computer,'MACI64') || strcmp(computer,'GLNXA64') || strcmp(computer,'PCWIN64'); %------------------------------------------------------------------- %% the configuration of compiler % You need to modify this configuration according to your own path of OpenCV % Notice: if your system is 64bit, your OpenCV must be 64bit! out_dir='./'; CPPFLAGS = ' -O -DNDEBUG -I.\ -IC:\opencv\build\include -IC:\opencv\build\include\opencv -IC:\opencv\build\include\opencv2'; % your OpenCV "include" path LDFLAGS = ' -LC:\opencv\build\x64\vc12\lib'; % your OpenCV "lib" path LIBS = ' -lopencv_calib3d249d -lopencv_contrib249d -lopencv_core249d -lopencv_features2d249d -lopencv_flann249d -lopencv_gpu249d -lopencv_highgui249d -lopencv_imgproc249d -lopencv_legacy249d -lopencv_ml249d -lopencv_nonfree249d -lopencv_objdetect249d -lopencv_photo249d -lopencv_stitching249d -lopencv_ts249d -lopencv_video249d -lopencv_videostab249d'; %LIBS = ' -lopencv_calib3d249 -lopencv_contrib249 -lopencv_core249 -lopencv_features2d249 -lopencv_flann249 -lopencv_gpu249 -lopencv_highgui249 -lopencv_imgproc249 -lopencv_legacy249 -lopencv_ml249 -lopencv_nonfree249 -lopencv_objdetect249 -lopencv_photo249 -lopencv_stitching249 -lopencv_ts249 -lopencv_video249 -lopencv_videostab249'; if is_64bit CPPFLAGS = [CPPFLAGS ' -largeArrayDims']; end %% add your files here! compile_files = { % the list of your code files which need to be compiled <span style="white-space:pre"> </span>'RGB2Gray.cpp' <span style="white-space:pre"> </span>'OpenImage.cpp' }; %------------------------------------------------------------------- %% compiling... for k = 1 : length(compile_files) str = compile_files{k}; fprintf('compilation of: %s\n', str); str = [str ' -outdir ' out_dir CPPFLAGS LDFLAGS LIBS]; args = regexp(str, '\s+', 'split'); mex(args{:}); end fprintf('Congratulations, compilation successful!!!\n');
说明:只要修改相应的opencv的路径和版本,写好自己的cpp文件,放到compile_files中即可。
5、展望
一下说明下以后需要做的,同时混合编程中还有几个问题没明白,后面有需要再解决补充。也希望大家可以提供解决思路和方法a) 不能读取绝对路径中的图片文件,需要在同一路径中,而VS中是可以的;
b) cpp文件中,imread不能读取图片文件,不知道是不是跟matlab中imread混淆,纯属猜测
c) 不是给定图片名参数,而是传递通过matlab读取的图像信息,需要修改程序
d) ......
相关文章推荐
- 解析在main函数之前调用函数以及对设计的作用详解
- 详解Matlab中 sort 函数用法
- python中使用OpenCV进行人脸检测的例子
- opencv 做人脸识别 opencv 人脸匹配分析
- java和matlab画多边形闭合折线图示例讲解
- 使用opencv拉伸图像扩大分辨率示例
- 深入理解C/C++混合编程
- C#调用Matlab生成的dll方法的详细说明
- Android Studio中配置OpenCV库开发环境的教程
- 基于C++实现kinect+opencv 获取深度及彩色数据
- visual studio 2012安装配置方法图文教程 附opencv配置教程
- OpenCV 2.4.3 C++ 平滑处理分析
- C和C++混合编程问题
- python和C语言混合编程实例
- 简述Matlab中size()函数的用法
- 从java中调用matlab详细介绍
- Python中使用OpenCV库来进行简单的气象学遥感影像计算
- 利用Python和OpenCV库将URL转换为OpenCV格式的方法
- python结合opencv实现人脸检测与跟踪
- Python环境搭建之OpenCV的步骤方法