2015-11-03 225 views
4

我想讀取以下網站ufldl.stanford.edu/housenumbers中給出的mat文件,文件train.tar.gz中有一個mat文件名爲digitStruct.mat。如何在python中讀取Mat v7.3文件?

當我使用scipy.io來讀取mat文件時,它告訴我'請使用hdf reader for matlab v7.3文件'。

原始MATLAB文件被提供作爲下面

load digitStruct.mat 
for i = 1:length(digitStruct) 
    im = imread([digitStruct(i).name]); 
    for j = 1:length(digitStruct(i).bbox) 
     [height, width] = size(im); 
     aa = max(digitStruct(i).bbox(j).top+1,1); 
     bb = min(digitStruct(i).bbox(j).top+digitStruct(i).bbox(j).height, height); 
     cc = max(digitStruct(i).bbox(j).left+1,1); 
     dd = min(digitStruct(i).bbox(j).left+digitStruct(i).bbox(j).width, width); 

     imshow(im(aa:bb, cc:dd, :)); 
     fprintf('%d\n',digitStruct(i).bbox(j).label); 
     pause; 
    end 
end 

如上所示,墊子文件具有鍵「digitStruct」和「digitStruct」內,鍵「名稱」和「BBOX」,可以發現,我用h5py API來讀取文件。

import h5py 
f = h5py.File('train.mat') 
print len(f['digitStruct']['name']), len(f['digitStruct']['bbox'] ) 

我可以讀取數組,但是當我循環訪問數組時,如何讀取每個項目?

for i in f['digitStruct']['name']: 
    print i # only print out the HDF5 ref 
+0

嘿,你有解決方案嗎?我也有同樣的問題。謝謝 –

回答

4

寫在Matlab:

test = {'Hello', 'world!'; 'Good', 'morning'; 'See', 'you!'}; 
save('data.mat', 'test', '-v7.3') % v7.3 so that it is readable by h5py 

enter image description here

閱讀Python中(適用於任何數量或行或列,但假定每個單元是一個字符串):

import h5py 
import numpy as np 

data = [] 
with h5py.File("data.mat") as f: 
    for column in f['test']: 
     row_data = [] 
     for row_number in range(len(column)):    
      row_data.append(''.join(map(unichr, f[column[row_number]][:]))) 
     data.append(row_data) 

print data 
print np.transpose(data) 

輸出:

[[u'Hello', u'Good', u'See'], [u'world!', u'morning', u'you!']] 

[[u'Hello' u'world!'] 
[u'Good' u'morning'] 
[u'See' u'you!']] 
1
import numpy as np 
import cPickle as pickle 
import h5py 

f = h5py.File('train/digitStruct.mat') 

metadata= {} 
metadata['height'] = [] 
metadata['label'] = [] 
metadata['left'] = [] 
metadata['top'] = [] 
metadata['width'] = [] 

def print_attrs(name, obj): 
    vals = [] 
     if obj.shape[0] == 1: 
      vals.append(int(obj[0][0])) 
     else: 
      for k in range(obj.shape[0]): 
       vals.append(int(f[obj[k][0]][0][0])) 
     metadata[name].append(vals) 

for item in f['/digitStruct/bbox']: 
    f[item[0]].visititems(print_attrs) 

with open('train_metadata.pickle','wb') as pf: 
    pickle.dump(metadata, pf, pickle.HIGHEST_PROTOCOL)  

我修改了它從https://discussions.udacity.com/t/how-to-deal-with-mat-files/160657/3。老實說,我無法弄清楚visititmes()究竟是怎麼回事。 HDF5文件太分級,太抽象。

該元數據是一個字典。每個密鑰的內容都是嵌入式數組。該數組有33402個項目,它們與具有名稱的png文件相對應。每個項目是一個長度爲1〜6的數組。我計算不同數字的數字,即5137,18130,8691,1434,9,1。

令我驚訝的是,pickle文件只有9 MB,比mat文件小20多倍。我猜HDS文件犧牲了層次結構的存儲空間。

注意:爲了切分圖像,我已將值轉換爲整數。現在train_metadata.pickle文件的大小隻有2 MB,是mat文件的100倍。