是否可以使用 Cython 创建 PIL 映像而无需冗余复制内存?

K. *_*ord 5 python usb camera cython python-imaging-library

我正在使用 Cython 从 USB 摄像头抓取图像并将其转换为返回给调用者的 PIL 图像。

图像的数据位于图像抓取函数返回的结构体的“convert_buffer”成员所指向的字符数组中:

struct FlyCaptureImage:
   /// stuff
  char * convert_buffer
   /// more stuff
Run Code Online (Sandbox Code Playgroud)

现在,我正在这样做将其转换为 PIL 图像:

cdef unsigned char *convert_buffer
cdef Py_ssize_t byte_length
cdef bytes py_string

// get the number of bytes into a Py_ssize_t type
byte_length = count

// slice the char array so it looks like a Python str type
py_string = convert_buffer[:byte_length]

// create the PIL image from the python string
pil_image = PILImage.fromstring('RGB', (width, height), py_string)
Run Code Online (Sandbox Code Playgroud)

将数据转换为 Python 字符串的过程需要 2 毫秒,这听起来可能是一个零复制事件。是否可以让 PIL 仅从相机 API 提供的 char * 图像数据指针创建我的图像?

lnm*_*nmx 4

从 PIL 1.1.4 开始,该Image.frombuffer方法支持零拷贝:

使用标准“原始”解码器从字符串或缓冲区对象中的像素数据创建图像内存。对于某些模式,图像内存将与原始缓冲区共享内存(这意味着对原始缓冲区对象的更改会反映在图像中)。并非所有模式都可以共享内存;支持的模式包括“L”、“RGBX”、“RGBA”和“CMYK”。

问题是您的相机数据似乎是 24 位 RGB,而 PIL 需要 32 位 RGBA/RGBX。你能控制来自相机 API 的像素格式吗?

如果没有,使用 仍然可能有一个优势Image.frombuffer,因为它会接受 abuffer而不是要求您从像素数据构建 python 字符串。

编辑:查看 的源代码frombuffer,它是 的轻包装器fromstring,零复制需要列表中的像素格式Image._MAPMODES(即 RGBX)。至少,您必须将 RGB 数据复制/转换到 RGBX 缓冲区才能获得零复制兼容的像素格式。

我没有更好的方法将原始字节放入 PIL 中,但这里有一些有趣的参考: