4

我正在使用 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 字符串的过程需要 2 毫秒,这听起来像是一个零拷贝事件。是否可以让 PIL 仅从相机 API 提供的 char * 图像数据指针创建我的图像?

4

2 回答 2

3

从 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,但这里有一些有趣的参考资料:

于 2012-06-26T14:26:39.993 回答
0

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

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

于 2013-01-22T14:00:37.540 回答