Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Imaging: YCbCr problems

I'm doing some image processing in Python using PIL, I need to extract the luminance layer from a series of images, and do some processing on that using numpy, then put the edited luminance layer back into the image and save it. The problem is, I can't seem to get any meaningful representation of my Image in a YCbCr format, or at least I don't understand what PIL is giving me in YCbCr. PIL documentation claims YCbCr format gives three channels, but when I grab the data out of the image using np.asarray, I get 4 channels. Ok, so I figure one must be alpha.

Here is some code I'm using to test this process:

import Image as im
import numpy as np    
pengIm = im.open("Data\\Test\\Penguins.bmp")
yIm = pengIm.convert("YCbCr")
testIm = np.asarray(yIm)

grey = testIm[:,:,0]
grey = grey.astype('uint8')
greyIm = im.fromarray(grey, "L")
greyIm.save("Data\\Test\\grey.bmp")

I'm expecting a greyscale version of my image, but what I get is this jumbled up mess:

http://i.imgur.com/zlhIh.png

Can anybody explain to me where I'm going wrong? The same code in matlab works exactly as I expect.

like image 232
daver Avatar asked May 09 '10 08:05

daver


1 Answers

Since YCbCr is a simple, mathematically determinate conversion from RGB colorspace, going through the intermediate stage of YCbCr is just an indirect way of pulling a computed (not absolute) luminance value from an image. You can accomplish the same, more directly with:

yIm = pengIm.convert('L')

I suspect that there is a problem with your conversion via numpy asarray or fromarray or in your numpy code because the sequence:

>>> import Image
>>> import ImageOps
>>> import ImageChops
>>> c = Image.open('squished_levels.png')
>>> c
<PngImagePlugin.PngImageFile image mode=RGB size=320x240 at 0xB7686DAC>
>>> c.getbands()
('R', 'G', 'B')
>>> d = c.convert('L')
>>> d.getextrema()       # squished_levels.png has squished levels for testing
(77, 182)
>>> d.getbands()
('L',)
>>> e = ImageOps.equalize(d)
>>> e.getextrema()
(0, 255)
>>> f = e.convert('RGB')
>>> g = ImageChops.lighter(c, f)
>>> g.show()             # not  squished in luminance

All works as expected. Incidentally,

>>> h = c.convert('YCbCr')
>>> h
<Image.Image image mode=YCbCr size=320x240 at 0xB761378C>
>>> h.getpixel((0,0))
(119, 127, 128)
>>> h.getbands()
('Y', 'Cb', 'Cr')

Gives me three channels, not four.

like image 71
msw Avatar answered Sep 19 '22 02:09

msw