首先声明一点,这里的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));上文只是一个子程序,可是绝对可用。