zoukankan      html  css  js  c++  java
  • 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: est-picflower.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));
    上文只是一个子程序,但是绝对可用。

  • 相关阅读:
    fafu 1231 dp(线段树优化dp)
    OUTLOOK+VBA 备份邮件到GMAIL
    心灵的程序:佛学与计算机
    建议增加编辑器插件“自动排版”
    高效演讲:简单四步走
    找呀找呀找地铁
    为什么你总是烦?
    变形金刚之雷曼疯狂兔子:抽水马桶变身
    客观:别人的主观
    用VBSCRIPT朗读文本
  • 原文地址:https://www.cnblogs.com/liangxiaofeng/p/6943553.html
Copyright © 2011-2022 走看看