Arrays 更快地转换数据(从字节到3D numpy阵列)
我必须读取一个二进制文件,其中包含1300个320*256 uint8像素的图像,并将其转换为numpy数组。使用struct.unpack从字节转换数据的格式如下:Arrays 更快地转换数据(从字节到3D numpy阵列),arrays,numpy,type-conversion,byte,python-3.6,Arrays,Numpy,Type Conversion,Byte,Python 3.6,我必须读取一个二进制文件,其中包含1300个320*256 uint8像素的图像,并将其转换为numpy数组。使用struct.unpack从字节转换数据的格式如下:b'\xbb\x17\xb4\x17\xe2\x17\xc3\x17\xd3\x17'。保存的数据如下表所示: Main header / Frame header1 / Frame1 / Frame header2 / Frame2 / etc. 对不起,我不能把文件给你 编辑:代码的新版本(在操作过程中使用3Go,最终在RA
b'\xbb\x17\xb4\x17\xe2\x17\xc3\x17\xd3\x17'
。保存的数据如下表所示:
Main header / Frame header1 / Frame1 / Frame header2 / Frame2 / etc.
对不起,我不能把文件给你
编辑:代码的新版本(在操作过程中使用3Go,最终在RAM中使用1,5Go)——感谢Paul
import struct, numpy as np, matplotlib.pyplot as plt
filename = 'blabla'
with open(filename, mode="rb") as f:
# Initialize variables
width = 320
height = 256
frame_nb_octet = width * height * 2
count_frame = 1300
fmt = "<" + "H" * width * height # little endian and unsigned short
main_header_size = 4000
frame_header_size = 100
data = []
tab = []
# Read all images (<=> all the file to read once)
data.append(f.read())
data = data[0]
# -------------- BEFORE --------------
# # Convert bytes into int (be careful to pass main/fram headers)
# for indice in range(count_frame):
# ind_start = main_header_size + indice * (frame_header_size + frame_nb_octet) + frame_header_size
# ind_end = ind_start + frame_nb_octet
# tab.append(struct.unpack(fmt, data[ind_start:ind_end]))
# images = np.resize(np.array(tab), (count_frame, height, width))
# ------------------------------------
# Convert bytes into float (because after, mean, etc) passing main/frame headers
dt = np.dtype(np.uint16)
dt = dt.newbyteorder(('<'))
array = np.empty((frame_nb_octet, count_frame), dtype=float)
for indice in range(count_frame):
offset = main_header_size + indice * (frame_header_size + frame_nb_octet) + frame_header_size
array[:, indice] = np.frombuffer(data, dtype=dt, count=frame_nb_octet, offset=offset)
array = np.resize(array, (height, width, count_frame))
# Plotting first image to verify data
fig = plt.figure()
# plt.imshow(np.squeeze(images[0, :, :]))
plt.imshow(np.squeeze(array[:, :, 0]))
plt.show()
import struct,numpy作为np,matplotlib.pyplot作为plt
文件名='blabla'
将open(filename,mode=“rb”)作为f:
#初始化变量
宽度=320
高度=256
帧\u nb\u八位字节=宽度*高度*2
计数/帧=1300
fmt=“尝试内存映射:
dtype = [('headers', np.void, frame_header_size), ('frames', '<u2', (height, width))]
mmap = np.memmap(filename, dtype, offeset=main_header_size)
array = mmap['frames']
这就剩下了帧数据和帧头。幸运的是,每个帧和帧头都有相同的大小,所以我们可以用结构化的数据类型来描述它们。我们对帧头不太感兴趣,所以我们给它们指定大小的无效数据类型。对于数据本身,我们有height*width
值,我们使用了一个方便的子数组格式。我们使用typestring您很可能不需要使用struct.unpack
trynp.frombuffer(buf,dtype)
直接在bytes
对象上。你的解决方案更快。是的。我用新版本编辑了我的帖子。在阅读过程中仍然3进入RAM,所以我必须在阅读之前检查内存。其他想法?:d抱歉延迟。numpy memmap的官方文档没有提到你的方法。你能解释一下吗你在做什么?因为在我的二进制文件中,我必须在每个帧之间跳过一个帧头,我不知道如何将它应用到你的解决方案中。谢谢你,我先试试你的代码:1ms,250Mo在RAM中。Just:OMG谢谢。你能解释一下它是如何工作的吗?只是为了理解并在以后需要时复制另一个示例。我添加了一个解释初始化。请注意,memmap
看起来非常快,因为它实际上并没有加载任何数据。它只是创建了一个从磁盘上的一个位置到RAM中地址的映射。只有当您尝试使用数据时,例如,.astype(float)
才会透明地从磁盘中提取数据。非常感谢。请确保,当您说“get pull”时“,这意味着Python正在复制原始数据?不,内存映射不是副本,它仍然是与磁盘上的文件相同的文件,只是以一种特殊的方式访问,就好像它是RAM一样。”。对memmap所做的任何更改最终都会写入磁盘(除非操作系统崩溃)。
fh = open(filename, 'rb')
fh.seek(main_header_size)
data = np.fromfile(fh, our_structured_dtype)