YUV420序列轉成圖片

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

關於YUV格式的圖片,存儲以下圖所示:函數

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

460800/640*480=3/2。至關於每二個像素有3個數據。spa

 

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

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

固然這種格式也不是惟一的,我發現大多數的圖片都是這種格式。固然還有其餘的方式來驗證一個圖片是否是這樣的格式。對於一個YUV420格式的圖片來講,它一幀畫面的數據量是它像素數的1.5倍,固然,咱們確定是知道一幀畫面的分辨率的,而後能夠讀入YUV420視頻文件中的1.5*X*Y個數據量,而後查看它對應有圖片。如圖所示:htm

紅框中的是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。blog

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

大功告成。ip

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

 

[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));上文只是一個子程序,可是絕對可用。

相關文章
相關標籤/搜索