我想使用Python3包h5py读取Matlab版本7.3的.mat文件。
它包含一个在Matlab中命名为results的变量。
它包含一个1*1的cell,里面的struct的值是我需要的。
在Matlab中,我可以通过以下代码获取这些数据:
load('.mat PATH');
results{1}.res
我该如何使用h5py读取这些数据?示例.mat文件可以从这里获取。
虽然 h5py
可以从 MATLAB 读取 h5
文件,但是要了解其中的内容需要一些探索——查看 keys
、groups
和 datasets
(还可能是属性)。没有任何 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>
我需要查看文档,以便进一步检查该对象的引用。 我对此不太熟悉。
但是可以探索其他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]])
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')
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中访问的单元格内嵌套的单元格(例如results{1}{1}
)折叠成一个二维numpy数组,你需要使用pyIn['results'][0,0]
来访问。我在处理这些数据时遇到的另一个奇怪的问题是,在更深层次的结构字段中添加了一个维度,如下所示:
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
)时遇到了一个问题,当数组/单元格/结构组合嵌套非常深时,它变得异常缓慢。好消息是,这个包仍在维护中,因此对此进行修复可能已在计划中。尽管如此,这促使我编写了自己的 h5py 读取器,用于 matfiles,在这些情况下更快,我将在另一个答案中讨论它。
正如我在关于hd5fstorage包的另一篇文章中所提到的,当它加载深层数组时,我遇到了速度过慢的问题。因此,我实现了自己的matfile加载器,其代码也可能更有用(因为它很紧凑),如果您关心将v7.3 matfile读入Python的具体方式的话。(话虽如此,目前这段代码很少有注释,因此可能并不是那么有用。)
对于我的库而言,输出与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)
results {1} {1}
调用)成为二维numpy.ndarray
,可以使用以下方式调用:pyIn ['results'] [0,0]
。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 字典,以便结构的字段成为字典的键。
无论如何,该模块并未经过充分测试,但对于加载约 500Mb 及更大的 mat 文件,它已经可以很好地使用了,而版本 0.2
的 hdf5storage
似乎不能处理这些文件(我的自定义加载程序需要约 1.5 分钟,而 hdf5storage
需要超过 10 分钟才能加载完毕(在10分钟后它仍未加载完成)。)(我要注意到,1.5 分钟的时间仍然远远不及 Matlab 自己的小于 15 秒的加载时间,因此还有改进的空间...)