前言:在進行圖形圖像處理時,經常會用到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; }