在 Python 中读取 .mat 文件

Posted

技术标签:

【中文标题】在 Python 中读取 .mat 文件【英文标题】:Read .mat file in Python 【发布时间】:2020-11-03 17:00:59 【问题描述】:

我知道如何通过 Python 从附件 (URL) 中调用任何数据,除了与名称“ROI”相关的任何数据。例如,您可以检查“data_dic_save/displacements/roi_ref_formatted”。我想在我的工作中使用来自这条路径的数据(如掩码和区域)。但是,我无法打开(阅读)它们。你能帮帮我吗?

.mat 文件的 URL: https://www.dropbox.com/s/127vo3uew0fppw5/res.mat?dl=0

代码:

with h5py.File('~/res.mat', 'r') as f:
    d = f.get('data_dic_save/displacements/roi_ref_formatted')
    print(d.attrs['mask'])

错误信息:

KeyError: "Can't open attribute (can't locate attribute: 'mask')"

【问题讨论】:

这是一个有效的问题。您的数据集 (data_dic_save/displacements/roi_ref_formatted) 没有名为 mask 的属性。这就是你得到错误的原因。可以通过print (d.attrs.__contains__('mask'))确认,其实这个数据集没有任何属性。 亲爱的kcw78,感谢您的回复。但是,如何从“roi_ref_formatted”读取数据?我在 Matlab 中检查了这个文件,并从这个路径中得到了很多信息。但我需要用 Python 解析这个文件... 您的数据集 (roi_ref_formatted) 是形状为 (54,1) 的对象引用数组。使用print (d.dtype, d.shape) 进行确认。保存为 HDF5 的 MATLAB 很复杂。它使用指向文件中其他对象的对象引用。要查看它是如何工作的,print (f[ d[0,0] ]) 你会得到HDF5 dataset "Lj",它是指向f['/#refs#/Lj'] 的对象引用你可以通过比较print (f['/#refs#/Lj'][:])print (f[ d[0,0] ][:]) 来看到这一点 我检查了您的建议并得到以下信息:object (54, 1) [[3707764736 2 1 1 110 1]] [[3707764736 2 1 1 110 1]] 但是,Matlab 得到了另一个结果(截图见附件链接)。为什么我会得到这些奇怪的值??? dropbox.com/sh/1uli6oeq9yzrn1r/AAAUI0qnymY1qoNRfok9J_Yva?dl=0 警告:我不是 MATLAB 或对象引用方面的专家。我所知道的一切都是通过反复试验学到的。我无法回答你的“为什么”问题。 MATLAB 使用一种复杂的方法以 HDF5 格式存储数据(大量的对象引用)。我用 HDFVIEW 打开了你的 .mat 文件。 displacements 组中的所有数据集都是 54X1 对象引用数组。 strains 组中的所有数据集也是如此。我怀疑dispinfostraininfo 组中的数据集提供了映射。我在#refs# 数据集中找到了regionsize_mask 数据。 【参考方案1】:

这个答案是从我上面的 cmets 收集的,以及关于读取保存为 HDF5 的 MATLAB 文件的一些额外见解。坦率地说,它比典型的 HDF5 文件更复杂。

首先,让我们解决您在读取mask 属性时的错误。数据集 data_dic_save/displacements/roi_ref_formatted 没有名为 mask 的属性。这就是你得到错误的原因。您可以通过以下方式确认:

print (d.attrs.__contains__('mask')) 

事实上,这个数据集没有任何属性。以下代码将遍历对象d的所有属性,然后打印属性名称和值:

for name in d.attrs.__iter__():
    print (name, h5f.attrs[name])

现在,我们来谈谈 HDF5 格式的 MATLAB 文件。 (警告:我不是 MATLAB 或对象引用方面的专家。我所知道的一切都是通过反复试验学到的)。

我使用 The HDF GroupHDFVIEW 打开了您的 .mat 文件。在开始使用 HDF5 时,我认为这是一个必不可少的工具,因为它可以让您在 GUI 中“查看”文件的架构和数据。 (坦率地说,这是我找出 .mat 文件内容的唯一方法。它们不像大多数 HDF5 文件那样具有自我描述性。)本文末尾有您文件的快照供参考。

displacements 组中的所有数据集都是 54X1 对象引用数组。 strains 组中的所有数据集也是如此。我怀疑dispinfostraininfo 组中的数据集提供了某种映射。另外,我在#refs#/XX数据集中发现了regionsize_mask数据。

您应该阅读 h5py 文档以了解有关对象引用的详细信息。 参考:h5py Object Reference doc

以下是使用您的文件的简要说明。

下面的调用将d 作为形状(54,1) 和dtype object 的NumPy 数组返回。打印语句确认相同。

d = f.get('data_dic_save/displacements/roi_ref_formatted')
print (d.dtype, d.shape)
object (54, 1)

对象引用指向文件中的其他对象。要查看它是如何工作的,请打印d 中的第一个数组条目,您将获得对数据集Lj 的引用(将在组/#refs# 中)。你可以看到Lj 数据集是一个NumPy 数组,形状为(1,6),类型为u4(无符号整数)。

print (f[ d[0,0] ]) 
<HDF5 dataset "Lj": shape (1, 6), type "<u4">

这意味着以下 2 个语句指向同一个对象并产生相同的结果:

print (f['/#refs#/Lj'][:])
[[3707764736          2          1          1        110          1]]
print (f[  d[0,0] ][:])
[[3707764736          2          1          1        110          1]]    

此时,我无法解释您的其余数据。以下是一些可能对您有所帮助的其他答案。

此 SO Q&A 提供了有关读取 .mat 文件的基本说明:read-matlab-v7-3-file-into-python-list-of-numpy-arrays-via-h5py

我写了一个更完整的解释(用于阅读 SVHN 数据集)。您可以在这里访问它:what-is-the-difference-between-the-two-ways-of-accessing-the-hdf5-group-in-svhn

【讨论】:

以上是关于在 Python 中读取 .mat 文件的主要内容,如果未能解决你的问题,请参考以下文章

python 笔记:读取mat文件

在 python 中读取 v 7.3 mat 文件

python中读取mat文件

Python读取mat文件

在 Python 中读取 .mat 文件。但是数据的形状发生了变化

python读取mat文件