rgb to yuv conversion and accessing Y, U and V channels

Viewed 27300

I have been looking this conversion for a while. What are the ways of converting RGB image to YUV image and accessing Y, U and V channels using Python on Linux? (using opencv, skimage, or etc...)

Update: I used opencv

img_yuv = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)
y, u, v = cv2.split(img_yuv)

cv2.imshow('y', y)
cv2.imshow('u', u)
cv2.imshow('v', v)
cv2.waitKey(0)

and got this result but they are all seems gray. Couldn't get an result represented like on the wikipedia page

Am I doing something wrong?

enter image description here

2 Answers

Using the LUT values as described might be exactly how the Wikipedia article image was made but the description implies it's arbitrary and used maybe because it's simple. It isn't arbitrary; the results essentially match how RGB <-> YUV conversions work. If you are using OpenCV then the methods BGR2YUV and YUV2BGR give the result using the conversion formula found in the same Wikipedia YUV article. (My images generated using Java were slightly darker otherwise the same.)

Addendum: I feel bad that I picked on Dan Mašek after he answered the question perfectly and astutely by showing us the lookup table trick. The author of the Wikipedia YUV article didn't do a bad job depicting the green-blue and green-red gradient shown in the article but as Dan Mašek pointed out it wasn't perfect. The images of color for U and V do somewhat resemble what really happens so I'd call them exaggerated-color and not false-color. The Wikipedia article on YCrCb is similar but different somehow.

// most of the Java program which should work in other languages with OpenCV:
// everything duplicated to do both the U and V at the same time
Mat src = new Mat();
Mat dstA = new Mat();
Mat dstB = new Mat();
src = Imgcodecs.imread("shed.jpg", Imgcodecs.IMREAD_COLOR);

List<Mat> channelsYUVa = new ArrayList<Mat>();
List<Mat> channelsYUVb = new ArrayList<Mat>();

Imgproc.cvtColor(src, dstA, Imgproc.COLOR_BGR2YUV); // convert bgr image to yuv
Imgproc.cvtColor(src, dstB, Imgproc.COLOR_BGR2YUV);

Core.split(dstA, channelsYUVa); // isolate the channels y u v
Core.split(dstB, channelsYUVb);

// zero the 2 channels we do not want to see isolating the 1 channel we want to see
channelsYUVa.set(0, Mat.zeros(channelsYUVa.get(0).rows(),channelsYUVa.get(0).cols(),channelsYUVa.get(0).type()));
channelsYUVa.set(1, Mat.zeros(channelsYUVa.get(0).rows(),channelsYUVa.get(0).cols(),channelsYUVa.get(0).type()));

channelsYUVb.set(0, Mat.zeros(channelsYUVb.get(0).rows(),channelsYUVb.get(0).cols(),channelsYUVb.get(0).type()));
channelsYUVb.set(2, Mat.zeros(channelsYUVb.get(0).rows(),channelsYUVb.get(0).cols(),channelsYUVb.get(0).type()));

Core.merge(channelsYUVa, dstA); // combine channels (two of which are zero)
Core.merge(channelsYUVb, dstB);

Imgproc.cvtColor(dstA, dstA, Imgproc.COLOR_YUV2BGR); // convert to bgr so it can be displayed
Imgproc.cvtColor(dstB, dstB, Imgproc.COLOR_YUV2BGR);

HighGui.imshow("V channel", dstA); // display the image
HighGui.imshow("U channel", dstB);

HighGui.waitKey(0);
Related