matlab文件读写库(matio),了解一下?
一、引言
MATLAB是美国MathWorks公司出品的商业数学软件,用于算法开发、数据可视化、数据分析以及数值计算的高级技术计算语言和交互式环境,主要包括MATLAB和Simulink两大部分。一言以蔽之——很牛很强大!
如果在项目中把数据保存为mat文件,这对于算法分析来说简直就是雪中送炭啊。matlab可是PC软件啊,在PC上借助matlab生成mat格式文件很好实现,那如何在嵌入式项目中生成matlab文件呢?
网上搜索资料发现一个matio(MAT File I/O Library),matio是一个基于C语言的对matlab格式文件读写操作的库。基于C语言的话,那可移植性自然是极好的。
二、下载,编译
那matlab文件格式到底长啥样子呢?
MAT-File FormatMathWorks公司官网有这个文件格式的说明。这篇文档描述了MAT-File的Level 4和Level 5的格式说明,我们就理解为MAT-File的版本4和版本5吧,上面说了版本4比较老,版本5算是比较新的,但是现在其文件版本已经7.3了,下面会说到这个事情。总之,说了这个matlab文件格式,是二进制格式,不是给人看的,看起来很不直观。
我们大概了解一下matlab文件格式就行了
matio 1.5.12下载。因为我们是在嵌入式产品上做,所以要交叉编译,首先配置好自己的环境变量。在编译之前,我们还是先看一下人家matio的帮助文档,会有助于我们编译哦。
文档中有编译指导,文档中也明确写出,支持mat文件的V4、V5、V7.3,都需要依赖zlib库,但是V7.3还需要依赖hdf5库。我们这里不需要v7.3版本,所以不用hdf5。
我们心里已经有个谱了,开始进行编译。
-
zlib库编译参看我之前文档交叉编译zlib
-
解压matio-1.5.12.tar.gz
tar zxvf matio-1.5.12.tar.gz cd matio-1.5.12/ ./configure --host=arm-none-linux-gnueabi --prefix=$PWD/install --with-default-file-ver=5 --with-zlib=/home/.../zlib-1.2.11/install
指定默认版本是5,连接zlib库的目录,注意zlib库目录要写绝对路径
发现配置出错
checking for va_copy() function... configure: error: in `/home/.../matio-1.5.12': configure: error: cannot run test program while cross compiling See `config.log' for more details
根据错误信息在configure文中查找错误发生处:
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for va_copy() function" >&5 $as_echo_n "checking for va_copy() function... " >&6; } if ${ac_cv_va_copy+:} false; then : $as_echo_n "(cached) " >&6
从中可知变量ac_cv_va_copy无法被自动配置上,所以:
echo ac_cv_va_copy=yes > arm-linux.cache ./configure --host=arm-none-linux-gnueabi --prefix=$PWD/install --with-default-file-ver=5 --cache-file=arm-linux.cache --with-zlib=/home/.../zlib-1.2.11/install
我们可以看到配置成功的显示输出:
matio配置成功最后,执行make
make && make install
进到install目录下面会看到四个目录:bin、include、lib、share。我们主要需要include头文件目录和lib库目录,里面有静态库和共享库。
三、Demo
由于项目中用到的是写mat文件,我们这里只展示一个写mat文件的例子,这个例子在matio_user_guide.pdf的2.3.3节,Writing Structure Arrays。
编写源码文件,main.c
#include <stdio.h>
#include <stdlib.h>
#include "matio.h"
int main(int argc,char **argv)
{
mat_t *matfp;
matvar_t *matvar, *field;
size_t dims[2] = {10,1}, struct_dims[2] = {2,1};
double x1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,10},
x2[10] = {11,12,13,14,15,16,17,18,19,20},
y1[10] = {21,22,23,24,25,26,27,28,29,30},
y2[10] = {31,32,33,34,35,36,37,38,39,40};
struct mat_complex_split_t z1 = {x1,y1}, z2 = {x2,y2};
const char *fieldnames[3] = {"x","y","z"};
unsigned nfields = 3;
matfp = Mat_CreateVer("test.mat",NULL,MAT_FT_DEFAULT);
if ( NULL == matfp )
{
fprintf(stderr,"Error creating MAT file \"test.mat\"\n");
return EXIT_FAILURE;
}
matvar = Mat_VarCreateStruct("a", 2,struct_dims,fieldnames,nfields);
if ( NULL == matvar )
{
fprintf(stderr,"Error creating variable for ’a’\n");
Mat_Close(matfp);
return EXIT_FAILURE;
}
/* structure index 0 */
field = Mat_VarCreate(NULL,MAT_C_DOUBLE,MAT_T_DOUBLE,2,dims,x1,0);
Mat_VarSetStructFieldByName(matvar,"x",0,field);
field = Mat_VarCreate(NULL,MAT_C_DOUBLE,MAT_T_DOUBLE,2,dims,y1,0);
Mat_VarSetStructFieldByName(matvar,"y",0,field);
field = Mat_VarCreate(NULL,MAT_C_DOUBLE,MAT_T_DOUBLE,2,dims,&z1,MAT_F_COMPLEX);
Mat_VarSetStructFieldByName(matvar,"z",0,field);
/* structure index 1 */
field = Mat_VarCreate(NULL,MAT_C_DOUBLE,MAT_T_DOUBLE,2,dims,x2,0);
Mat_VarSetStructFieldByName(matvar,"x",1,field);
field = Mat_VarCreate(NULL,MAT_C_DOUBLE,MAT_T_DOUBLE,2,dims,y2,0);
Mat_VarSetStructFieldByName(matvar,"y",1,field);
field = Mat_VarCreate(NULL,MAT_C_DOUBLE,MAT_T_DOUBLE,2,dims,&z2,MAT_F_COMPLEX);
Mat_VarSetStructFieldByName(matvar,"z",1,field);
Mat_VarWrite(matfp,matvar,MAT_COMPRESSION_NONE);
Mat_VarFree(matvar);
Mat_Close(matfp);
return EXIT_SUCCESS;
}
代码中大概能看明白,生成的文件名叫test.mat,里面有一个大结构数据叫a,a下面有两个小结构数据,每个小结构数据里面有x,y,z三维数组数据,下面我们来看一下,生成的文件结果是不是这样呢?
接下来进行交叉编译,注意编译时候一定要链接libz库。
然后把这个可执行程序放到板子上运行,把生成的mat格式文件拿出来,放到我们PC上用matlab软件查看一下:
test.mat结果正如我们代码中写的那样。
四、VS 编译 matio
源码目录下面有一个visual_studio目录,进去打开matio.sln,编译好之后就可以在PC下玩了(注意可能会依赖hdf5和zlib库)。不是我们重点,在这里不多做说明。
五、Ending
我不是正版“格列宁”(matlab),我是开源“格列宁”(matio) ——《我不是药神》
网友评论