Ask an expert. Trust the answer.

Your academic and career questions answered by verified experts

10 bit YUV420 to RGB Conversion

Date: 2022-12-01 11:41:29

I am working with conversion from YUV420 to RGB but the image colours are not producing fine. Originally my own files are 10 bit. Initially, I started with 8 bit files.

I am using the code below to read YUV420 image and convert to RGB. Because I have YUV420.YUV image file but that code is for video therefore, I only read 1 frame. Then I get YUV as Y as the full size but U and V as half size as described at Wikipedia. I then resize the images to the full size of the image and apply YUV to RGB conversion. But the RGB images are not in correct colors. I have attached the files so that you can run and see what is the problem. Here is the YUV file tulips_yuv420_inter_planar_qcif.yuv.

I have two more questions;

Firstly, The size of the "stream" for one frame should be equal to 1.5*the size of the Y but it is very large whether I use uint8 or uint16 to read the file.

Secondly, If I have 10bit YUV420 file how to I to modify this code to show correct RGB. 

 

fname = 'tulips_yuv420_inter_planar_qcif.yuv'; width = 176; height = 144; nFrame=1; fid = fopen(fname,'r'); % Open the video file stream = fread(fid,'uint8'); % uint16 % stream = fread(fid); % uint8 length = 1.5 * width * height; % Length of a single frame y = double(zeros(height, width, nFrame)); u = double(zeros(height/2, width/2, nFrame)); v = double(zeros(height/2, width/2, nFrame)); for iFrame = 1:nFrame frame = stream((iFrame-1)*length+1:iFrame*length); % Y component of the frame yImage = reshape(frame(1:width*height), width, height)'; % U component of the frame uImage = reshape(frame(width*height+1:1.25*width*height), width/2, height/2)'; % V component of the frame vImage = reshape(frame(1.25*width*height+1:1.5*width*height), width/2, height/2)'; y(:,:,iFrame) = double(yImage); u(:,:,iFrame) = double(uImage); v(:,:,iFrame) = double(vImage); end u=imresize(u,size(y),'bicubic'); v=imresize(v,size(y),'bicubic'); yuv=cat(3,y,u,v); T = [1,0,1.28033;1,-0.21482,-0.38059;1,2.12798,0]; RGB(:,:,1) = T(1)*yuv(:,:,1) + T(4)*yuv(:,:,2) + T(7)*yuv(:,:,3) ; RGB(:,:,2) = T(2)*yuv(:,:,1) + T(5)*yuv(:,:,2) + T(8)*yuv(:,:,3) ; RGB(:,:,3) = T(3)*yuv(:,:,1) + T(6)*yuv(:,:,2) + T(9)*yuv(:,:,3) ; figure,imshow(uint8(RGB)) 

Expert Answer:

The sample file is 8 bit (not 10 bit), and the storage format is tricky.

The tool allows you selecting the format.
The suitable format is as follows:
enter image description here

The frame is divided to two fields - upper filed and lower filed (interlace format).
Resolution of each filed is 176x72.
Because the format is YUV420, the size of U and V fields is 88x36.

The code sample uses the following stages:

  • Read the upper filed of Y, U and V (8 bits per element).
  • Read the lower filed of Y, U and V.
  • Interleave upper and lower filed.
  • Up-sample U and V to the size of Y.
  • Convert YUV to RGB (use existing MATLAB function ycbcr2rgb).

The following code sample reads the first frame and convert to RGB: 

 

fname = 'tulips_yuv420_inter_planar_qcif.yuv'; width = 176; height = 144; fid = fopen(fname, 'r'); % Open the video file Y0 = (fread(fid, [width, height/2], 'uint8'))'; %Read upper field of Y plane U0 = (fread(fid, [width/2, height/4], 'uint8'))'; %Read lower field of Y plane V0 = (fread(fid, [width/2, height/4], 'uint8'))'; %Read upper field of U plane Y1 = (fread(fid, [width, height/2], 'uint8'))'; %Read upper field of Y plane U1 = (fread(fid, [width/2, height/4], 'uint8'))'; %Read lower field of U plane V1 = (fread(fid, [width/2, height/4], 'uint8'))'; %Read lower field of V plane fclose(fid); %Interleave upper and lower fields Y = zeros(height, width); Y(1:2:end, :) = Y0; Y(2:2:end, :) = Y1; U = zeros(height/2, width/2); U(1:2:end, :) = U0; U(2:2:end, :) = U1; V = zeros(height/2, width/2); V(1:2:end, :) = V0; V(2:2:end, :) = V1; U = imresize(U, size(Y), 'bicubic'); V = imresize(V, size(Y), 'bicubic'); YUV = cat(3, Y, U, V); %Convert YUV to RGB (MATLAB function ycbcr2rgb uses BT.601 conversion formula). RGB = ycbcr2rgb(uint8(YUV)); figure,imshow(RGB) 

Result:
enter image description here


Reading 10 bit YUV420:

Assumptions:

  • Each 10 bits component is stored in 2 bytes (no "bits packing").
  • Data is stored in lower part of each byte (each uint16 element holds a value in range [0, 1023]).
  • Storage format is the same non-standard interlace format as the uint8 sample.

Build 10 bits YUV420 sample file from the 8 bits sample (singe frame for testing):
The following code build a 10 bits sample out of the 8 bits sample (expands the range from 8 bits stored in uint8 to 10 bits stored in uint16). 

 

fname = 'tulips_yuv420_inter_planar_qcif.yuv'; width = 176; height = 144; fid = fopen(fname, 'r'); % Open the video file Y0 = (fread(fid, [width, height/2], 'uint8'))'; %Read upper field of Y plane U0 = (fread(fid, [width/2, height/4], 'uint8'))'; %Read lower field of Y plane V0 = (fread(fid, [width/2, height/4], 'uint8'))'; %Read upper field of U plane Y1 = (fread(fid, [width, height/2], 'uint8'))'; %Read upper field of Y plane U1 = (fread(fid, [width/2, height/4], 'uint8'))'; %Read lower field of U plane V1 = (fread(fid, [width/2, height/4], 'uint8'))'; %Read lower field of V plane fclose(fid); fid = fopen('10bits__tulips_yuv420_inter_planar_qcif.yuv', 'w'); % Open for writing fwrite(fid, uint16(Y0'*(1023/255)), 'uint16'); %1023 = 2^10-1, and 255 = 2^8-1 fwrite(fid, uint16(U0'*(1023/255)), 'uint16'); fwrite(fid, uint16(V0'*(1023/255)), 'uint16'); fwrite(fid, uint16(Y1'*(1023/255)), 'uint16'); fwrite(fid, uint16(U1'*(1023/255)), 'uint16'); fwrite(fid, uint16(V1'*(1023/255)), 'uint16'); fclose(fid);

Reading 10 bit YUV420
The following code reads single frame of 10 bit YUV420 (matching list of assumptions): 

 

fname = '10bits__tulips_yuv420_inter_planar_qcif.yuv'; width = 176; height = 144; fid = fopen(fname, 'r'); % Open the video file Y0 = (fread(fid, [width, height/2], 'uint16'))'; %Read upper field of Y plane U0 = (fread(fid, [width/2, height/4], 'uint16'))'; %Read lower field of Y plane V0 = (fread(fid, [width/2, height/4], 'uint16'))'; %Read upper field of U plane Y1 = (fread(fid, [width, height/2], 'uint16'))'; %Read upper field of Y plane U1 = (fread(fid, [width/2, height/4], 'uint16'))'; %Read lower field of U plane V1 = (fread(fid, [width/2, height/4], 'uint16'))'; %Read lower field of V plane fclose(fid); %Interleave upper and lower fields Y = zeros(height, width); Y(1:2:end, :) = Y0; Y(2:2:end, :) = Y1; U = zeros(height/2, width/2); U(1:2:end, :) = U0; U(2:2:end, :) = U1; V = zeros(height/2, width/2); V(1:2:end, :) = V0; V(2:2:end, :) = V1; U = imresize(U, size(Y), 'bicubic'); V = imresize(V, size(Y), 'bicubic'); YUV = cat(3, Y, U, V); %Convert elements range from [0, 1023] to range [0, 1] (MATLAB function ycbcr2rgb supports doubles in range [0, 1]). YUV = YUV/1023; %1023 applies 10 bits range. 2^10-1 = 1023 %Convet YUV to RGB (MATLAB function ycbcr2rgb uses BT.601 conversion formula). RGB = ycbcr2rgb(YUV); %Convert from double to uint8 (from range [0, 1] to range [0, 255]). RGB = im2uint8(RGB); figure,imshow(RGB)

Note:
The code YUV = YUV/1023 converts the "10 bits" format to [0, 1] double format.
Conversion is used because ycbcr2rgb is not supporting 10 bits input.


Computing the size of the file:
You are correct: "The size of one frame equals 1.5*the size of Y".
Assuming 10 bits component is stored in 2 bytes, size of Y is width*height*2, and size of one frame is width*height*3.

Why Matlabhelpers ?

Looking for reliable MATLAB assignment help? Our expert MATLAB tutors deliver high-quality, easy-to-understand solutions tailored to your academic needs. Whether you're studying at Monash University, the University of Sydney, UNSW, or the University of Melbourne, we provide trusted MATLAB assistance to help you excel. Contact us today for the best MATLAB solutions online and achieve academic success!

MATLAB Assignment Help Services

Personalized Tutoring: Get one-on-one guidance from our MATLAB experts. Whether you're tackling basic concepts or advanced algorithms, we provide clear, step-by-step explanations to help you master MATLAB with confidence.

Assignment Assistance: Struggling with tight deadlines or complex assignments? Our team offers end-to-end support, from problem analysis to code development and debugging, ensuring your assignments meet the highest academic standards.

Project Development: Need expert help with your MATLAB research project? We assist in designing and implementing robust solutions, covering project planning, data collection, coding, simulation, and result analysis.

Coursework Support: Enhance your understanding of MATLAB with our comprehensive coursework assistance. We help you grasp lecture concepts, complete lab exercises, and prepare effectively for exams.

Thesis and Dissertation Guidance: Incorporate MATLAB seamlessly into your thesis or dissertation. Our experts provide support for data analysis, modeling, and simulation, ensuring your research is methodologically sound and impactful.

Contact us on WhatsApp for MATLAB help

Contact us on Telegram for MATLAB solutions