首页 > 解决方案 > 优化 CBOR 读取函数以将数据传递到 numpy

问题描述

我正在尝试将 CBOR 文件中的图像数据读入 Numpy 数组。

理想情况下,我正在寻找一种更有效的读取方式,将字节从二进制补码转换为无符号,然后将图像数据读入 numpy 数组。

我尝试了几种不同的方法来转换和读取字节,但无法显着提高速度。

最初我使用 for 循环来转换字节(下面的 1.),然后我使用带模数的 numpy(下面的 2.),然后转到选择性加法(下面的 3.)。

我的全部功能也在下面。

1) for x in data:
    new_byte = x%256
2) ndarray%256
3) image[image<0] += 256
import os
from cbor2 import dumps, loads, decoder
import numpy as np
import itertools

def decode_image_bytes(image_byte_array):
    """Input: 1-D list of 16 bit two's compliment bytes 
        Operations: Converts the bytes to unsigned and decodes them
        Output: a 1-D array of 16-bit image data"""
    # Convert input to numpy array
    image = np.array(image_byte_array)
    # Convert two's complement bytes to unsigned
    image[image<0] += 256
    # Split the unsigned bytes into segments
    bytes_array=np.array_split(image,(len(image)/2))
    holder = list()
    # Convert segements into integer values
    for x in bytes_array:
        holder.append(int.from_bytes(list(x), byteorder='big', signed=False))
    return holder

def decode_image_metadata(image_dimensions_bytes_array):
    """Input: 1-D list of sint64 two's complement bytes
        Operations: Converts bytes to unsigned and decodes them
        Output: Dictionary with possible values: 'width, height, channels, Z, time'"""
    # Convert input to numpy array
    dimensions = np.array(image_dimensions_bytes_array)
    # Covert two's complement bytes to unsigned
    dimensions[dimensions<0] += 256
    # Split the unsigned bytes into segements
    bytes_array=np.array_split(dimensions,(len(dimensions)/8))
    # Convert the segments into integer values
    for x in range(0, len(bytes_array)):
        bytes_array[x]=int.from_bytes(list(bytes_array[x]), byteorder='big', signed=True)
    # Put the converted integer values into a dictionary
    end = dict(itertools.zip_longest(['width', 'height', 'channels', 'Z', 'time'], bytes_array, fillvalue=None))
    return end

现在需要 20-30 秒来转换字节并返回 Numpy 数组。如果可能的话,我想把它减半。

现在我想出了使用来消除 for 循环。有没有更好的方法?

bytes_array = np.apply_along_axis(metadata_values, 1, bytes_array)

def metadata_values(element):
    return int.from_bytes(element, byteorder='big', signed=True)

标签: pythonpython-3.xnumpyoptimizationcbor

解决方案


除非您是为自己的教育而这样做,否则您不应该在二进制数表示之间编写自己的转换,因为它会慢几个数量级。

这是一个将字节读入各种格式的 numpy 数组的示例:

>>> b = bytes([0,1,127,128,255,254]) #equivelant to reading bytes from a file in binary mode
>>> np.frombuffer(b, dtype=np.uint8)
array([  0,   1, 127, 128, 255, 254], dtype=uint8) #notice the *U*int vs int
>>> np.frombuffer(b, dtype=np.int8)
array([   0,    1,  127, -128,   -1,   -2], dtype=int8)
>>> #you can also specify other than 1 byte data formats as long as you have the right amount of bytes
>>> np.frombuffer(b, dtype=np.int16)
array([   256, -32641,   -257], dtype=int16)
>>> np.frombuffer(b, dtype=np.uint16)
array([  256, 32895, 65279], dtype=uint16)

推荐阅读