你可以使用Cython创建PIL图像而无需冗余复制内存吗?

时间:2012-06-23 20:57:42

标签: python camera usb python-imaging-library cython

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

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

struct FlyCaptureImage:
   /// stuff
  char * convert_buffer
   /// more stuff

现在,我这样做是为了把它变成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)

将数据转换为python字符串的过程需要2ms才能听起来像是零复制事件。是否可以通过相机API提供的char *图像数据指针来获取PIL来创建我的图像?

2 个答案:

答案 0 :(得分:2)

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

  

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

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

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

编辑:查看frombuffer的来源,它是fromstring上的光包装,零拷贝需要Image._MAPMODES列表中的像素格式(即RGBX)。至少,您必须将RGB数据复制/转换为RGBX缓冲区,以获得零拷贝兼容的像素格式。

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

答案 1 :(得分:0)

也许,要做的就是手动组装Python String或array.array对象 - 使用C结构,并将缓冲区指向您的数据。因为我根本不需要它,所以我没有为它编写代码。

刚检查过它 - 字符串是不可能的 - strign体必须与字符串 - 对象标题一起分配(没有指向另一块内存的指针)。