使用 h5py 读取 matlab .mat 文件
Posted
技术标签:
【中文标题】使用 h5py 读取 matlab .mat 文件【英文标题】:Read a matlab .mat file using h5py 【发布时间】:2021-02-23 04:19:55 【问题描述】:我想使用 Python3 包 h5py 读取 7.3 版本的 matlab .mat 文件。
它包含一个matlab中的变量,名为results。
里面包含一个1*1的cell,里面struct里面的值就是我需要的。
在matlab中,我可以通过以下代码获取这些数据:
load('.mat PATH');
results1.res
我应该如何在 h5py 中读取这些数据? 示例.mat文件可以从here获取
【问题讨论】:
【参考方案1】:虽然 h5py
可以从 MATLAB 读取 h5
文件,但要弄清楚其中的内容需要一些探索 - 查看 keys
groups
和 datasets
(可能还有 attr)。 scipy
中没有任何内容可以帮助您(scipy.io.loadmat
用于旧的 MATLAB mat 格式)。
使用下载的文件:
In [61]: f = h5py.File('Downloads/Basketball_ECO_HC.mat','r')
In [62]: f
Out[62]: <HDF5 file "Basketball_ECO_HC.mat" (mode r)>
In [63]: f.keys()
Out[63]: <KeysViewHDF5 ['#refs#', 'results']>
In [65]: f['results']
Out[65]: <HDF5 dataset "results": shape (1, 1), type "|O">
In [66]: arr = f['results'][:]
In [67]: arr
Out[67]: array([[<HDF5 object reference>]], dtype=object)
In [68]: arr.item()
Out[68]: <HDF5 object reference>
我必须检查h5py
文档,看看是否可以进一步检查该对象引用。我不熟悉。
但探索其他key
:
In [69]: list(f.keys())[0]
Out[69]: '#refs#'
In [70]: f[list(f.keys())[0]]
Out[70]: <HDF5 group "/#refs#" (2 members)>
In [71]: f[list(f.keys())[0]].keys()
Out[71]: <KeysViewHDF5 ['a', 'b']>
In [72]: f[list(f.keys())[0]]['a']
Out[72]: <HDF5 dataset "a": shape (2,), type "<u8">
In [73]: _[:]
Out[73]: array([0, 0], dtype=uint64)
In [74]: f[list(f.keys())[0]]['b']
Out[74]: <HDF5 group "/#refs#/b" (7 members)>
In [75]: f[list(f.keys())[0]]['b'].keys()
Out[75]: <KeysViewHDF5 ['annoBegin', 'fps', 'fps_no_ftr', 'len', 'res', 'startFrame', 'type']>
In [76]: f[list(f.keys())[0]]['b']['fps']
Out[76]: <HDF5 dataset "fps": shape (1, 1), type "<f8">
In [77]: f[list(f.keys())[0]]['b']['fps'][:]
Out[77]: array([[22.36617883]])
在 OS shell 中,我可以使用h5dump
查看文件。由此看来,res
数据集的数据最多。数据集也有属性。这可能是获得概览的更好方法,并使用它来指导 h5py
加载。
In [80]: f[list(f.keys())[0]]['b']['res'][:]
Out[80]:
array([[198., 196., 195., ..., 330., 328., 326.],
[214., 214., 216., ..., 197., 196., 192.],
[ 34., 34., 34., ..., 34., 34., 34.],
[ 81., 81., 81., ..., 81., 80., 80.]])
In [81]: f[list(f.keys())[0]]['b']['res'][:].shape
Out[81]: (4, 725)
In [82]: f[list(f.keys())[0]]['b']['res'][:].dtype
Out[82]: dtype('<f8')
【讨论】:
【参考方案2】:如果您的问题一般是询问如何在 Python 中读取使用 v7.3 保存的 matfile,hdf5storage 包提供了一些可能对您有用的实用程序。对于您的文件(安装软件包后),您将运行
In [0]: import hdf5storage as hdf5
In [1]: pyIn = LoadMatFile('Basketball_ECO_HC.mat')
In [2]: type(pyIn)
Out[2]: dict
In [3]: pyIn.keys()
Out[3]: dict_keys(['results'])
In [4]: type(pyIn['results'])
Out[4]: numpy.ndarray
In [5]: pyIn['results'].shape
Out[5]: (1, 1)
In [6]: pyIn['results'].dtype
Out[6]: dtype('O')
In [7]: pyIn['results'][0,0].dtype
Out[7]: dtype([('type', '<U4', (1, 1)), ('res', '<f8', (725, 4)), ('fps', '<f8', (1, 1)), ('fps_no_ftr', '<f8', (1, 1)), ('len', '<f8', (1, 1)), ('annoBegin', '<f8', (1, 1)), ('startFrame', '<f8', (1, 1))])
您可以看到它在解析输入数组方面做得很好,尽管它可以将您在 Matlab 中使用 results11
访问的单元格中的单元格折叠成您使用 @ 访问的二维 numpy 数组987654324@ 代替。我遇到的另一个奇怪的事情是在更深的结构字段中添加了一个维度,如下所示:
In [8]: pyIn['results'][0,0]['res'].shape
Out[8]: (1, 725, 4)
In [9]: pyIn['results'][0,0]['res'][0,0,:]
Out[9]: array([198., 214., 34., 81.])
不完全确定为什么会发生这种情况,但总的来说应该可以正常工作。
也就是说,我确实遇到了这个软件包的最新版本 (0.2
) 的问题,对于真正深的数组/单元格/结构组合,它变得异常缓慢。好消息是该软件包仍在维护中,因此可能正在对此进行修复。尽管如此,这促使我为 matfiles 编写自己的 h5py 阅读器,这在这些情况下更快,我将作为另一个答案讨论它。
【讨论】:
【参考方案3】:正如我在关于 hd5fstorage 包的另一篇文章中提到的,我遇到了加载深度数组时速度太慢的问题。所以我实现了my own matfile loader,如果您关心如何将 v7.3 matfile 读入 Python 工作的细节,它的代码也可能更有用(因为它很紧凑)。 (也就是说,代码目前只有很少的 cmets,所以可能没那么有用。)
对于我的库,输出与hdf5storage
非常相似,如下所示。
In [0]: from MatFileMethods import LoadMatFile
In [1]: pyIn = LoadMatFile('/Users/emilio/Downloads/Basketball_ECO_HC.mat')
In [2]: type(pyIn)
Out[2]: dict
In [3]: pyIn.keys()
Out[3]: dict_keys(['results'])
In [4]: type(pyIn['results'])
Out[4]: numpy.ndarray
In [5]: pyIn['results'].shape
Out[5]: (1, 1)
请注意,与hdf5storage
包一样,Matlab 中使用results11
调用的cell-within-a-cell 变成了使用pyIn['results'][0,0]
调用的二维numpy.ndarray
,如下所示。
In [6]: type(pyIn['results'][0,0])
Out[6]: dict
In [7]: pyIn['results'][0,0].keys()
Out[7]: dict_keys(['annoBegin', 'fps', 'fps_no_ftr', 'len', 'res', 'startFrame', 'type'])
In [8]: pyIn['results'][0,0]['res'].shape
Out[8]: (725, 4)
In [9]: pyIn['results'][0,0]['res'][0,:]
Out[9]: array([198., 214., 34., 81.])
与hdf5storage
相比,我选择将Matlab 结构制作成Python dicts,这样结构的字段就是字典的键。
在任何情况下,这个模块都没有经过全面测试,但对于加载 ~500Mb 和 hdf5storage
版本 0.2
似乎无法处理的更大 mat 文件(我的自己的装载机与hdf5storage
的 >10 分钟加载时间(它在 10 分钟时还没有完成加载))。 (我会注意到,与 Matlab 自己的
【讨论】:
以上是关于使用 h5py 读取 matlab .mat 文件的主要内容,如果未能解决你的问题,请参考以下文章