c++读写matlab中.mat数据

时间:2024-02-24 13:37:21

  前言:在进行图形图像处理时,经常会用到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;
}