如何将 .mat 二进制格式转换为 2D numpy 数组?

How to convert .mat binary format to 2D numpy array?

我正在将 hand_dataset 注释转换为可以在 YOLOv3 中使用的格式。注释采用 .mat 二进制格式,我想将其提取、转换和重组为 .csv。

我试过mat = scipy.io.loadmat(file),但提取数据的格式很奇怪。

mat = scipy.io.loadmat(file)
bboxes = np.transpose(mat['boxes'])

给出输出:

[[array([[(array([[488.42954942, 345.62261032]]), array([[461.57045058, 348.37738968]]), array([[465.57045058, 387.37738968]]), array([[492.42954942, 384.62261032]]))]],
      dtype=[('a', 'O'), ('b', 'O'), ('c', 'O'), ('d', 'O')])]

其中形状是 (2,1) 和 numpy.array 类型。

我能够像这样提取遍历整个数据集注释的点: points = np.array([point[0] for point in bboxes[0][0][0][0]])

层次结构是:

print(bboxes[0])
print(bboxes[0][0])
print(bboxes[0][0][0])
print(bboxes[0][0][0][0])
print(bboxes[0][0][0][0][0])
print(bboxes[0][0][0][0][0][0][1])

有没有"nicer"方法提取需要的点数?

给定打印的输出:

[[(array([[488.42954942, 345.62261032]]), array([[461.57045058, 348.37738968]]), array([[465.57045058, 387.37738968]]), array([[492.42954942, 384.62261032]]))]]
[(array([[488.42954942, 345.62261032]]), array([[461.57045058, 348.37738968]]), array([[465.57045058, 387.37738968]]), array([[492.42954942, 384.62261032]]))]
(array([[488.42954942, 345.62261032]]), array([[461.57045058, 348.37738968]]), array([[465.57045058, 387.37738968]]), array([[492.42954942, 384.62261032]]))
[[488.42954942 345.62261032]]
345.6226103157693

如有任何帮助,我们将不胜感激!谢谢!

这应该会给出更好的结果:

np.concatenate(bboxes[0][0].tolist()).squeeze()

我想我可以用

重新创建你的数组
In [38]: array=np.array 
In [43]: data = np.zeros((1,1),object)                                          
In [44]: data[0,0] = array([[(array([[488.42954942, 345.62261032]]), array([[461
    ...: .57045058, 348.37738968]]), array([[465.57045058, 387.37738968]]), arra
    ...: y([[492.42954942, 384.62261032]]))]], 
    ...:       dtype=[('a', 'O'), ('b', 'O'), ('c', 'O'), ('d', 'O')])          
In [45]: data                                                                   
Out[45]: 
array([[array([[(array([[488.42954942, 345.62261032]]), array([[461.57045058, 348.37738968]]), array([[465.57045058, 387.37738968]]), array([[492.42954942, 384.62261032]]))]],
      dtype=[('a', 'O'), ('b', 'O'), ('c', 'O'), ('d', 'O')])]],
      dtype=object)

这是一个 (1,1) 对象数据类型数组,其中包含另一个数组。该数组也是 (1,1) 形状,但具有复合数据类型(structured 数组)。

In [51]: data.shape, data.dtype                                                 
Out[51]: ((1, 1), dtype('O'))

在 MATLAB 中,一切都是二维的。 loadmat 有一个 squeeze 参数可以告诉它删除不必要的尺寸。如果没有它,我们会得到很多 (1,1) 形状的数组。

cellstruct 这样的 MATLAB 对象被 return 编辑为某种类型的对象 dtype 数组。常规 MATLAB 矩阵是 returned 数字 numpy 数组。

我们可以使用二维索引从 data 中提取一个元素(比 data[0][0] 更惯用):

In [52]: data1 = data[0,0]                                                      
In [53]: data1.shape, data1.dtype                                               
Out[53]: ((1, 1), dtype([('a', 'O'), ('b', 'O'), ('c', 'O'), ('d', 'O')]))

item() 也可以从数组中删除一项:

In [54]: data.item().dtype                                                      
Out[54]: dtype([('a', 'O'), ('b', 'O'), ('c', 'O'), ('d', 'O')])

在此级别,数组是一个结构化数组,具有 4 个(命名的)字段,每个对象 dtype。

字段(通常)按名称索引。但是作为对象数据类型,我们还有另一层:

In [74]: data1['a']                                                             
Out[74]: array([[array([[488.42954942, 345.62261032]])]], dtype=object)
In [75]: data1['a'].item()                                                      
Out[75]: array([[488.42954942, 345.62261032]])
In [76]: data1['a'].item().squeeze()                                            
Out[76]: array([488.42954942, 345.62261032])

@aparpara 使用 tolist() 的想法可能是提取那些嵌套对象字段的最干净的方法:

In [85]: data1.tolist()                                                         
Out[85]: 
[[(array([[488.42954942, 345.62261032]]),
   array([[461.57045058, 348.37738968]]),
   array([[465.57045058, 387.37738968]]),
   array([[492.42954942, 384.62261032]]))]]

在结构化数组上 tolist() 创建一个元组列表(或嵌套列表),每个 'record' 个数组一个元组。

然后我们可以使用np.arrayconcatenate将数组合并为一个,并使用squeeze删除多余的维度:

In [87]: np.array(data1.tolist()).squeeze()                                     
Out[87]: 
array([[488.42954942, 345.62261032],
       [461.57045058, 348.37738968],
       [465.57045058, 387.37738968],
       [492.42954942, 384.62261032]])

MATLAB 源代码不是简单的二维数字矩阵。因此,翻译成另一种语言也不是一件容易的事。一些loadmat参数可以简化return结构。除此之外,我们必须通过层层深入,使用 item[0,0] 类型的索引。