MATLAB讀取一張RGB圖片轉成YUV格式


 1.讀入照片

控制輸出的標志定義

clc;close all;clear 
YES = 1; NO = 0;
%YES表示輸出該文件,請用戶配置
yuv444_out_txt = 1;   
yuv444_out_yuv = 0;

yuv422_out_txt = 0; 
yuv422_out_yuv = 0;

yuv420_out_txt = 0; 
yuv420_out_yuv = 1;
filename = 'Koala.jpg';
filestr = filename(1:findstr(filename,'.jpg')-1);
filepath = ['.\' filestr 'out\']
mkdir(filepath);
filestr = [filepath filestr];
RGBimg =imread(filename);
figure;imshow(RGBimg);

 1)讀入的照片由filename 配置,這里照片必須放在該目錄下。如:filename = 'Koala.jpg'

 2)filename找到字符串的起始位置。findstr('Koala.jpg','.jpg') = 6,所以就可以取到去掉后綴名的文件名

 3)得到一個 .\文件名out\的目錄

 4)創建該目錄

 5)filestr = 目錄+文件名,用於后面的數據輸出,方便輸出到 .\文件名out\目錄下。這里 filestr = '.\Koalaout\Koala'

2. 調用matlab函數將rgb轉換成yuv

YUVimg = rgb2ycbcr(RGBimg);     %%% rgb -> yuv
figure;imshow((YUVimg));

3.分別取出YUV

  Y,U,V數據保留矩陣存儲方式,方便后面的4:2:2,4:2:0采樣,更加直觀

[imgHeight imgWidth imgDim] = size(YUVimg);         %%
len = imgHeight*imgWidth*imgDim;
yuvimout = zeros(1,len);
Y = YUVimg(:,:,1);     % Y 矩陣
U = YUVimg(:,:,2);     % U 矩陣
V = YUVimg(:,:,3);     % V 矩陣
Yvec = reshape(YUVimg(:,:,1)',1,[]); % 矩陣整理成行向量
Uvec = reshape(YUVimg(:,:,2)',1,[]);
Vvec = reshape(YUVimg(:,:,3)',1,[]);
yuvimout(1:3:len) = Yvec;
yuvimout(2:3:len) = Uvec;
yuvimout(3:3:len) = Vvec;

 注意:reshape矩陣時,需要對結果做轉置,保證是按行來將矩陣整理成行向量的

4.輸出YUV444的數據到文件

%%
% 輸出圖像的yuv數據到 .txt
%
if yuv444_out_txt == YES
    filename = [filestr '_444.txt'];
    fid= fopen(filename,'w');
        fprintf(fid,'%02x\n',yuvimout);
    fclose(fid);
    disp('yuv444_out_txt YES');
else
    disp('yuv444_out_txt NO');
end

 在本例中:filename = [filestr '_444.txt'] = '.\Koalaout\Koala_444.txt'

%%
% 輸出圖像的yuv數據到 .yuv
% 四個像素為:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
%
% 存放的碼流:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
%
% 映射的像素: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
if yuv444_out_yuv == YES
    filename = [filestr '_444.yuv'];
    fid= fopen(filename,'wb');
        fwrite(fid,yuvimout,'uint8');
    fclose(fid);
    disp('yuv444_out_yuv YES');
else
    disp('yuv444_out_yuv NO');
end

 5.將 YUV4:4:4 轉成 YUYV 4:2:2 packed

%%
% YUV4:4:4 -->> YUYV 4:2:2
% 四個像素為:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
%
% 存放的碼流:[Y0 U0] [Y1 V1] [Y2 U2] [Y3 V3]
%
% 映射的像素: [Y0 U0 V1] [Y1 U0 V1] [Y2 U2 V3] [Y3 U2 V3]
%%%
len = imgHeight*imgWidth+imgHeight*imgWidth/2+imgHeight*imgWidth/2;
yuv422out = zeros(1,len);
yuv422sampY = Y;
yuv422sampU = U(:,1:2:size(U,2));
yuv422sampV = V(:,2:2:size(V,2));
yuv422out(1:2:len) = reshape(yuv422sampY',1,[]);  %%% 注意要轉置
yuv422out(2:4:len) = reshape(yuv422sampU',1,[]);
yuv422out(4:4:len) = reshape(yuv422sampV',1,[]);

 說明:

1)4:2:2模式是保留所有的Y,U,V是每間隔1列抽取抽樣一個點,如代碼中所示。

2)YUYV 4:2:2 packed 即像素值是 YU/YV 交替存儲的模式。存放的碼流:[Y0 U0] [Y1 V1] [Y2 U2] [Y3 V3]

 輸出數據到文件

%%
% 輸出圖像的yuv422數據到 .txt
%
if yuv422_out_txt == YES
    filename = [filestr '_422.txt'];
    fid= fopen(filename,'w');
        fprintf(fid,'%02x\n',yuv422out);
    fclose(fid);
    disp('yuv422_out_txt YES');
else
    disp('yuv422_out_txt NO');
end
% output yuyv422 to .yuv file
if yuv422_out_yuv == YES
    filename = [filestr '_422yuyv.yuv'];
    fid= fopen(filename,'wb');
        fwrite(fid,yuv422out,'uint8');
    fclose(fid);
    disp('yuv422_out_yuv YES');
else
    disp('yuv422_out_yuv NO');
end

 6. 將 YUV4:4:4 轉成 YV12 4:2:0 planar

%%
% YUV4:4:4 -->> YUYV 4:2:0
% output yuyv422 to .yuv file
% 第一行四個像素為:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
% 第二行四個像素為:[Y4 U4 V4] [Y5 U5 V5] [Y6 U6 V6] [Y7 U7 V7]
% 4:2:0 采樣
% 第一行采樣像素為:[Y0 U0   ] [Y1      ] [Y2 U2   ] [Y3      ]
% 第二行采樣像素為:[Y4    V4] [Y5      ] [Y6    V6] [Y7      ]
% 420yv12 planar 的存儲碼流: [Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7] [V4 V6] [U0 U2]
% 映射的像素:  [Y0 U0 V4] [Y1 U0 V4] [Y2 U2 V6] [Y3 U2 V6]
%             [Y4 U0 V4] [Y5 U0 V4] [Y6 U2 V6] [Y7 U2 V6]
%%%
len = imgHeight*imgWidth+imgHeight*imgWidth/4+imgHeight*imgWidth/4;
yuv420out = [];
yuv420sampY = Y;
yuv420sampU = U(1:2:size(U,1),1:2:size(U,2));
yuv420sampV = V(2:2:size(V,1),1:2:size(V,2));
%%%yuv420out = [y v u]  % yuv420 yv12 format
yuv420out = [yuv420out reshape(yuv420sampY',1,[])];    %Y 注意要轉置
yuv420out = [yuv420out reshape(yuv420sampV',1,[])];    %V
yuv420out = [yuv420out reshape(yuv420sampU',1,[])];    %U

說明:

1)yuv420sampU = U(1:2:size(U,1),1:2:size(U,2)); 從圖片的第一行開始 每間隔1行 和 每間隔1列 采樣一個U

2)yuv420sampV = V(2:2:size(V,1),1:2:size(V,2)); 從圖片的第二行開始 每間隔1行 和 每間隔1列 采樣一個V

數據數據到文件

%%
% 輸出圖像的yuv422數據到 .txt
%
if yuv420_out_txt == YES
    filename = [filestr '_420.txt'];
    fid= fopen(filename,'w');
        fprintf(fid,'%02x\n',yuv420out);
    fclose(fid);
    disp('yuv420_out_txt YES');
else
    disp('yuv420_out_txt NO');
end
% output yuyv420 to .yuv file
if yuv420_out_yuv == YES
    filename = [filestr '_420yv12.yuv'];
    fid= fopen(filename,'wb');
        fwrite(fid,yuv420out,'uint8');
    fclose(fid);
    disp('yuv420_out_yuv YES');
else
    disp('yuv420_out_yuv NO');
end

 觀察命令輸出,並等待關閉

disp('---program run susseed---');
disp('---press any key to close all figure---');
system('pause');
close all;

打開輸出的yuv文件查看圖片

參考

http://www.cnblogs.com/xkfz007/archive/2012/07/31/2616806.html
http://www.xuebuyuan.com/1541892.html
http://www.fourcc.org/yuv.php

 代碼鏈接:

http://pan.baidu.com/s/1pLMRcmB

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM