改善10到8位转换性能

时间:2018-07-03 10:34:00

标签: python python-3.x performance

我有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仅报告buildins.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}

如何提高性能?

2 个答案:

答案 0 :(得分:2)

您可以通过使用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倍)。根据最初存储数据的方式,可能甚至不需要这种转换。

答案 1 :(得分:1)

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

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