Как преобразовать двоичный формат .mat в двумерный массив? - PullRequest
1 голос
/ 06 октября 2019

Я конвертирую 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])

Есть ли "более приятный" способ извлечения необходимых точек?

Вывод из заданных отпечатков:

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

Любойпомощь была бы признательна! Спасибо!

Ответы [ 2 ]

0 голосов
/ 06 октября 2019

Я думаю, что могу воссоздать ваш массив с помощью

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) форму, но с составным типом d (массив structured).

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

В MATLAB все равно 2d. loadmat имеет параметр squeeze, который может указывать на удаление ненужных измерений. Без этого мы получаем множество (1,1) массивов.

Объекты MATLAB, такие как cell и struct, возвращаются в виде массивов типа d объекта. Обычные матрицы 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.

Поля(обычно) индексируются по имени. Но, будучи объектом 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() создает список (или вложенный список) кортежей, один кортеж на «запись» массива.

Затем мы можем использовать np.array или concatenate, чтобы объединить массивы в один,и 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].

0 голосов
/ 06 октября 2019

Это должно дать лучший результат:

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