前言:在进行图形图像处理时,经常会用到matlab进行算法的仿真验证,然后再移植到别的语言中。有时会涉及到数据的交互,比如直接读取matlab的.mat类型数据,或者是将c++中的数组存为.mat,为了使用方便,这里介绍一下c++对.mat的读写。
一、工程配置:
1、附加包含目录:
D:\MATLAB\extern\include
2、附加库目录:
D:\MATLAB\extern\lib\win64\microsoft
3、附加依赖库:
libmat.lib
libmx.lib
libmex.lib
libeng.lib
4、计算机环境变量->path 添加:
D:\MATLAB\bin\win64;
5、其他:
- 上述路径应改为自己的路径。
- C++工程解决方案平台应与matlab版本一致
二、存储.mat
直接上代码:
#include <string.h> #include <iostream> #include <stdio.h> #include <mat.h> using namespace std; template<typename T> bool SaveMatlabMat(T *src,string savePath,string matrixName,int width,int height) { //转置存储 int datasize = width * height; double *Final = new double[datasize];//待存储数据转为double格式 memset(Final, 0, datasize * sizeof(double)); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { Final[i*width+j] = double(src[i*width+j]); } } mxArray *pWriteArray = NULL;//matlab格式矩阵 MATFile *pmatFile = NULL;//.mat文件指针 pmatFile = matOpen(savePath.c_str(), "w"); if (pmatFile == nullptr) { printf("mat save path is error"); return false ; } //创建一个width*height的矩阵 pWriteArray = mxCreateDoubleMatrix(width, height, mxREAL); //把data的值赋给pWriteArray指针 memcpy((void *)(mxGetPr(pWriteArray)), (void *)Final, sizeof(double) * datasize); //给矩阵命名为matrixName matPutVariable(pmatFile, matrixName.c_str(), pWriteArray); matClose(pmatFile); mxDestroyArray(pWriteArray);//release resource delete[]Final;//release resource return true; } int main() { int width=2592; int height=2048; int *array = new int[width*height];//初始化一个height*width的二维矩阵 memset(array,0,sizeof(int)*width*height); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { array[i*width + j] = i*width + j; } } string filePath = "aa.mat";//文件名字 string matrixName = "aa";//文件内矩阵名 SaveMatlabMat(array,filePath, matrixName,width,height); return 0; }
代码运行完会在当前目录下发现“aa.mat”文件,用matlab打开后如下图所示:
可以发现与c++中矩阵为转置关系,这是因为matlab中的数据是按列存储的,而c++中是按行存储的。前面我初始化的c++矩阵中第一行为0~2591,在matlab中存为第一列。这在实际使用中很不方便,为了消除这种转置关系,我们只需在把数据存入Final时提前进行转置,附上代码如下:
template<typename T> bool SaveMatlabMat(T *src, string savePath, string matrixName, int width, int height) { //转置存储 int datasize = width * height; double *Final = new double[datasize];//待存储数据转为double格式 memset(Final, 0, datasize * sizeof(double)); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { Final[j*height+i] = double(src[i*width + j]); } } mxArray *pWriteArray = NULL;//matlab格式矩阵 MATFile *pmatFile = NULL;//.mat文件指针 pmatFile = matOpen(savePath.c_str(), "w"); if (pmatFile == nullptr) { printf("mat save path is error"); return false; } //创建一个height*width的矩阵 pWriteArray = mxCreateDoubleMatrix(height, width, mxREAL); //把data的值赋给pWriteArray指针 memcpy((void *)(mxGetPr(pWriteArray)), (void *)Final, sizeof(double) * datasize); //给矩阵命名为matrixName matPutVariable(pmatFile, matrixName.c_str(), pWriteArray); matClose(pmatFile);//close file mxDestroyArray(pWriteArray);//release resource delete[]Final;//release resource return true; }
这样,便使得写入的.mat文件和c++矩阵格式保持一致。
三、读取.mat
与写入一样,由于matlab按列存储数据,c++读取时也是读取matlab的第一列数据,因此读取时也要考虑转置关系,这里直接附上代码,读取我们刚刚存储的aa.mat。
template<typename T> bool ReadMatlabMat(T *dst, string filePath,string matrixName, int width, int height) { MATFile *pmatFile = NULL; mxArray *pMxArray = NULL; double *matdata; pmatFile = matOpen(filePath.c_str(), "r");//打开.mat文件 if (pmatFile == NULL) { printf("filePath is error"); return false; } pMxArray = matGetVariable(pmatFile, matrixName.c_str());//获取.mat文件里面名为matrixName的矩阵 matdata = (double *)mxGetData(pMxArray);//获取指针 matClose(pmatFile);//close file for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { dst[i*width+j] = T(matdata[j*height + i]); } } mxDestroyArray(pMxArray);//释放内存 matdata = NULL; return 1; }