Clear Filters
Clear Filters

Convert RGB image to YUV (MATLAB)

79 views (last 30 days)
Dear,
I'm trying to convert an image from standard RGB to YUV and vice-versa And I need to plot each parameter Y, U, V in subplot. I tried with this program
im1=imread('peppers.png');
plot_flag=1;
Im_YUV = rgb2yuv(im1,plot_flag);
[Y,U,V] = rgb2yuv(im1);
figure
imshow(Im_YUV)
figure
subplot(221), imshow(im1); title('RGB');
subplot(222), imshow(Y); title('Y'); colormap('YUV');
subplot(223), imshow(U); title('U'); colormap('YUV');
subplot(224), imshow(V); title('V'); colormap('YUV');
function YUV=rgb2yuv(RGB,plot_flag)
R = double(RGB(:,:,1));
G = double(RGB(:,:,2));
B = double(RGB(:,:,3));
%Conversion Formula
Y = 0.299 * R + 0.587 * G + 0.114 * B;
U = - 0.168736 * R - 0.331264 * G + 0.5 * B;
V = 0.5 * R - 0.418688 * G - 0.081312 * B;
if (plot_flag==1)
figure();
subplot(1,3,1);imshow(Y);title('Y');
subplot(1,3,2);imshow(U);title('U');
subplot(1,3,3);imshow(V);title('V');
end
YUV=cat(3,uint8(Y),uint8(U),uint8(V));
YUV=rgb2ycbcr(RGB);
end
but I got an error of too many output arguments in line of : [Y,U,V]=rgb2yuv(im1)
How can I fixe this error please !

Accepted Answer

Image Analyst
Image Analyst on 9 Nov 2022
I made some changes:
rgbImage = imread('peppers.png');
plot_flag=0;
yuvImage = rgb2yuv(rgbImage,plot_flag);
[Y,U,V] = imsplit(yuvImage);
subplot(4, 2, 1:4);
imshow(yuvImage)
axis('on', 'image');
subplot(425), imshow(rgbImage); title('RGB');
cmap = gray(256);
subplot(426), imshow(Y, 'Colormap', cmap); title('Y');
subplot(427), imshow(U, 'Colormap', cmap); title('U');
subplot(428), imshow(V, 'Colormap', cmap); title('V');
function YUV=rgb2yuv(RGB,plot_flag)
R = double(RGB(:,:,1));
G = double(RGB(:,:,2));
B = double(RGB(:,:,3));
%Conversion Formula
Y = 0.299 * R + 0.587 * G + 0.114 * B;
U = - 0.168736 * R - 0.331264 * G + 0.5 * B;
V = 0.5 * R - 0.418688 * G - 0.081312 * B;
if (plot_flag==1)
figure();
subplot(1,3,1);imshow(Y, []);title('Y');
subplot(1,3,2);imshow(U, []);title('U');
subplot(1,3,3);imshow(V, []);title('V');
end
YUV=cat(3,uint8(Y),uint8(U),uint8(V));
YUV=rgb2ycbcr(RGB);
end

More Answers (1)

DGM
DGM on 9 Nov 2022
Edited: DGM on 9 Nov 2022
First, that's not YUV. I know everyone calls it YUV. If it's not analog PAL video, it's probably not YUV. That's the forward transform for YPbPr/YCbCr. If you think you still want YUV, there are conversion examples here.
Your outputs are obviously being replaced by the valid results from rgb2ycbcr(), so I don't know what you're trying to do or why. Maybe you were just testing things?
YUV=cat(3,uint8(Y),uint8(U),uint8(V)); % you assemble the output
YUV=rgb2ycbcr(RGB); % and then discard it
Either way, it appears you're trying to convert RGB to 8-bit integer YCbCr. You can't just multiply and be done. If you do that, you'll truncate half your chroma data and you won't have the expected margins.
After multiplication by the forward transform, Cb and Cr will (depending on the color content) span [-128 128] (note A(2,3) and A(3,1)). Converting that to uint8 will truncate all your color information. It needs to be offset.
Margins might be a variable thing, but I'm going to assume that they're expected by whatever will read the data. Certainly, rgb2ycbcr() and ycbcr2rgb() expect standard margins. The synopsis mentions this:
YCBCR is uint8 where Y is in the range [16 235], and Cb and Cr are in the range [16 240].
Here's an example of manual conversion. You're free to adapt it to your needs.
inpict = imread('peppers.png');
% transformation matrix
A = [0.299 0.587 0.114;-0.1687 -0.3313 0.5;0.5 -0.4187 -0.08131];
Asc = [219; 224; 224]; % channel scaling for uint8
os = [16; 128; 128]; % offset
% convert to 8-bit YCbCr, compare to built-in tools
s = size(inpict);
yccpict = uint8(reshape(reshape(im2double(inpict),[],3)*(A.*Asc).' + os.',s));
yccpict2 = rgb2ycbcr(inpict);
% compare
immse(yccpict,yccpict2)
ans = 5.5271e-04
% convert back to 8-bit RGB, compare to built-in tools
rgbpict = im2uint8(reshape((reshape(double(yccpict),[],3) - os.')/(A.*Asc).',s));
rgbpict2 = ycbcr2rgb(yccpict2);
% compare manual conversion
immse(rgbpict,inpict)
ans = 0.3881
% compare built-in conversion
immse(rgbpict2,inpict)
ans = 0.3884
The small difference is merely a matter of order of operations.
As a sidenote. I mentioned A(2,3) and A(3,1). Those two terms determine the half-width of the chroma plane in each direction. Since they're neatly half, the chroma data is a nice intmax-width and can be offset by 128 to fit back into [0 255]. Look at those terms in the YUV forward transformation matrix. If you tried to do the same with YUV, V would be [-157 157]. Offsetting won't fit that back into [0 255].

Categories

Find more on Convert Image Type in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!