python struct.pack和vs vs matlab fwrite

python struct.pack and write vs matlab fwrite

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

matlab

1
2
3
4
5
6
7
8
9
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的文件,这需要几秒钟的时间。

python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

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

我很乐意使用其他方法,只要标题和数据列可以有两种格式即可。


无需使用struct保存阵列。 numpy.ndarray有一种方便的方法可以将自己保存为二进制模式:ndarray.tofile。与创建具有与数组相同数量的元素的巨型字符串相比,以下命令应效率更高:

1
2
3
4
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应该创建一个视图(指向相同基础数据的package对象)而不是副本,因此此操作不会显着增加内存使用量。