Python:读取 12 位二进制文​​件

标签 python python-3.x binary unpack

我正在尝试使用 Python 3 读取包含图像(视频)的 12 位二进制文​​件。

要读取以 16 位编码的类似文件,以下方法非常有效:

import numpy as np
images = np.memmap(filename_video, dtype=np.uint16, mode='r', shape=(nb_frames, height, width))

其中 filename_video 是可以从另一个文件读取的视频的文件和 nb_frames、高度和宽度特征。我所说的“运行良好”是指速度快:在我的计算机上读取具有 140 帧的 640x256 视频大约需要 1 毫秒。

据我所知,当文件以 12 位编码时我无法使用它,因为没有 uint12 类型。所以我想做的是读取一个 12 位文件并将其存储在一个 16 位 uint 数组中。以下内容取自 ( Python: reading 12 bit packed binary image),有效:

with open(filename_video, 'rb') as f:
    data=f.read()
images=np.zeros(int(2*len(data)/3),dtype=np.uint16)
ii=0
for jj in range(0,int(len(data))-2,3):
    a=bitstring.Bits(bytes=data[jj:jj+3],length=24)
    images[ii],images[ii+1] = a.unpack('uint:12,uint:12')
    ii=ii+2
images = np.reshape(images,(nb_frames,height,width))

但是,这非常慢:使用我的机器读取只有 5 帧的 640x256 视频大约需要 11.5 秒。理想情况下,我希望能够像使用 memmap 读取 8 位或 16 位文件一样高效地读取 12 位文件。或者至少不会慢 10^5 倍。我怎样才能加快速度?

这是一个文件示例: http://s000.tinyupload.com/index.php?file_id=26973488795334213426 (nb_frames=5,高度=256,宽度=640)。

最佳答案

我的实现与@max9111 提出的实现略有不同,它不需要调用 unpackbits

它通过将中间字节切成两半并使用 numpy 的二进制运算,直接从三个连续的 uint8 中创建两个 uint12 值。在下文中,data_chunks 被假定为包含任意数量的 12 位整数信息的二进制字符串(因此其长度必须是 3 的倍数)。

def read_uint12(data_chunk):
    data = np.frombuffer(data_chunk, dtype=np.uint8)
    fst_uint8, mid_uint8, lst_uint8 = np.reshape(data, (data.shape[0] // 3, 3)).astype(np.uint16).T
    fst_uint12 = (fst_uint8 << 4) + (mid_uint8 >> 4)
    snd_uint12 = ((mid_uint8 % 16) << 8) + lst_uint8
    return np.reshape(np.concatenate((fst_uint12[:, None], snd_uint12[:, None]), axis=1), 2 * fst_uint12.shape[0])

我对其他实现进行了基准测试,结果证明这种方法在 ~5 Mb 输入上快 ~4 倍:
read_uint12_unpackbits 每个循环 65.5 ms ± 1.11 ms(7 次运行的平均值 ± std.dev,每次 10 次循环) read_uint12 每个循环 14 ms ± 513 µs(7 次运行的平均值 ± 标准偏差,每次 100 次循环)

关于Python:读取 12 位二进制文​​件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44735756/

相关文章:

python - 如何使用 Python(最好是 PyPDF2)选中/取消选中 PDF 中的复选框?

linux - 如何使用python脚本在linux中获取和打开接口(interface)

python-3.x - Matplotlib 使用文本而不是标记,但这不是最好的方法吗?

python - 读取日志数据的二进制文件并使用 int 输出到新文件(python)

sql - 使用 python pymssql 将二进制文件插入 MSSQL db (varbinary)

python - SQLAlchemy - 如何从 ResultProxy 访问列名并写入 CSV header

Python Matplotlib : plot text will not align left

python - Django 发布时间到数据库

django - Django 中 REST API 的目录结构应该是什么?

c++ - 你如何输出 float 的二进制表示?