是否有可能在磁盘上保存布尔numpy数组为每个元素1bit与memmap支持?



是否可以将numpy数组保存在布尔格式的磁盘上,每个元素只需要1位?这个答案建议使用packbits和unpackbits,但是从文档来看,这似乎不支持内存映射。是否有一种方法可以在磁盘上存储1bit数组与memmap支持?

memmap需求的原因:我正在全高清(1920x1080)图像数据库上训练我的神经网络,但我在每次迭代中随机裁剪出一个256x256补丁。由于读取完整的图像非常耗时,所以我使用memmap只读取所需的补丁。现在,我想使用二进制蒙版与我的图像,因此这个要求。

numpy不支持每元素1位数组,我怀疑memmap有这样的功能。但是,有一个使用packbits的简单解决方案。

由于您的case不是按位随机访问,因此您可以将其读取为每个元素数组1字节。

# A binary mask represented as an 1 byte per element array.
full_size_mask = np.random.randint(0, 2, size=[1920, 1080], dtype=np.uint8)
# Pack mask vertically.
packed_mask = np.packbits(full_size_mask, axis=0)
# Save as a memmap compatible file.
buffer = np.memmap("./temp.bin", mode='w+',
dtype=packed_mask.dtype, shape=packed_mask.shape)
buffer[:] = packed_mask
buffer.flush()
del buffer
# Open as a memmap file.
packed_mask = np.memmap("./temp.bin", mode='r',
dtype=packed_mask.dtype, shape=packed_mask.shape)
# Rect where you want to crop.
top = 555
left = 777
width = 256
height = 256
# Read the area containing the rect.
packed_top = top // 8
packed_bottom = (top + height) // 8 + 1
packed_patch = packed_mask[packed_top:packed_bottom, left:left + width]
# Unpack and crop the actual area.
patch_top = top - packed_top * 8
patch_mask = np.unpackbits(packed_patch, axis=0)[patch_top:patch_top + height]
# Check that the mask is cropped from the correct area.
print(np.all(patch_mask == full_size_mask[top:top + height, left:left + width]))

注意,这个解决方案可以(很可能会)读取额外的位。具体来说,两端最多7位。在您的情况下,它将是7x2x256位,但这只占补丁的5%左右,所以我认为它可以忽略不计。

顺便说一下,这不是你问题的答案,但是当你处理二进制掩码时,比如用于图像分割的标签,用zip压缩可能会大大减少文件大小。每个图像(而不是每个补丁)可以减少到小于8 KB。您也可以考虑一下这个选项。

最新更新