你尝试适应的示例是针对OpenCV 2.0的新Python接口的。这可能是前缀和非前缀函数名称(`cv.cvSetData()`与`cv.SetData()`)之间混淆的源头。
现在,OpenCV 2.0附带了两个Python绑定:
- 旧样式Python包装器,一个带有`opencv.{cv、highgui、ml}`模块的Python包。
- 新的接口,一个Python C扩展(`cv.pyd`),它包装了所有OpenCV功能(包括`highgui`和`ml`模块)。
错误消息背后的原因是SWIG包装器不处理将Python字符串转换为普通C缓冲区。然而,SWIG包装器附带了`opencv.adaptors`模块,旨在支持将`numpy`和`PIL`图像转换为OpenCV。
下面这段代码(已测试)应该可以解决您最初的问题(从 PIL 到 OpenCV 的转换),使用 SWIG 接口:
from opencv import cv, adaptors, highgui
import PIL
pil_img = PIL.Image.open(filename)
cv_img = adaptors.PIL2Ipl(pil_img)
highgui.cvNamedWindow("pil2ipl")
highgui.cvShowImage("pil2ipl", cv_img)
然而,这并不能解决
cv.cvSetData()
函数始终会失败的问题(在当前的 SWIG 封装实现中)。
您可以使用新式封装器,它允许您像预期的那样使用
cv.SetData()
函数:
import cv
import PIL
pil_img = PIL.Image.open(filename)
cv_img = cv.CreateImageHeader(pil_img.size, cv.IPL_DEPTH_8U, 3)
cv.SetData(cv_img, pil_img.tostring(), pil_img.size[0]*3)
cv.NamedWindow("pil2ipl")
cv.ShowImage("pil2ipl", cv_img)
一种方法是将OpenCV的Python接口切换到
基于ctypes的包装器。它带有实用函数,用于显式数据转换,例如Python字符串和C缓冲区之间的转换。在
Google代码搜索上快速查看似乎表明这是一种可行的方法。
关于
cvSetData()
函数的第三个参数,它表示图像缓冲区的大小,而不是图像步长。步长是图像一行中的字节数,即
pixel_depth * number_of_channels * image_width
。
pixel_depth
参数是与一个通道相关联的数据的字节数。在您的示例中,它只是图像宽度(仅一个通道,每个像素一个字节)。