之前用过基于VS2018 与MATLAB2018a 混合编程(C++特性)(见https://blog.csdn.net/wwwoowww/article/details/83013801),奈何后来matlab版本换成了2016a,混合编程的方式不一样了,自己尝试了几天,终于搞定了。

目录

版本选择

matlab与c++的混合编程有两个方法:

利用mex的方法

创建C++动态库


版本选择

版本: Win10 ,VS2015, Matlab2016a

注意:Matlab2016支持的VS版本有兼容问题,matlab具体支持哪些VS版本请见matlab的安装文件夹路径:C:\Program Files\MATLAB\R2016a\bin\win64\mexopts 中包含了哪些编译器。如下图所示,我的文件夹中包含了vs2015,说明该版本的matlab支持vs2015的编译器。

若想要支持的vs版本文件夹中没有,需要自己去下载对应版本的文件。详细的内容请见或自己找找吧,我是放弃了:https://blog.csdn.net/cztqwan/article/details/78902530

matlab与c++的混合编程有两个方法:

mex 和调用C++动态库

利用mex的方法

若是不在c/c++中使用其他第三方库,可以使用简单的编译方法。

  • matlab中使用mex -setup 命令,选择c++ 的编译器 (第一次可以使用mex setup -v ,先查找所有的已安装并且支持的编译器)
  • 创建test.cpp 文件, 文件输出 传入的第一个参数和参数的个数

matlab官方文档,对于mexFunction的解释:https://ww2.mathworks.cn/help/matlab/apiref/mexfunction.html

简单来说,mexFunction是matlab调用C/C++的入口,类似main函数,

nlhs 输出的个数, plhs matlab的array类型,是输出参数的地址

nrhs 输入数组的个数, prhs matlab的array类型,包含了输入参数地址

  1. #include "mex.h" //matlab的头文件
    void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
    {if(nrhs < 1){mexPrintf("Use example: test(12)");return;}//如果prhs的类型是double,打印一下语句。类似的函数有mxIsInt等等//if(mxIsDouble(prhs[0]))//      mexPrintf("Type of input arg is double\n");double *data = mxGetPr(prhs[0]); // 获取传入值的地址,不管传入的类型是什么,该方法的获得的都必须为double*int mrows, ncols;mrows = mxGetM(prhs[0]); //获取行的大小ncols = mxGetN(prhs[0]); //获取列的大小mexPrintf("value:%f,rows:%d, cols: %d\n",*data, mrows, ncols);}
  • matlab中使用命令 mex **.cpp。编译成功后使用文件名调用

  • 若要使用第三方库,需要创建make.m文件(但是我自己按网上的尝试,没有链接成功,放弃了)
%// This make.m is for MATLAB
%// Function: compile c++ files which rely on OpenCV for Matlab using mex
%// Author : zouxy
%// Date : 2014-03-05
%// HomePage : http://blog.csdn.net/zouxy09
%// Email : zouxy09@qq.com%% 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;
%-------------------------------------------------------------------
%% 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  -I.\ -ID:\OpenCV\build2015\install\include'; % your OpenCV "include" path
LDFLAGS = ' -LD:\OpenCV\build2015\install\x64\vc14\lib'; % your OpenCV "lib" path
LIBS = ' -lopencv_world346d';
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'
};%-------------------------------------------------------------------
%% 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');

创建C++动态库

上面我们使用了matlab中的vs2015编译器,鉴于我之前的混合编程经验(C++,vs2018,matlab2019,见https://blog.csdn.net/wwwoowww/article/details/83013801),我在尝试使用mex链接第三方库不成功后,想在vs中生成dll文件,再改后缀为.mexw64 。开干

1. 新建Win32 控制台应用程序

2. 配置项目的属性

需要配置的地方有四点:

2.1.注意选择平台为x64(因为我自己编译的opencv版本是64位的)

2.2.常规 -》 配置类型改为 .dll

2.3.VC++目录-》 2.3.1包含目录:添加opencv的include, 添加matlab安装目录下的/extern/include目录

2.3.2 库目录:添加opencv的 x64\vc14\lib(这是我自己编译的基于vs2015的opencv库), 添加matlab安装目录下的\extern\lib\win64\microsoft目录

2.4.连接器-》输入-》 附件依赖项 中 添加:

opencv_world346d.lib (我在opencv编译的时候选择了生成world库,该库将opencv所有的功能集合成一个文件。所以不用想一些博客中要包含n多个opencv_****.dll )
                       libmat.lib   (以下都是matlab的库文件)
                       libmx.lib
                       libmex.lib
                       libeng.lib

3 创建 ***.def 文件 

文件内容:

LIBRARY detect_mark.DLLEXPORTSmexFunction

4 创建源文件

功能:matlab传入一个图像矩阵,c++识别图像是否有aruco mark,并返回mark的id,和中心位置

提醒下, opencv的aruco头文件很可能找不到,因为该库在opencv_contrib包中,需要自己在编译opencv的时候加上这个额外的包

具体的详情见:https://blog.csdn.net/ezhchai/article/details/80557936

#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include "opencv2/aruco.hpp"
#include <iostream>
#include "mex.h"
using namespace std;
using namespace cv;void exit_with_help()
{mexPrintf("Usage: [id, x, y] = detect_mark(img_data);\n");
}/**检查图像中的mark,并返回mark的id和中心点坐标
*/
void detect_marks(cv::Mat& image, vector<Vec3d>&center)
{Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();Ptr<aruco::Dictionary> dictionary =aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(1));vector< int > ids;vector< vector< Point2f > > corners, rejected;vector< Vec3d > rvecs, tvecs;// detect markers and estimate pose/*markerCorners 是检测出的图像的角的列表。对于每个marker,将返回按照原始顺序排列的四个角(从左上角顺时针开始)。因此,第一个点是左上角的角,紧接着右上角、右下角和左下角。markerIds 是在markerCorners检测出的所有maker的id列表.注意返回的markerCorners和markerIds 向量具有相同的大小。*/aruco::detectMarkers(image, dictionary, corners, ids, detectorParams, rejected);//获取中心点坐标for (int i = 0; i < ids.size(); i++) {double x = (corners[i][0].x + corners[i][2].x) / 2;double y = (corners[i][0].y + corners[i][2].y) / 2;center.push_back(Vec3d(ids[i], x, y));//cout << "id: " << ids[i] << " ;center: " << x << "," << y << endl;}return ;
}static void fake_answer(mxArray *plhs[]){plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
}void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{if (nrhs == 1){//获取传入数据的指针,类型只能为double*double *data = mxGetPr(prhs[0]);//将传入的图像数据类型强转为uint8_t来解释,因为我们传入的是图像矩阵,图像在matlab中是uint8类型uint8_t *i_data = (uint8_t*) data;int mrows, ncols;mrows = mxGetM(prhs[0]);    //行数,,matlab按照uint8来计算的个数ncols = mxGetN(prhs[0]);    //列数mexPrintf("m = %d, n = %d", mrows, ncols);/**创建Opencv格式下的图像数据matlab和opencv的图像格式不一样。matlab是三个通道(RGB)分成了三张图片的保存,每一张图片的数据类型都是uint8。所以需要转换。但是如果是一个通道的灰度图,不需要转换opencv是三个通道同时保存,只有一张图片,每个图片的值为(BGR)[uint8,uint8,uint8]matlab和opencv的图像通道排列方式不一样,MATLAB中RGB,OPENCV BGR*///获取灰度图,只采了matlab图像中的R通道数据Mat img_gray = Mat(mrows, ncols / 3, CV_8UC1);for (int i = 0; i<mrows; i++) {for (int j = 0; j < ncols/3; j++) {*(img_gray.data + img_gray.step[0] * i + img_gray.step[1] * j) = (uchar)i_data[j*mrows + i];}}/**// 获取彩色图Mat img_col = Mat(mrows, ncols / 3, CV_8UC3);for (int i = 0; i<mrows; i++) {for (int j = 0; j < ncols; j++) {//改变通道,matlab和opencv的图像通道排列方式不一样,MATLAB中RGB,OPENCV BGR,写的真难看,不忍直视。。。。int chan = j / (ncols / 3);int n;if (chan == 0)n = 2;else if (chan == 2)n = 0;else n = 1;*(img_col.data + img_col.step[0] * i + img_col.step[1] * (j % (ncols / 3)) + img_col.elemSize1()* n) = (uchar)i_data[j*mrows + i];}}*/vector<Vec3d> center;detect_marks(img_gray, center);if (center.size() == 0) {plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);double *resultMat = mxGetPr(plhs[0]);*resultMat = -1;return;}int rows = center.size();int cols = 3;//创建返回给matlab的数据plhs[0] = mxCreateDoubleMatrix(rows, cols, mxREAL);//获取指针double *resultMat = mxGetPr(plhs[0]);//赋值for (int i = 0; i < rows; i++)for (int j = 0; j < cols; j++)*(resultMat + i + j * rows) = (double)center.at(i)[j];//imwrite("out_file_color.png", img_col);}else{exit_with_help();fake_answer(plhs);return;}
}

说明下Matlab的图像存储方式:

matlab文档:https://ww2.mathworks.cn/help/matlab/matlab_external/matlab-data.html

原图是500*312*3的彩色图(不可否认,我媳妇儿很漂亮)

matlab读入上图并传入到C/C++图像的格式是1500*312*1的二维矩阵,排列方式如下,从左到右分别是R、G、B通道的值。

5. 生成.dll文件

最后使用 控制界面 生成-》生成解决方案

把生成的.dll 文件后缀改为 .mexw64

使用matlab调用就可以了

附 我的结果:

传入图像:

Matlab与C/C++混合编程 (基于Opencv库)相关推荐

  1. Matlab与C/C++混合编程调用OpenCV

    *************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com http:/ ...

  2. matlab与vc混合编程指导书.doc,vc与matlab混合编程—基于com.doc

    vc与matlab混合编程-基于com.doc VC与MATLAB混合编程基于COM2010年03月21日星期日1118注意旨在提供一份VC调用MATLAB的快速试验参考和一些实际经验,不保证所有内容 ...

  3. Matlab与C/C++混合编程接口及应用

    http://www.cnblogs.com/lidabo/archive/2012/08/24/2654148.html 在参考文献基础上.补充和完善了. Matlab与C/C++混合编程接口及应用 ...

  4. matlab与c 接口与混合编程,Matlab与C/C++混合编程接口及应用方法解析

    1 引言 Matlab 是当前应用最为广泛的数学软件,具有强大的数值计算.数据分析处理.系统 分析.图形显示甚至符号运算等功能[1].利用这一完整的数学平台,用户可以快速实现十分 复杂的功能,极大地提 ...

  5. matlab和C/C++混合编程--Mex

    最近的项目需要matlab和C的混合编程,经过一番努力终于完成了项目要解决的问题.现在就将Mex的一些经验总结一下,当然只是刚刚开始,以后随着学习的深入继续添加.首先讲讲写Mex的一些常规规定,然后我 ...

  6. 【转】matlab与C/C++混合编程——在Windows/Linux上调用Matlab编译的动态库文件

    转自:matlab与C/C++混合编程--在Windows/Linux上调用Matlab编译的动态库文件_sinat_18131557的博客-CSDN博客 date version comments ...

  7. matlab和C/C++混合编程--Mex (转载)

    matlab和C/C++混合编程--Mex 最近的项目需要matlab和C的混合编程,经过一番努力终于完成了项目要解决的问题.现在就将Mex的一些经验总结一下,当然只是刚刚开始,以后随着学习的深入继续 ...

  8. MATLAB和C语言混合编程示例

    MATLAB虽然很好用,尤其在数值运算,图像处理,仿真方面很简洁.方便,但有时间当处理比较大的数据时速度确实有点让人捉急,不过MATLAB提供了和C/C++混合编程的接口,以此兼具二者的优点来缓解这个 ...

  9. matlab和C/C++混合编程--Mex (六)参数传递

    最近的项目需要matlab和C的混合编程,经过一番努力终于完成了项目要解决的问题.现在就将Mex的一些经验总结一下,当然只是刚刚开始,以后随着学习的深入继续添加.首先讲讲写Mex的一些常规规定,然后我 ...

最新文章

  1. 美团Serverless产品落地与演进
  2. java swing 链接_JAVA中Jtable标签设置超级链接:基于Java Swing的超链接标签和超链接按钮的实现...
  3. 风变编程python第一关脸黑怪我喽_风变编程:Python适合编程初学者学习吗?
  4. ES 断路器——本质上保护OOM提前抛出异常而已
  5. 转 JavaScript 操作select控件大全(新增、修改、删除、选中、清空、判断存在等)...
  6. 权重对生成对抗网络GAN性能的影响
  7. [蓝桥杯2018决赛]三角形面积-数论
  8. Usaco_1_3_Calf Flac
  9. cad图纸问号怎么转换文字_CAD中文图纸中文字体变成问号怎么办?不慌这几步教你轻松解决...
  10. 使用C语言快速统计fastq文件q20、q30、GC含量
  11. win7触摸板怎么关闭_笔记本触控板怎么关闭 笔记本触控板关闭方法【详解】
  12. 勒让德函数C语言编程设计,用递归方法求n阶勒让德多项式的值
  13. OOC-GCC 特性介绍
  14. Java筑基10-封装继承多态(重点)
  15. PMP与我 - 我的58天备考生涯
  16. Oracle查询表名注释及表字段注释
  17. 微信小程序:页面传递中文出现乱码
  18. mysql 危险字符_PHP过滤指定字符串,过滤危险字符
  19. oracle asm密码是什么,ORACLE 12C ASM 新特性:共享密码文件
  20. 搭建即可运营的秒收录导航网源码带广告管理完美运营版

热门文章

  1. ImCash:币圈英文术语大全
  2. ubuntu16.04 关闭防火墙的方法
  3. 合并排序(Java)-解析
  4. objective-c高级编程 笔记
  5. USACO shuttle
  6. 把虚拟机装到内存里(打开PScs3只需要2秒)
  7. 利用自定义分页技术提高数据库性能
  8. [Pyhon疫情大数据分析] 三.新闻信息抓取及词云可视化、文本聚类和LDA主题模型文本挖掘
  9. 【python数据挖掘课程】二十五.Matplotlib绘制带主题及聚类类标的散点图
  10. iOS之深入解析保证线程安全的“锁”的使用和性能分析