YUV420序列轉成圖片


首先聲明一點,這里的YUV其實不是YUV,嚴格來說是YCbCr。這里就先這樣稱呼YUV吧。本文是關於YUV420格式的視頻轉成圖片序列的。

關於YUV格式的圖片,存儲如下圖所示:

舉個例子,一個640*480的420的圖片,讀入matlab中的數據量為460800個數據。

460800/640*480=3/2。相當於每二個像素有3個數據。

 

如果想要把一個YUV文件轉成RGB數據,那么必須要知道這個YUV文件是怎么以文件格式存儲的。舉個例子,假如一張4*4的大小的圖片,它的YUV420格式的存儲是這樣的,如下圖:

這只是一個示意圖,假如一個圖片是100*100像素的,那么它的存儲文件中,前100*100=10000個字節是用來存儲Y的。接下來2500個字節是用來存儲U的,然后的2500個字節是用來存儲V的。

當然這種格式也不是唯一的,我發現大多數的圖片都是這種格式。當然還有其他的方式來驗證一個圖片是不是這樣的格式。對於一個YUV420格式的圖片來說,它一幀畫面的數據量是它像素數的1.5倍,當然,我們肯定是知道一幀畫面的分辨率的,然后可以讀入YUV420視頻文件中的1.5*X*Y個數據量,然后查看它對應有圖片。如圖所示:

紅框中的是Y數據,藍框中的是U數據,黃框中的是V數據。
現在應該可以得到一個YUV幀的YUV分量啦,接下來要做的就是把這三個分量加權求和,生成R,G,B分量啦。加權公式如下:
    R=1.164*(Y-16)+1.596*(VV-128);
    G=1.164*(Y-16)-0.813*(UU-128)-0.392*(VV-128);
    B=1.164*(Y-16)+2.017*(UU-128);

這里要注意一下,這里的YUV最好是double型的,我剛才始生成RGB的時候,YUV都是uint8型的,最后生成的圖片顏色總是不對,換成double型的話,就沒有問題啦,注意一下,double型的數據還要再歸一化或者強制轉換成uint8型的數據,才可以用imshow()顯示出來。還有RGB三個分量矩陣中,大於255的量要設置成255,小於0的元素要設置為0。

本實驗中用的圖片恢復出來,如下圖所示:

大功告成。

本程序實現代碼如下圖所示:

 

[plain]  view plain  copy
 
  1.   
[plain]  view plain  copy
 
  1.   

%函數功能:這個函數用於加載一個UYV序列文件
%入口參數:  path是包含要讀寫YUV序列的地址的字符串
%           x,y是這個圖片的高與寬
%           start表示要從第幾幀開始讀取畫面
%           count表示要讀出的圖片的張數
%出口參數:  picout(x,y,,3,count)表示出口參數
function [picout]=loadYUV(path,x,y,start,count);


% clear;
% clc


% x=288;
% y=352;
% count=10;
% path='e:\test-pic\flower.yuv';
fid=fopen(path,'r');


for ii=1:count
    fseek(fid,1.5*x*y*(ii-1+start-1),-1);
    pic=uint8(fread(fid,[y,1.5*x],'uint8'));
    pic=pic';
    Y=double(pic(1:x,:));
    u=double(pic(x+1:1.25*x,:));
    v=double(pic(1.25*x+1:1.5*x,:));
    for i=1:0.25*x
        U(2*i-1,1:y/2)=u(i,1:y/2);
        U(2*i,1:y/2)=u(i,y/2+1:y);
        V(2*i-1,1:y/2)=v(i,1:y/2);
        V(2*i,1:y/2)=v(i,y/2+1:y);
    end


    UU=imresize(U,2);
    VV=imresize(V,2);


%     R=Y+1.140*(VV-128);
%     G=Y-0.395*(UU-128)-0.581*(VV-128);
%     B=Y+2.032*(UU-128);   
    R=1.164*(Y-16)+1.596*(VV-128);
    G=1.164*(Y-16)-0.813*(UU-128)-0.392*(VV-128);
    B=1.164*(Y-16)+2.017*(UU-128);


    for i=1:x
    for j=1:y
    if R(i,j)<0
    R(i,j)=0;
    end
    if R(i,j)>255
    R(i,j)=255;
    end
    if G(i,j)<0
    G(i,j)=0;
    end
    if G(i,j)>255
    G(i,j)=255;
    end
    if B(i,j)<0
    B(i,j)=0;
    end
    if B(i,j)>255
    B(i,j)=255;
    end
    end
    end
    R=uint8(R);
    G=uint8(G);
    B=uint8(B);
    %R=R/255;G=G/255;B=B/255;
    picout(:,:,:,ii)=cat(3,R,G,B);
end
%imshow(picout(:,:,:,1));
上文只是一個子程序,但是絕對可用。


免責聲明!

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



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