How do I create an OpenCV image from a PIL image?
我想用 OpenCV(在 Python 中)做一些图像处理,但我必须从 PIL
这个配方(改编自 http://opencv.willowgarage.com/wiki/PythonInterface)不起作用,因为
1 2 3 4 5 6 7 | 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)) |
我认为
您尝试调整的示例是针对 OpenCV 2.0 的新 python 接口。这可能是前缀和非前缀函数名称(
OpenCV 2.0 现在附带两组 python 绑定:
-
"老式"python package器,一个带有
opencv.{cv,highgui,ml} 模块的 python 包 -
新接口,python C 扩展 (
cv.pyd ),它package了所有 OpenCV 功能(包括highgui 和ml 模块。)
错误消息背后的原因是 SWIG package器不处理从 python 字符串到普通 C 缓冲区的转换。但是,SWIG package器附带
使用 SWIG 接口,以下(经过测试的)代码应该可以解决您的原始问题(从 PIL 转换为 OpenCV):
1 2 3 4 5 6 7 8 9 10 | # 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) |
但是,这并不能解决
然后,您可以使用新样式的package器,它允许您按预期使用
1 2 3 4 5 6 7 8 9 10 11 | # 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 的package器。它带有实用功能,用于在例如之间进行显式数据转换。 python 字符串和 C 缓冲区。快速浏览一下谷歌代码搜索似乎表明这是一种可行的方法。
关于
同时拥有 swig 和新的 python 绑定真的很令人困惑。例如,在 OpenCV 2.0 中,cmake 可以同时接受 BUILD_SWIG_PYTHON_SUPPORT 和 BUILD_NEW_PYTHON_SUPPORT。但无论如何,我有点想通了大多数陷阱。
在使用"import cv"(新的python绑定)的情况下,需要多一步。
1 2 | cv.SetData(cv_img, pil_img.tostring(), pil_img.size[0]*3) cv.CvtColor(cv_img, cv_img, cv.CV_RGB2BGR) |
对于 RGB 图像,转换是必要的,因为 PIL 和 IplImage 中的顺序不同。这同样适用于 Ipl 到 PIL。
但如果你使用 opencv.adaptors,它已经被处理好了。如果有兴趣,您可以查看 adapters.py 中的详细信息。
我使用 OpenCV2.1 的 python2.6 绑定做到了这一点:
1 2 3 4 | ... cv_img = cv.CreateImageHeader(img.size, cv.IPL_DEPTH_8U, 3) cv.SetData(cv_img, img.rotate(180).tostring()[::-1]) ... |
字符串的图像旋转和反转是将RGB转换为BGR,用于OpenCV视频编码。我认为这对于从 PIL 转换为 OpenCV 的图像的任何其他用途也是必要的。
我不是专家,但我设法使用以下代码从 PIL 图像中获取了 opencv 图像:
1 2 3 | import opencv img = opencv.adaptors.PIL2Ipl(pilimg) |