How to display Y, Cb and Cr components of an image?

128 views (last 30 days)
Swapnil Srivastava on 16 Aug 2020
Edited: DGM on 2 May 2022
Hi everyone, I've got an image which im trying to seperate out its Y, Cb and Cr components and display them. I seperated them out using the equation that relates YCbCr to RGB.
%% Reading the image as a tiff format
im1=double(im1)/256;
im1(:,:,4)=[];
xsize=size(im1,1);
ysize=size(im1,2);
%% Transforming the image from RGB to YCbCr
R=im1(:,:,1);
G=im1(:,:,2);
B=im1(:,:,3);
Y=0.288*R+0.587*G+0.114*B;
Cb=-0.1687*R-0.3313*G+0.5*B;
Cr=0.5*R-0.4187*G-0.0813*B;
%% Display the various different Y, Cb and Cr
figure;
subplot(1,3,1)
image(im1);
I'm now trying to find out how do I display them seperately. Does anyone know how to do it?
Thank you

Stephan on 16 Aug 2020
Edited: Stephan on 16 Aug 2020
I used the inbuild example file peppers_RGB_tiled.tif, which has no 4rd dimension that could be cleared, so i used a try catch block to avoid errors:
%% Reading the image as a tiff format
im1=double(im)/256;
try
im1(:,:,4)=[];
catch
end
xsize=size(im1,1);
ysize=size(im1,2);
%% Transforming the image from RGB to YCbCr
R=im1(:,:,1);
G=im1(:,:,2);
B=im1(:,:,3);
Y=0.288*R+0.587*G+0.114*B;
Cb=-0.1687*R-0.3313*G+0.5*B;
Cr=0.5*R-0.4187*G-0.0813*B;
%% Display thoe original & the various different Y, Cb and Cr
figure;
hold on
subplot(1,4,1)
imshow(im);
subplot(1,4,2)
imshow(Y);
subplot(1,4,3)
imshow(Cb);
subplot(1,4,4)
imshow(Cr);
hold off
2 CommentsShowHide 1 older comment
DGM on 2 May 2022
There are a couple problems with this answer.
First of all, the luma constants in the transform look like they got typo'd The BT601 luma constants are [0.299 0.587 0.114]. It should also be noted that while YCbCr and YPbPr use the same transformation matrix, common integer YCbCr has offsets and scaling to consider. For visual purposes, it should suffice, but don't expect the values to be directly comparable to the results from something like rgb2ycbcr().
Second, since the above transformation is essentially YPbPr, the chroma channels are unit-scale and centered on zero. Because of that, imshow() will truncate them. Instead, offset them by 0.5 for viewing.
im1 = im2double(im); % needs IPT in older versions
% Transforming the image from RGB to YCbCr
[R G B] = imsplit(im1); % R2018b+
Y = 0.299*R + 0.587*G + 0.114*B; % 0.299
Cb = -0.1687*R - 0.3313*G + 0.5*B;
Cr = 0.5*R - 0.4187*G - 0.0813*B;
% Display the original & the various different Y, Cb and Cr
subplot(2,2,1) % i changed the tiling for web-view
imshow(im);
subplot(2,2,2)
imshow(Y);
subplot(2,2,3)
imshow(Cb+0.5); % offset
subplot(2,2,4)
imshow(Cr+0.5); % offset

Image Analyst on 16 Aug 2020
Try this:
% Transforming the image from RGB to YCbCr
yCbCrImage = rgb2ycbcr(rgbImage);
[yImage, crImage, cbImage] = imsplit(yCbCrImage);
% If you have r2018a or earlier, use the code below instead of imsplit().
% yImage = yCbCrImage(:, :, 1);
% crImage = yCbCrImage(:, :, 2);
% cbImage = yCbCrImage(:, :, 3);
% Display thoe original & the various different Y, Cb and Cr
figure;
subplot(2, 2, 1)
imshow(rgbImage, []);
title('RGB Image', 'FontSize', 16);
subplot(2, 2, 2)
imshow(yImage, []);
title('Y Image', 'FontSize', 16);
subplot(2, 2, 3)
imshow(cbImage, []);
title('Cb Image', 'FontSize', 16);
subplot(2, 2, 4)
imshow(crImage, []);
title('Cr Image', 'FontSize', 16);
Image Analyst on 19 Aug 2020
They applied an artificial colormap to the monochrome Y, Cb, and Cr images. Without a doubt. I guarantee it. The images don't really look like that. Neither mine nor Stephan's look like that. If you want to you can apply a colormap but don't be deceived - the underlying image is still gray scale, not color. Actually I think doing that makes the images harder to visualize.

DGM on 2 May 2022
Edited: DGM on 2 May 2022
While I agree with Image Analyst that grayscale representations of the chroma channels are accurate, easier to read, and should be more than sufficient, sometimes people want some sort of pseudocolor representations. This can either be done by colormapping or by representing the given chroma values on a locus of constant luma.
Consider the examples in the following related questions:
You should be able to take the concepts demonstrated in YIQ and LAB and apply them to YCbCr without much trouble.
YCC = rgb2ycbcr(RGB);
[Y Cb Cr] = imsplit(YCC);
z = 127*ones(size(YCC, 1), size(YCC, 2)); % chroma center is offset!
Ysub = 127*ones(size(YCC, 1), size(YCC, 2)); % assume some luma
% substitute new luma, zero opposite chroma channel
just_Cb = ycbcr2rgb(cat(3, Ysub, Cb, z));
just_Cr = ycbcr2rgb(cat(3, Ysub, z, Cr));
montage({RGB Y; just_Cb just_Cr}'); % display it
Like I said, I don't really think that's easy to intuit, and the fact that we're using a dummy luma value means it's a misrepresentation anyway. Take it as you will.
Maybe nobody will ever ask this, but I'll point it out anyway. While the grayscale representations of the luma and chroma channels can be taken and (if scaled properly) be concatenated and converted back into an RGB image, these pseudocolor representations generally cannot. Think about why that might be. Think about why it might seem like you could. After all, the pseudocolor versions of Cb and Cr just have some constant luma and are assembled using standard conversions. Why can't we just take one step backwards and get Cb and Cr and then convert back to RGB?
% try to reverse the process
YCC_Cb = rgb2ycbcr(just_Cb);
YCC_Cr = rgb2ycbcr(just_Cr);
Cbrec = YCC_Cb(:,:,2);
Crrec = YCC_Cr(:,:,3);
RGBrec = ycbcr2rgb(cat(3, Y, Cbrec, Crrec));
% show the error in the recovered image
err = im2double(imabsdiff(RGB,RGBrec));
imshow(err/range(err(:)));
Think about why it's saturated regions on the primary-secondary corners that are being distorted. What if we picked a different value for the substituted luma? Is there any luma value that would be safe?