Issue with Y, Cb and Cr image. Only Y (luma) image looks red, Cb looks green and Cr looks red. But converting the YCbCr image using ycbcr2rgb, give original image

9 views (last 30 days)
Have an image and converted RGB to YCbCr color space, using rgb2ycbcr code. And when i try to seperate the Luma (Y) and color components (Cb and Cr), the generated images, doesnt look satisfying.
As per my understanding, if we take an image and convert it to RGB or YCbCr, the image should be similar in both RGB or YCbCr color space right ?
Issue image : "Original" is the image taken for the experiment. "New RGB" is obtained by converting "YCbCr Image" using ycbcr2rgb.
The Only Luma Y, Only Cb Blue difference and Only Cr Red difference doesnt make sense to me as per what i saw in internet, only luma should be a gray scale image, only Cb should be blue and only Cr should be red. But here i get strange image.
Code:
%load image
RGB = imread('example.jpg');
%get resolution of image
pic = size(RGB);
%create a zero matrix corresponding to the image
zero_matrix = zeros(pic(1:2), 'uint8');
%convert image to YCbCr color space
YCBCR = rgb2ycbcr(RGB);
%convert YCBCR to RGB again
new_rgb = ycbcr2rgb(YCBCR);
%Extract Red, Green and Blue components from the image
R=RGB(:,:,1);
G=RGB(:,:,2);
B=RGB(:,:,3);
%Generate image with only Read, Green and Blue components
only_r = cat(3, R, zero_matrix, zero_matrix);
only_g = cat(3, zero_matrix, G, zero_matrix);
only_b = cat(3, zero_matrix, zero_matrix, B);
%Extract Y and Cb, Cr components from the converted image
Y=YCBCR(:,:,1);
Cb=YCBCR(:,:,2);
Cr=YCBCR(:,:,3);
%Generate image with only Y, Cb and Cr components
only_y = cat(3, Y, zero_matrix, zero_matrix);
only_Cb = cat(3, zero_matrix, Cb, zero_matrix);
only_Cr = cat(3, zero_matrix, zero_matrix, Cr);
%Display RGB image
figure();
imshow(RGB);
impixelinfo;
title('original');
%Display Only Red image
figure();
imshow(only_r);
title('Only Red');
impixelinfo;
%Display Only Green image
figure();
imshow(only_g);
title('Only Green');
impixelinfo;
%Display Only Blue image
figure();
imshow(only_b);
title('Only Blue');
impixelinfo();
%Display YCbCr image
figure();
imshow(YCBCR);
title('YCbCr Image');
impixelinfo();
%Display Only Luma Y image
figure();
imshow(only_y);
title('Only Luma Y');
impixelinfo;
%Display Only Blue difference image
figure();
imshow(only_Cb);
title('Only Cb Blue difference');
impixelinfo;
%Display Only Red difference image
figure();
imshow(only_Cr);
title('Only Cr Red difference');
impixelinfo();
%Display new RGB
figure();
imshow(new_rgb);
title('New RGB');
impixelinfo();
Help is appreciated!

Accepted Answer

Daniel
Daniel on 6 May 2023
It looks to me like the only issue is in the "Display YCbCr image" region of your script. imshow expects an RGB input matrix. It's rendering your Y component as if it were red because it expects input(:,:,1) to be the red value, and so on for the other components. And
If you want to render the Y, Cr, and Cb elements as if they were RGB, you'll need to start by converting them back into RGB image space, so imshow renders them properly. So you could render, for instance, ycrcb2rgb(only_y).
However, when you do this, you'll still run into saturation issues. Since Cr and Cb represent differences, they can represent either positive or negative values. Cr and Cb values of 0 actually denote a negative amount of red and blue, so when you want to create an image with only y, only Cr, or only Cb, the other elements have to be set to 128 rather than 0.
So when you're rendering your YCrCb components, you need to make two changes:
  1. The "uninteresting" values in only_y, only_Cr, and only_Cb need to be set to 128, not 0.
  2. You need to run ycrcb2rgb before passing only_whatever into imshow.
  6 Comments
Daniel
Daniel on 8 May 2023
Honestly, how to convert from RGB to YCrCb is about the limit of my knowledge in the area. 4:2:0 is beyond my experience. You might want to post this as a new question to get a fresh set of eyes on it, or try asking one of the other people who answered.

Sign in to comment.

More Answers (2)

Image Analyst
Image Analyst on 6 May 2023
I think you don't understand what the color spaces actually mean. imshow() treats a 3-D image as if it were a true color RGB image, which a YCbCr image is NOT. If you do display the ycbcr image as rgb, or course it will look very strange. And if you extract any of the color planes, for example, Y, then it's a gray scale image. You could display it as some color - whatever you want - but it could be misleading. And the Cb image, which is the ycbcrImage(:, :, 2) is not a green image, though you could display it as green or any other color or even apply a pseudocolor colormap. Though that would be deceptive. And like @Daniel said, Cb and Cr could have positive and negative values, so the least deceptive way to display them would be with [] in imshow, like (untested):
ycbcrImage = rgb2ycbcr(rgbImage);
[y, cb, cr] = imsplit(ycbcrImage);
subplot(2, 2, 2);
imshow(y, []);
title('Y Color Channel');
subplot(2, 2, 3);
imshow(cb, []);
title('Cb Color Channel');
subplot(2, 2, 4);
imshow(cr, []);
title('Cr Color Channel');

DGM
DGM on 6 May 2023
This answer shows one way to represent the YCbCr channels in pseudocolor,
Included in this thread are other examples representing the YCbCr channels in grayscale, commentary on the merits of either, and links to other threads with examples doing similar in other color spaces.

Products


Release

R2017a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!