python – 如何从PIL图像创建OpenCV图像?

我想用OpenCV(在Python中)进行一些图像处理,但是我必须从PIL Image对象开始,所以我不能使用cvLoadImage()调用,因为它需要一个文件名.

这个配方(从http://opencv.willowgarage.com/wiki/PythonInterface改编)不起作用,因为cvSetData抱怨类型为’void *’的参数2.有任何想法吗?

from opencv.cv import *
from PIL import Image

pi = Image.open('foo.png')                       # PIL image
ci = cvCreateImage(pi.size, IPL_DEPTH_8U, 1)     # OpenCV image
data = pi.tostring()
cvSetData(ci, data, len(data)) 

我认为cvSetData的最后一个参数是错误的,但我不知道应该是什么.

最佳答案
您尝试适应的示例是OpenCV 2.0的新的python接口.这可能是前缀和非前缀函数名(cv.cvSetData()与cv.SetData())之间混淆的根源.

OpenCV 2.0现在附带两套python绑定:

> “old-style” python wrapper,一个带opencv.{cv,highgui,ml}模块的python包
> new interface,一个python C扩展(cv.pyd),它包装了所有的OpenCV功能(包括highgui和ml模块).

错误消息背后的原因是SWIG包装器不处理从python字符串到普通C缓冲区的转换.然而,SWIG包装器附带opencv.adaptors模块,该模块旨在支持从numpy和PIL图像到OpenCV的转换.

以下(测试)代码应该使用SWIG界面解决您的原始问题(从PIL转换为OpenCV):

# PIL to OpenCV using the SWIG wrapper
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()函数:

# PIL to OpenCV using the new wrapper
import cv
import PIL

pil_img = PIL.Image.open(filename)       

cv_img = cv.CreateImageHeader(pil_img.size, cv.IPL_DEPTH_8U, 3)  # RGB image
cv.SetData(cv_img, pil_img.tostring(), pil_img.size[0]*3)

cv.NamedWindow("pil2ipl")
cv.ShowImage("pil2ipl", cv_img)

第三种方法是将OpenCV python接口切换到ctypes-based wrapper.它具有用于例如显示数据转换的实用功能. python字符串和C缓冲区. google code search快速浏览似乎表明这是一种工作方法.

关于cvSetData()函数的第三个参数,图像缓冲区的大小,但是图像的步长.该步骤是您图像的一行中的字节数,即pixel_depth * number_of_channels * image_width. pixel_depth参数是与一个通道相关联的数据的大小(以字节为单位).在你的例子中,它只是图像宽度(只有一个通道,每像素一个字节).

转载注明原文:python – 如何从PIL图像创建OpenCV图像? - 代码日志