Matlab在处理图像时进行数据分析时具有很大的优势,由于与企业对接时一般需要用到其他编程语言,如C++等,因此可以将Matlab函数编译成dll文件,可以在C++中对其进行调用。初次使用时会出现许多错误,并且很多错误都没法通过编译器的提示进行修改,本文将详述使用的整个过程并把几乎所有可能遇到的错误罗列出来,希望对读者有所帮助。
本文的方法针对所有版本的Visual Studio+Matlab均适用,关键要确保所使用的C++编译器能被当前使用的Matlab所支持,查看各版本Matlab所支持编译器
由于工作对接需要使用的是Microsoft Visual C++ 2010 Professional,这里找到只有MatlabR2012往后的老版本还支持VS2010,点击Detail可以看到
由于使用的操作系统为WindowsXP,是一个32位的操作系统,在安装上与Matlab只有一点细微的差别。网上下载的安装包一般是32位/64位放在一起的一个安装包,而安装教程给的只有64位的安装教程,其实我们只要找到对应的32位的setup.exe按照64位的方法同样安装即可。
一般点开解压后的安装包可以看到
我们需要点开同目录下的bin文件夹,可以看到win32以及win64文件夹,里边分别存放32位和64位的安装程序,我们选择所需的win32打开即可,使用win32目录下的setup.exe按照64位安装教程进行即可完成32位的Matlab安装。
安装好后打开Matlab我们可以在Command窗口输入mexext可以查看到
返回mexw32表示当前Matlab是支持生成win32的动态链接库的,64位对应为mexw64。
第一步:在matlab的命令行窗口中输入mex -setup,会出现以下界面(旧版本),新版本会列出当前系统所存在的所有编译器,点击选择即可。
第二步:在Matlab中创建一个图像处理函数
function fun_imshow(path) I=imread(path); I1=rgb2gray(I); [Can,~]=edge(I1,'canny'); imshow(Can); end
第三步:对matlab的函数进行编译。**注意:这里只能对matlab的function进行编译,并不能对一般的.m脚本进行编译。
这里采用的mcc命令有两种方式:
1.mcc -W cpplib:fun_imshow -T link:lib fun_imshow.m -C 2.mcc -W cpplib:fun_imshow -T link:lib fun_imshow.m
第一种方式会把Matlab所用到的工具箱单独生成一个.ctf文件,需要把.ctf文件与.dll文件一同放到所生成的.exe文件目录下;第二种方式不会单独编译出.ctf文件来,只需要把.dll文件放到.exe文件目录下即可。我们采用的是第二种方式,生成文件如下所示:
我们需要用到的文件只有fun_imshow.dll,fun_imshow.h,fun_imshow.lib这三个。
第一步:新建一个空项目,添加一个新的源文件,输入一个简单的main()函数预生成一次,此时会在工程目录下多出一个Debug文件夹。
注意:我们所使用的是32位的Matlab,对应需要在Win32下进行Debug
第二步:将fun_imshow.h,fun_imshow.lib复制到.cpp文件的同目录下,fun_imshow.dll复制到Debug目录下(注意:可能工程目录下会有多个Debug目录,应复制到生成.exe的Debug目录下)
第三步:右键工程文件,选择Properties → \rightarrow →VC++ Directories
matlabroot为本机Matlab的安装目录。
第四步:Properties → \rightarrow →Linker → \rightarrow →Input
Additional Dependencies:mclmcrrt.lib,libmat.lib,libmx.lib
至此完成VS2010调用Matlab库的环境配置。
提供以下测试程序
#include "fun_imshow.h" #include <iostream> #pragma comment(lib, "fun_imshow.lib") using namespace std; int main() { bool isOk = 0;//判断动态库是否初始化成功 if (!mclInitializeApplication(NULL, 0)) { cout << "Could not initialize the application.\n"; return -1; } cout << "isOk = " << isOk << endl;// 0 isOk = fun_imshowInitialize(); // 动态库初始化成功 cout << "isOk = " << isOk << endl;// 1 //system("pause"); fun_imshow("C:/Users/Admin/Desktop/aaa.jpg"); //调用matlab函数 mclWaitForFiguresToDie(NULL); //等待图像显示,不加此句无法显示图像 fun_imshowTerminate(); //关闭动态库 mclTerminateApplication(); return 0; }
只要修改fun_imshow()函数的图片输入路径即可输出图片显示结果。
mclmcrrtx_xx.dll是位于Matlab安装目录下tuntime文件夹里的一个文件,我们正常安装后是具有这一个文件的,并且程序编译时可以通过我们的path环境变量去找到这一个文件。首先去查看电脑的path环境变量是否含有这一个文件的路径,如果没有,将这一个文件的文件夹路径添加进去,重启电脑。一般情况下,安装完Matlab后会自动给我们添加进去,如果我们是首次安装完后就进行编译,系统依然是无法找到这个文件的,需要重启电脑。
这个错误是在使用64位编译环境时会抛出的一个异常,因为我们此时使用的是一个64位Matlab编译出来的dll文件,Win32无法兼容。此时程序是可以编译成功,但无法执行。我们只需要按Ctrl+Alt+E(或Debug → \rightarrow →Exceptions)取消Win32 Exceptions勾选即可。
C++数组数据转换成Matlab可读取的图片数据格式(参考刘维的《精通Matlab与C/C++混合程序设计》)
提供测试程序如下
function fun_imshow(I) imshow(I); end
#include "fun_imshow.h" #include <iostream> #include <vector> #pragma comment(lib, "fun_imshow.lib") using namespace std; int main() { const int rows = 1000; const int columns = 1000; double* a; a = new double[rows*columns]; for(int i=0; i<rows*columns;i++){ a[i] = 0; } bool isOk = 0;//判断动态库是否初始化成功 if (!mclInitializeApplication(NULL, 0)) { cout << "Could not initialize the application.\n"; return -1; } cout << "isOk = " << isOk << endl;// 0 isOk = fun_imshowInitialize(); // 动态库初始化成功 cout << "isOk = " << isOk << endl;// 1 system("pause"); mwArray data(columns,rows,mxDOUBLE_CLASS); data.SetData(a,rows*columns); delete a; fun_imshow(data); //调用matlab函数 mclWaitForFiguresToDie(NULL); //等待图像显示,不加此句无法显示图像 fun_imshowTerminate(); //关闭动态库 mclTerminateApplication(); return 0; }
实现任何形式图片数据通过调用Matlab生成的dll进行处理显示,只要实现图片数据类型向mwArraw类型转换即可。
注意:Matlab数据读取的方式是按列读取的
Link1
Link2
Link3