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));上文只是一个子程序,可是绝对可用。

相关文章
相关标签/搜索