首先聲明一點,這裏的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
本程序實現代碼以下圖所示:
%函數功能:這個函數用於加載一個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));上文只是一個子程序,可是絕對可用。