2017-02-07 13 views
2

Я пытаюсь порта этот бит MatLab код на Pythonпитон struct.pack и писать против MatLab FWRITE

MatLab

function write_file(im,name) 
fp = fopen(name,'wb'); 

M = size(im); 

fwrite(fp,[M(1) M(2) M(3)],'int'); 
fwrite(fp,im(:),'float'); 

fclose(fp); 

где im является 3D-матрицу. Насколько я понимаю, функция сначала записывает двоичный файл со строкой заголовка, содержащей размер матрицы. Заголовок состоит из 3 целых чисел. Затем im записывается как один столбец поплавков. В Matlab это занимает несколько секунд для файла размером 150 МБ.

питона

import struct 
import numpy as np 
def write_image(im, file_name): 

    with open(file_name, 'wb') as f: 
     l = im.shape[0]*im.shape[1]*im.shape[2] 

     header = np.array([im.shape[0], im.shape[1], im.shape[2]]) 
     header_bin = struct.pack("I"*3, *header) 
     f.write(header_bin) 

     im_bin = struct.pack("f"*l,*np.reshape(im, (l,1), order='F')) 
     f.write(im_bin) 
    f.close() 

, где im является Numpy массив. Этот код работает хорошо, поскольку я сравнивал с двоичным кодом, возвращаемым matlab, и они одинаковы. Однако для файла с 150 МБ требуется несколько секунд и, как правило, выгружает всю память (в связанном изображении я остановил выполнение, чтобы избежать его, но вы можете увидеть, как он создается!).

see memory usage

Это не имеет смысла для меня, как я бегу функцию на 15GB оперативной памяти компьютера. Почему при обработке файлов на 150 МБ требуется так много памяти?

Я был бы рад использовать другой метод, насколько возможно иметь два формата для заголовка и столбца данных.

+0

Нет необходимости в продукте: 'l = im.size' –

+0

Что такое' header'? –

+0

Кроме того, да, вы создали строку того же размера, что и все изображение, а затем скопировали все изображение. Да, это будет сосать тебя сухим. –

ответ

1

Нет необходимости использовать struct, чтобы сохранить ваш массив. numpy.ndarray имеет удобный способ для сохранения себя в двоичном режиме: ndarray.tofile. Следующий должен быть гораздо более эффективным, чем создание гигантской строки с тем же числом элементов, как ваш массив:

def write_image(im, file_name): 
    with open(file_name, 'wb') as f: 
     np.array(im.shape).tofile(f) 
     im.T.tofile(f) 

tofile всегда сохраняет в строке-мажорный порядке C, в то время как MATLAB использует столбцам Fortran заказа. Самый простой способ обойти это - сохранить транспонирование массива. В общем случае ndarray.T должен создать представление (объект-обертку, указывающее на одни и те же базовые данные) вместо копии, поэтому использование вашей памяти не должно заметно увеличиваться с этой операции.

+1

определенно делает трюк! спасибо Я только что изменил последнюю строку как 'im.astype ('f'). T.tofile (f)' так, чтобы массив находился в float32 – amelies