Matlab 10位YUV420到RGB转换
我正在处理从YUV420到RGB的转换,但是图像的颜色不好。最初我自己的文件是10位的。最初,我从8位文件开始 我使用下面的代码读取YUV420图像并转换为RGB。因为我有YUV420.YUV图像文件,但该代码用于视频,所以我只读取1帧。然后我得到YUV是全尺寸,而U和V是维基百科上描述的一半尺寸。然后,我将图像调整为图像的完整大小,并将YUV应用于RGB转换。但是RGB图像的颜色不正确。我已经附加了文件,以便您可以运行并查看问题所在。这是YUV文件 我还有两个问题 首先,一帧的“流”的大小应该等于Y的大小的1.5倍,但是无论我使用uint8还是uint16来读取文件,它都非常大 其次,如果我有10位YUV420文件,我如何修改此代码以显示正确的RGBMatlab 10位YUV420到RGB转换,matlab,image-processing,video-processing,yuv,Matlab,Image Processing,Video Processing,Yuv,我正在处理从YUV420到RGB的转换,但是图像的颜色不好。最初我自己的文件是10位的。最初,我从8位文件开始 我使用下面的代码读取YUV420图像并转换为RGB。因为我有YUV420.YUV图像文件,但该代码用于视频,所以我只读取1帧。然后我得到YUV是全尺寸,而U和V是维基百科上描述的一半尺寸。然后,我将图像调整为图像的完整大小,并将YUV应用于RGB转换。但是RGB图像的颜色不正确。我已经附加了文件,以便您可以运行并查看问题所在。这是YUV文件 我还有两个问题 首先,一帧的“流”的大小应该
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))
示例文件是8位(不是10位),存储格式很复杂
该工具允许您选择格式。合适的格式如下:
帧分为两个字段-上字段和下字段(隔行扫描格式)。
每个文件的分辨率为176x72。
因为格式是YUV420,所以U和V字段的大小是88x36 代码示例使用以下阶段:
- 读取Y、U和V的上部字段(每个元素8位)李>
- 读取Y、U和V的较低字段
- 交错上下两个字段李>
- 将样品U和V增大到Y的大小
- 将YUV转换为RGB(使用现有的MATLAB函数
)李>ycbcr2rgb
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)
结果:读取10位YUV420: 假设:
- 每个10位组件存储在2个字节中(无“位打包”)李>
- 数据存储在每个字节的下半部分(每个
元素保存一个范围为[01023]的值)李>uint16
- 存储格式与
样本的非标准隔行格式相同李>uint8
以下代码从8位样本中构建10位样本(将范围从存储在
uint8
中的8位扩展到存储在uint16
中的10位)
读取10位YUV420以下代码读取10位YUV420的单帧(匹配假设列表): 注:
代码
YUV=YUV/1023
将“10位”格式转换为[0,1]double
格式。之所以使用转换,是因为
ycbcr2rgb
不支持10位输入
计算文件大小:
您是正确的:“一帧的大小等于1.5*Y的大小”。
假设10位组件存储在2个字节中,Y的大小是宽度*高度*2,一帧的大小是宽度*高度*3 请问您使用的工具是什么?您发布的工具。备注:工具未在我的机器中显示视频。@Rotem你说得对,上图为8比特。但我的第二个问题是如何阅读10位YUV420。谢谢你,如果我不得不猜的话。。。每个10位组件存储在2个字节中,最有可能存储在每个字节的下半部分(每个
uint16
元素保存一个范围为[01023]的值)。它是相同的非标准隔行扫描格式吗?你能提供一个样本文件吗?我更新了答案。对于您的10位输入,解决方案很可能无法“按原样”工作。有太多的假设。。。
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);
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)