该博客为《Ubuntu 相关》系列博客的第四篇,该系列博客主要对Ubuntu安装各种软件或者库进行一个记录,方便重装系统后快速恢复工作。
这是进项目组以来接受的第一个任务,以此记录实现过程。
此篇紧接上篇实现c++读取.mat文件。
Ubuntu 下用 C++ 读写.mat文件
由于项目工程要求,需要使用matlab生成的.mat文件,于是查找了基本使用方法。
C++代码
该代码是这个项目的部分代码,包含了前几篇博客的内容,就借助这个代码解释一下。
#include <mat.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include "mclmcrrt.h"//
#include "mclmcr.h"
#include "matrix.h"
#include "mclcppclass.h"
#include "predictresult.h"//
using namespace std;
int main()
{
///初始化应用程序///
// Set up the application state for the MATLAB Runtime instance created in the application.
if (!mclInitializeApplication(NULL,0))
{
cerr << "could not initialize the application properly" << endl;
return -1;
}
cout << "I initialize the application properly" << endl;
///读取mat文件//
MATFile *pmatFile = NULL;
mxArray *pMxArray = NULL;
// 读取.mat文件(例:mat文件名为"xunlianjitezheng.mat",其中包含"result_feature_5")
double *result_feature_5;
char Train_file[100];
cout << "Please enter the file path of training data:" << endl;
cin >> Train_file;
pmatFile = matOpen(Train_file,"r");
pMxArray = matGetVariable(pmatFile, "result_feature_5");
// 按列读的数据
result_feature_5 = (double*) mxGetData(pMxArray);
size_t M_1 = mxGetM(pMxArray);
size_t N_1 = mxGetN(pMxArray);
double Train_date[M_1*N_1];
for (int i=0; i<M_1; i++)
for (int j=0; j<N_1; j++)
Train_date[M_1*j+i] = result_feature_5[M_1*j+i];
matClose(pmatFile);
mxFree(result_feature_5);
cout << "OK! I get the result_feature_5 date!" << endl;
// 读取.mat文件(例:mat文件名为"ceshijitezheng.mat",其中包含"result_feature_test")
double *result_feature_test;
char Test_file[100];
cout << "Please enter the file path of testing data:" << endl;
cin >> Test_file;
pmatFile = matOpen(Test_file,"r");
pMxArray = matGetVariable(pmatFile, "result_feature_test");
// 按列读的数据
result_feature_test = (double*) mxGetData(pMxArray);
size_t M_2 = mxGetM(pMxArray);
size_t N_2 = mxGetN(pMxArray);
double Test_date[M_2*N_2];
for (int i=0; i<M_2; i++)
for (int j=0; j<N_2; j++)
Test_date[M_2*j+i] = result_feature_test[M_2*j+i];
matClose(pmatFile);
mxFree(result_feature_test);
cout << "OK! I get the result_feature_test date!" << endl;
//初始化函数库
// initialize lib,这里必须做初始化!
if( !predictresultInitialize())
{
cout << "Could not initialize libpredictresultInitialize!" << endl;
return -1;
}
cout << "I initialize libpredictresultInitialize!" << endl;
///调用predictresult函数//
// 为变量分配内存空间, maltab只有一种变量,就是矩阵,为了和c++变量接轨,设置成1*1的矩阵
// 此处应为【列, 行】!!!
// 不转换了!!!
mwArray mwA(M_1, N_1, mxDOUBLE_CLASS);
mwArray mwB(M_2, N_2, mxDOUBLE_CLASS);
mwArray mwC(1, 1, mxINT8_CLASS);
// 调用类里面的SetData函数给类赋值
// 此处矩阵赋值,跟一般的不同,其从列开始赋值,所以需要做以下处理:1.上一步创建矩阵空间应为【列, 行】。 2.matlab的输入做一个转置处理。
// 惊奇的发现,读取mat文件时也是按列读取的,所以不用转换了
mwA.SetData(Train_date, M_1*N_1);
mwB.SetData(Test_date, M_2*N_2);
// 调用自己的函数,分类。
predictresult(1, mwC, mwA, mwB);
// 输出结果
int Result=mwC.Get(1, 1);
cout << "Result: " << Result << endl;
// 后面是一些终止调用的程序
// terminate the lib
predictresultTerminate();
// terminate MCR
mclTerminateApplication();
return EXIT_SUCCESS;
}
代码分解
初始化应用程序
但纯的读取.mat文件不需要这个,如果读取了.mat文件之后需要调用自己的matlab函数,这一步很重要,而且一定要在读取.mat文件的代码之前,否则就会出现段错误(核心已转储)
的错误。这个错误我搞了一中午,一直没发现这个错误!!!突然想到整个程序实在RCM Install的环境下运行的,那是不是应该先初始化这个环境,结果就好了!!!
///初始化应用程序///
// Set up the application state for the MATLAB Runtime instance created in the application.
if (!mclInitializeApplication(NULL,0))
{
cerr << "could not initialize the application properly" << endl;
return -1;
}
cout << "I initialize the application properly" << endl;
.mat读取部分
// 读取.mat文件(例:mat文件名为"xunlianjitezheng.mat",其中包含"result_feature_5")
double *result_feature_5;
// 为了工程实现,定义一个输入,这个输入是.mat的文件路径+文件名
// 如:/home/al007/桌面/predictresult/xunlianjitezheng.mat
char Train_file[100];
cout << "Please enter the file path of training data:" << endl;
cin >> Train_file;
// 读取.mat文件
pmatFile = matOpen(Train_file,"r");
// 这里的要注意.mat里面的变量名,是这个函数的第二个输入
pMxArray = matGetVariable(pmatFile, "result_feature_5");
// 注意:按列读的数据,就是先读第一列数据,然后依次按列读取数据。很重要!很重要!!很重要!!!
result_feature_5 = (double*) mxGetData(pMxArray);
//获取数据的行和列
size_t M_1 = mxGetM(pMxArray);
size_t N_1 = mxGetN(pMxArray);
//单纯的读取.mat文件不需要定义一个数组,这是为了跟mwArray传递数据用的
double Train_date[M_1*N_1];
for (int i=0; i<M_1; i++)
for (int j=0; j<N_1; j++)
Train_date[M_1*j+i] = result_feature_5[M_1*j+i];
matClose(pmatFile);
mxFree(result_feature_5);
cout << "OK! I get the result_feature_5 date!" << endl;
调用自己编译的MATLAB函数函数
单纯的调用.mat文件不需要这部分,如果程序涉及到调用MATLAB函数,那就要注意数据的传输!!!
在.mat读取部分
我们额外定义了一个数组,并把我们读到的数据复制到了数组中,为什么不直接用mat文件的变量直接传数据呢,我试了一下午,数据一直不对,我也不清楚原因(如果有知道的大佬,还请评论区留言,非常感谢!),然后自己的写一个小的demo传入的是数组,发现数据没有问题,那我也就把数据复制到数组中,发现成了!!!
.mat读取是按列读取,mwArray构造数组也是按列来的(在这篇博客已经说明!),所以这个地方放就不要特殊的处理了!!!
///调用predictresult函数//
// 为变量分配内存空间, maltab只有一种变量,就是矩阵,为了和c++变量接轨,设置成1*1的矩阵
// 此处应为【列, 行】!!!
// 不转换了!!!
mwArray mwA(M_1, N_1, mxDOUBLE_CLASS);
mwArray mwB(M_2, N_2, mxDOUBLE_CLASS);
mwArray mwC(1, 1, mxINT8_CLASS);
// 调用类里面的SetData函数给类赋值
// 此处矩阵赋值,跟一般的不同,其从列开始赋值,所以需要做以下处理:1.上一步创建矩阵空间应为【列, 行】。 2.matlab的输入做一个转置处理。
// 惊奇的发现,读取mat文件时也是按列读取的,所以不用转换了
mwA.SetData(Train_date, M_1*N_1);
mwB.SetData(Test_date, M_2*N_2);
// 调用自己的函数,分类。
predictresult(1, mwC, mwA, mwB);
// 输出结果
int Result=mwC.Get(1, 1);
cout << "Result: " << Result << endl;
测试数组输入的demo:
double a[6] = {2.4435e07, 1.46488, 6.15623, 1.22475, 19.4892, 2.03679};
mwArray A(2,3,mxDOUBLE_CLASS);
A.SetData(a,6);
for (int i=0; i<6; i++)
cout << a[i] << ", ";
cout << endl;
cout << A << endl;
至此我们已经完成C++读取.mat文件。
生成.mat文件
// 生成.mat文件
double *outA = new double[M*N];
for (int i=0; i<M; i++)
for (int j=0; j<N; j++)
outA[M*j+i] = A[i][j];
pmatFile = matOpen("A.mat","w");
pMxArray = mxCreateDoubleMatrix(M, N, mxREAL);
mxSetData(pMxArray, outA);
matPutVariable(pmatFile, "A", pMxArray);
matClose(pmatFile);
2022年11月22日更新
创建一个.mat文件
main.cpp文件
#include <mat.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include "mclmcrrt.h"//
#include "mclmcr.h"
#include "matrix.h"
#include "mclcppclass.h"
using namespace std;
int main()
{
///初始化应用程序///
// Set up the application state for the MATLAB Runtime instance created in the application.
if (!mclInitializeApplication(NULL,0))
{
cerr << "could not initialize the application properly" << endl;
return -1;
}
cout << "I initialize the application properly" << endl;
///读取mat文件//
MATFile *pmatFile = NULL;
mxArray *pMxArray = NULL;
// 读取.mat文件(例:mat文件名为"matlab.mat",其中包含"a")
double *a;
pmatFile = matOpen("/home/f216/matlab.mat","r");
pMxArray = matGetVariable(pmatFile, "a");
// 按列读的数据
a = (double*) mxGetData(pMxArray);
size_t M_1 = mxGetM(pMxArray);
size_t N_1 = mxGetN(pMxArray);
for (int i=0; i<M_1; i++)
for (int j=0; j<N_1; j++)
printf("%f \t", a[M_1*j+i]);
matClose(pmatFile);
mxFree(a);
cout << "OK! I get the a date!" << endl;
return EXIT_SUCCESS;
}
CMakeList.txt文件:
cmake_minimum_required(VERSION 2.8)
project(main)
set(CMAKE_CXX_STANDARD 11)
include_directories("/usr/local/MATLAB/MATLAB_Runtime/v95/extern/include")
add_executable(main main.cpp)
target_link_libraries(main "/usr/local/MATLAB/MATLAB_Runtime/v95/bin/glnxa64/libmwmclmcr.so")
target_link_libraries(main "/usr/local/MATLAB/MATLAB_Runtime/v95/runtime/glnxa64/libmwmclmcrrt.so")
运行结果:
参考博客:
https://blog.csdn.net/lien0906/article/details/42921969
https://blog.csdn.net/left_la/article/details/8206645