使用h5py读取Matlab .mat文件

3

我想使用Python3包h5py读取Matlab版本7.3的.mat文件。

它包含一个在Matlab中命名为results的变量。

它包含一个1*1的cell,里面的struct的值是我需要的。

在Matlab中,我可以通过以下代码获取这些数据:

load('.mat PATH');
results{1}.res

我该如何使用h5py读取这些数据?示例.mat文件可以从这里获取。

3个回答

2

虽然 h5py 可以从 MATLAB 读取 h5 文件,但是要了解其中的内容需要一些探索——查看 keysgroupsdatasets(还可能是属性)。没有任何 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]])

在操作系统的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')

0
如果您的问题是一般性地询问如何在Python中读取使用v7.3保存的mat文件,那么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中访问的单元格内嵌套的单元格(例如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,在这些情况下更快,我将在另一个答案中讨论它。


0

正如我在关于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)

请注意,与包一样,在Matlab中的单元格(使用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.2hdf5storage 似乎不能处理这些文件(我的自定义加载程序需要约 1.5 分钟,而 hdf5storage 需要超过 10 分钟才能加载完毕(在10分钟后它仍未加载完成)。)(我要注意到,1.5 分钟的时间仍然远远不及 Matlab 自己的小于 15 秒的加载时间,因此还有改进的空间...)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接