重点!!!Vcpkg安装Matio
vcpkg包管理工具可以一键安装matio,省去复杂的配置环境过程,不再需要按照以下教程一步步做了
vcpkg的安装和使用请参考我的这篇文章:C++包管理工具vcpkg的安装使用教程-CSDN博客
vcpkg安装并使用matio只需要两步
安装
./vcpkg install matio:x64-windows
全局生效
./vcpkg integrate install
然后就可以使用了,就这么简单,不需要配置安装matiio,也不需要在项目中添加路径。
前言
主要参考:https://blog.csdn.net/weixin_73535565/article/details/140566000
matio库主要用于在cpp中读取在matlab保存的mat文件,我这里用于读取mat中的矩阵和cell。
下载提醒:如果遇到下载慢的情况可以选择把猫猫的模式从rule改为global。
编译工具安装
使用cmake作为编译工具,地址:https://cmake.org/download/
根据自己电脑是64位还是32位选择installer,我电脑是x64,所以选择cmake-3.30.1-windows-x86_64.msi
下载之后双击msi,根据指示安装完成。
HDF5库和zlib库编译安装
matio主要依赖HDF5和zlib这两个库,所以在编译安装matio之前需要先安装这两个库。
25.02.26更新-必看
官网把提供的安装包改了,里面没有build了,所以这里提供我下载的版本:
链接: https://pan.baidu.com/s/1IGnShuiOomUxjFkC8lka_g?pwd=9v95 提取码: 9v95
HDF5库编译安装
HDF5官网,先别点进去:https://www.hdfgroup.org
HDF5库的1.14版本没有提供Cmake版本,所以需要选择之前的1.12版本,
地址:https://portal.hdfgroup.org/downloads/hdf5/hdf5_1_12_3.html
下载地址:https://hdf-wordpress-1.s3.amazonaws.com/wp-content/uploads/manual/HDF5/HDF5_1_12_3/src/hdf5-1.12.3.zip
下载之后解压到一个不会被删除的地方,我不小心放在了下载文件夹下,不要学我。
解压之后根据VS版本双击bat文件运行(确保cmake已经安装,不然会直接闪退)
需要时间挺久的,运行之后窗口会自动退出。之后双击HDF5中新增的build文件夹中的HDF5.sln,进入VS
进入VS后确认一下是release还是debug,HDF5和zlib需要在同一模式下编译安装。release比较快,所以我这里选择release x64
右键ALL_BUILD,点击生成,如果之前由于各种原因生成失败的话可以右键ALL_BUILD-重新生成。ALL_BUILD生成成功之后右键INSTALL-生成,成功的话在输出中可以看到installing的位置,记录一下位置,之后要用。
zlib库编译安装
zlib库地址,不用点进去:http://www.zlib.net/
不用特地去下载,因为在HDF5文件夹里有zlib-1.3.tar.gz,一样解压到不会被删除的地方
在zlib文件夹下新建一个build文件夹,然后打开cmake(cmake-gui)
选择zlib路径和zlib中的build路径,勾选Grouped和Advanced,点击configure,在弹出来的窗口选择VS版本和系统位数,如果是VS2022和x64就可以直接点击finish。
修改INSTALL的路径,全部选择新建的build/xxx内,具体路径如图所示,选择好之后点击configure generate,不出问题之后点击open project,之后会自动打开VS。
和HDF5的步骤一样,在release x64模式下,右键ALL_BUILD-生成,之后右键INSTALL-生成,在输出里记录一下installing的地址,一会要用。
matio编译安装
matio库安装地址:https://github.com/tbeu/matio
下载并解压到一个不会被删除的地方,打开cmake,选择matio路径和里面的build路径
点击configure,会报错是正常的,因为路径还没选择,需要路径选择如下,仅供参考,可以搜索一下HDF5中具体的文件夹在哪,比如include
HDF5路径选择好之后点击configure,再次报错,这次需要选择zlib路径,具体如下
点击configure generate,这次应该不会报错,点击open project,和上面一样,右键ALL_BUILD-生成,右键INSTALL-生成
如果有以下报错,那么请把当前VS关掉,然后以管理员身份打开VS,选择matio.sln,右键ALL_BUILD-重新生成,右键INSTALL-重新生成,然后应该没有问题了。记录一下installing的位置,一会要用。
添加环境变量
任务栏搜索环境变量-点击编辑系统环境变量-点击环境变量-双击系统变量中的Path-点击右上角新建-添加这三个库的路径,路径都是不同的,但是位置的后半段应该是一样的。
在VS项目中附加matio库
右键项目(我这里是CMM)-属性-c/c++-附加包含目录,添加以下路径
C:\Program Files (x86)\matio\include
还是属性-链接器-输入-附加依赖项,添加以下路径
C:\Program Files (x86)\matio\lib\libmatio.lib
至此matio安装完毕
cpp读取mat中的cell和矩阵
需要事先添加Eigen库,添加过程略。
openMatFile用来读取矩阵,openCellFile用来读取cell中的矩阵,我这里是756*756的cell,每个cell元素是一个n*m的矩阵,读取之后为std::vector<std::vector<MatrixXd>>的变量。
#include <iostream>
#include <vector>
#include <matio.h>
#include <Eigen/Dense>
using Eigen::MatrixXd;
using namespace std;
bool openMatFile(const std::string& filePath, MatrixXd& eigenMatrix)
{
mat_t* pMatFile = nullptr; // MAT文件句柄
matvar_t* pMatVar = nullptr; // MAT文件中的变量
double* data = nullptr; // 存储矩阵数据的指针
int numRows, numCols; // 矩阵的行数和列数
// 打开mat文件
pMatFile = Mat_Open(filePath.c_str(), MAT_ACC_RDONLY); // matOpen 函数打开MAT文件
if (!pMatFile)
{
std::cerr << "Failed to open MAT file" << std::endl;
return false;
}
// 遍历所有变量
pMatVar = Mat_VarReadNext(pMatFile);
while (pMatVar)
{
// 输出变量信息
std::cout << "Variable name: " << pMatVar->name << std::endl;
std::cout << "Variable rank: " << pMatVar->rank << std::endl;
std::cout << "Variable dimensions: ";
for (int i = 0; i < pMatVar->rank; ++i)
{
std::cout << pMatVar->dims[i] << " ";
}
std::cout << std::endl;
// 处理二维双精度矩阵
if (pMatVar->class_type == MAT_C_DOUBLE && pMatVar->rank == 2)
{
numRows = pMatVar->dims[0];
numCols = pMatVar->dims[1];
data = static_cast<double*>(pMatVar->data);
// 将数据复制到Eigen矩阵
eigenMatrix.conservativeResize(numRows, numCols);
int i = 0;
for (int c = 0; c < numCols; ++c)
{
for (int r = 0; r < numRows; ++r)
{
eigenMatrix(r, c) = data[i];
++i;
}
}
//std::cout << "Read matrix: " << pMatVar->name << std::endl;
//std::cout << eigenMatrix << std::endl;
}
// 释放当前变量
Mat_VarFree(pMatVar);
pMatVar = nullptr;
// 继续遍历下一个变量
pMatVar = Mat_VarReadNext(pMatFile);
}
// 关闭mat文件
Mat_Close(pMatFile);
pMatFile = nullptr;
std::cout << "File closed" << std::endl;
return true;
}
bool openCellFile(const std::string& filePath, std::vector<std::vector<MatrixXd>>& output)
{
mat_t* pMatFile = nullptr; // MAT文件句柄
matvar_t* pMatVar = nullptr; // MAT文件中的变量
double* data = nullptr; // 存储矩阵数据的指针
int numRows, numCols; // 矩阵的行数和列数
// 打开mat文件
pMatFile = Mat_Open(filePath.c_str(), MAT_ACC_RDONLY); // matOpen 函数打开MAT文件
if (!pMatFile)
{
std::cerr << "Failed to open MAT file" << std::endl;
return false;
}
// 遍历所有变量
pMatVar = Mat_VarReadNext(pMatFile);
while (pMatVar)
{
// 输出变量信息
std::cout << "Variable name: " << pMatVar->name << std::endl;
std::cout << "Variable rank: " << pMatVar->rank << std::endl;
std::cout << "Variable dimensions: ";
for (int i = 0; i < pMatVar->rank; ++i)
{
std::cout << pMatVar->dims[i] << " ";
}
std::cout << std::endl;
// 获取cell数组的尺寸
size_t numRows = pMatVar->dims[0];
size_t numCols = pMatVar->dims[1];
output.resize(numRows, std::vector<MatrixXd>(numCols));
// 遍历cell数组中的每个元素
matvar_t** cells = (matvar_t**)pMatVar->data;
cell也是纵着读的,ij需要互换
for (size_t i = 0; i < numRows; ++i)
{
cout << i << endl;
for (size_t j = 0; j < numCols; ++j)
{
matvar_t* pCell = cells[i * numCols + j];
if (pCell->class_type == MAT_C_DOUBLE && pCell->rank == 2)
{
// 读取矩阵数据
size_t rows = pCell->dims[0];
size_t cols = pCell->dims[1];
double* data = static_cast<double*>(pCell->data);
MatrixXd matrix(rows, cols);
int index = 0;
for (size_t r = 0; r < rows; ++r)
{
for (size_t c = 0; c < cols; ++c)
{
matrix(r, c) = data[r + c*rows];
}
}
output[j][i] = matrix;
}
}
}
/*MatrixXd matrix = output[169][6];
cout << matrix << endl;*/
// 释放当前变量
Mat_VarFree(pMatVar);
pMatVar = nullptr;
// 继续遍历下一个变量
pMatVar = Mat_VarReadNext(pMatFile);
}
// 关闭mat文件
Mat_Close(pMatFile);
pMatFile = nullptr;
std::cout << "File closed" << std::endl;
return true;
}