convert openCV image into PIL Image in Python (for use with Zbar library)

Each Answer to this Q is separated by one/two green lines.

I’m trying to use the Zbar library’s QR code detection methods on images I extract with OpenCV’s camera methods. Normally the QR code detection methods work with images (jpg, png, etc.) on my computer, but I guess the captured frames of OpenCV are different.
Is there a way of making the captured frame into a PIL Image?

Thank you.

from PIL import Image
import zbar
import as cv

capture = cv.CaptureFromCAM(1)
imgSize = cv.GetSize(cv.QueryFrame(capture))
img = cv.QueryFrame(capture)

img = img.convert('L')
width, height = img.size

scanner = zbar.ImageScanner()
zbar_img = zbar.Image(width, height, 'Y800', img.tostring())

# scan the image for barcodes

for symbol in zbar_img:

With the python CV2, you can also do this:

import Image, cv2

cap = cv2.VideoCapture(0) # says we capture an image from a webcam
_,cv2_im =
cv2_im = cv2.cvtColor(cv2_im,cv2.COLOR_BGR2RGB)
pil_im = Image.fromarray(cv2_im)

I think I may have found the answer. I’ll edit later with results.

OpenCV to PIL Image

import Image, cv
cv_im = cv.CreateImage((320,200), cv.IPL_DEPTH_8U, 1)
pi = Image.fromstring("L", cv.GetSize(cv_im), cv_im.tostring())


Are you trying to obtain a RGB image? If that is the case, you need to change your parameters from this:

cv_im = cv.CreateImage((320,200), cv.IPL_DEPTH_8U, 1)
pi = Image.fromstring("L", cv.GetSize(cv_im), cv_im.tostring())

to that:

cv_im = cv.CreateImage((320,200), cv.IPL_DEPTH_8U, 3)
pi = Image.fromstring("RGB", cv.GetSize(cv_im), cv_im.tostring())

since it is documented almost nowhere, but the ‘L’ parameter of Image.fromstring is for 8-bit B&W images. Besides, you need to change the argument of your cv.CreateImage function from 1 (single channel image) to 3 (3 channels=RGB).

Hope it works for you.

A simple way is to directly swap the channels. Suppose you are trying to convert a 3-channel image file between OpenCV format and PIL format. You can just use:


In this way, you won’t be bothered with cv2.cvtColor as this function only works on images with certain depth.

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .