I want to do some image processing with OpenCV (in Python), but I have to start with a PIL
Image object, so I can't use the
cvLoadImage() call, since that takes a filename.
This recipe (adapted from http://opencv.willowgarage.com/wiki/PythonInterface) does not work because
argument 2 of type 'void *' . Any ideas?
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))
I think the last argument to the
cvSetData is wrong too, but I am not sure what it should be.
The example you tried to adapt is for the new python interface for OpenCV 2.0. This is probably the source of the confusion between the prefixed and non-prefixed function names (
OpenCV 2.0 now ships with two sets of python bindings:
cv.pyd), which wraps all the OpenCV functionalities (including the
The reason behind the error message is that the SWIG wrapper does not handle conversion from a python string to a plain-old C buffer. However, the SWIG wrapper comes with the
opencv.adaptors module, which is designed to support conversions from
PIL images to OpenCV.
The following (tested) code should solve your original problem (conversion from PIL to OpenCV), using the SWIG interface :
# 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)
However, this does not solve the fact that the
cv.cvSetData() function will always fail (with the current SWIG wrapper implementation).
You could then use the new-style wrapper, which allows you to use the
cv.SetData() function as you would expect :
# 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*3) cv.NamedWindow("pil2ipl") cv.ShowImage("pil2ipl", cv_img)
A third approach would be to switch your OpenCV python interface to the ctypes-based wrapper. It comes with utility functions for explicit data conversion between e.g. python strings and C buffers. A quick look on google code search seems to indicate that this is a working method.
Concerning the third parameter of the
cvSetData() function, size of the image buffer, but the image step. The step is the number of bytes in one row of your image, which is
pixel_depth * number_of_channels * image_width. The
pixel_depth parameter is the size in bytes of the data associated to one channel. In your example, it would be simply the image width (only one channel, one byte per pixel).