【问题标题】:How to convert .mat binary format to 2D numpy array?如何将 .mat 二进制格式转换为 2D numpy 数组?
【发布时间】:2020-02-04 00:02:12
【问题描述】:

我正在将 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')])]

其中 shape 为 (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])

是否有任何“更好”的方法来提取所需的点?

给定打印的输出:

[[(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

任何帮助将不胜感激!谢谢!

【问题讨论】:

  • 有一个squeeze 参数。

标签: python numpy mat-file


【解决方案1】:

我想我可以用

重新创建你的数组
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) 对象 dtype 数组,其中包含另一个数组。该数组也是 (1,1) 形状,但具有复合 dtype(structured 数组)。

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

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

cellstruct 等 MATLAB 对象作为某种对象 dtype 数组返回。常规 MATLAB 矩阵返回一个数字 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。

字段(通常)按名称索引。但是作为 object 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 使用 to 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() 上创建一个元组列表(或嵌套列表),每个数组“记录”一个元组。

然后我们可以使用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 参数可以简化返回结构。除此之外,我们必须通过item[0,0] 类型的索引逐层向下工作。

【讨论】:

  • 非常感谢,我正在寻找这样的答案!刚刚在其他一些 MATLAB 格式的论坛上迷路了,谢谢。
【解决方案2】:

这应该会产生更好的结果:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 2017-05-15
    • 2013-06-30
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    相关资源
    最近更新 更多