python struct.pack和write vs matlab fwrite

时间:2017-02-07 15:56:07

标签: python matlab numpy memory struct

我正在尝试将这段matlab代码移植到python

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中,150MB的文件需要几秒钟。

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返回的二进制文件相比,它们是相同的。然而,对于150MB的文件,它需要几秒钟并且倾向于耗尽所有内存(在链接的图像中我停止执行以避免它,但你可以看到它是如何构建的!)。

see memory usage

这对我来说没有意义,因为我在15GB的RAM PC上运行该功能。为什么150MB文件处理需要如此多的内存?

我很乐意使用不同的方法,只要标题和数据列有两种格式。

1 个答案:

答案 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应该创建一个视图(指向相同底层数据的包装器对象)而不是副本,因此您的内存使用量不应该从此操作中显着增加。