提高 10 到 8 位转换性能



我有10位数据的灰度图像文件。 10 位保存在 2 个字节上,低位对齐(10 位值0b10 0000 1111保存为0x020F

我想将其转换为 8 位,保留最高有效字节。

def convert_10bitTo8Bit(tenBitData):
output_size = int(len(tenBitData) / 2)
eightBitData = bytearray(output_size)
for i in range(output_size):
lowbyte, highbyte = tenBitData[i * 2 + 1], tenBitData[i * 2]
value = (highbyte << 8) + lowbyte
value = (value >> 2) & 0xff
eightBitData[i] = value
return eightBitData

这有效,但非常慢:对于 3MB 的映像,在我的开发计算机上大约需要 0.5 秒,在打算运行它的设备上需要>8 秒(ARM 系统,与 PI 类似的性能(。

我试图分析它以找到瓶颈,但cProfile只是将builtins.exec报告为最耗时的功能。

$ python3 ImageTools.py
5 function calls in 8.560 seconds
Ordered by: standard name
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
1    0.000    0.000    8.560    8.560 <string>:1(<module>)
1    8.559    8.559    8.559    8.559 ImageTools.py:11(convert_10bitTo8Bit)
1    0.000    0.000    8.560    8.560 {built-in method builtins.exec}
1    0.000    0.000    0.000    0.000 {built-in method builtins.len}
1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

如何提高性能?

您可以通过使用以下numpy对操作进行矢量化来提高性能:

# Store byte pairs as columns.
# If `tenBitData` is a `bytes` object, then use `np.fromiter` instead.
>>> data = np.asarray(tenBitData, dtype=np.uint8).reshape(-1, 2)
# Now we apply vectorized conversion.
>>> (data[:, 0] << 6) + (data[:, 1] >> 2)

在我的计算机上进行测试(4MB数据(时,我得到以下时间:

Conversion: 3.044390e-01s
Function: 1.002173e+00s
Numpy: 7.728000e-03s

因此,尽管numpy很快,但转换仍然是一个瓶颈(至少给出 3 倍(。根据数据的最初存储方式,这种转换甚至可能不是必需的。

您的函数名称与函数的实际操作略有冲突,但是是的,可以改进, 这假设您不再关心原始的 10 位数据。 假设您始终有字节对,它将适用于任何大小,奇数将引发错误

def convert_8bitTo10Bit(tenBitData):
eightBitData = bytearray()
while tenBitData:
eightBitData.insert(0,((tenBitData.pop() | (tenBitData.pop() << 8)) >> 2 & 0xFF))
return eightBitData

最新更新