YUV图像格式学习与灰度处理

YUV图像格式学习与灰度处理

前言

  • 刚入职不久,导师要我完成一个任务,就是将将彩色YUV图像数据处理成黑白色,由于对YUV并不了解,所以才有了下面的学习。

YUV概述

  • YUV与RGB一样,都是像素数据的编码格式,一组YUV渲染屏幕上的一个像素,控制屏幕用色彩的形式将事物表现出来,其中Y表示像素中的亮度,U表示色度,V表示浓度或饱和度。它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白色。这是一种压缩后的颜色表示方法,占用更少的物理空间,且对颜色的表现失真不明显,所以现在YUV格式非常常用。

YUV存储方式

  • YUV有两种存储方式:planar、packed。
    • planar:从字面意思上来看,planar是平面的意思,对应到存储方式上就是把YUV三种分量分别存储,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。这种在解析时很方便。
    • packed:从字面意思来看,packed是打包的意思,对应到存储方式上就是把YUV三种分量连续交叉存储,这种方式在解析时比较麻烦。

YUV的采样方式

  • 采样方式即如何表现一个像素,现在主流的有三种采样方式,4:4:4、4:2:2、4:2:0,这三种比例是YUV三种分量的比例,前面提到一个像素应该包含一个Y、一个U、一个V,如果要完全存储,那一个像素点就要存储YUV三个分量,这种形式就是4:4:4。但是因为人的眼睛对色度和饱和度不是特别敏感,所以一定程度上丢失一部分UV并不影响我们分辨颜色,所以为了节省存储空间,在存储时就故意丢掉部分UV分量,用两个Y分量共用一组UV分量,这种形式就是4:2:2,或用四个Y分量共用一组UV,这种形式就是4:2:0。
    YUV 4:4:4采样,每一个Y对应一组UV分量。
    YUV 4:2:2采样,每两个Y共用一组UV分量。 
    YUV 4:2:0采样,每四个Y共用一组UV分量。
    YUV图像格式学习与灰度处理_第1张图片

     

 

  • 在存储时YUV各占一个字节Byte,如果4:4:4方式,那一个256X256分辨率的图片要占用256×256×3=196608Byte,4:2:2方式要占用256×256×2=131072Byte,4:2:0方式要占用256×256×2/3=43690.7Byte,可以看到采用4:2:0方式存储空间整整减少了一半。

  • 以YUV420为例说明:

图像像素数据:[Y0 U0 V0]、[Y1 U1 V1]、 [Y2 U2 V2]、 [Y3 U3 V3]

             [Y5 U5 V5]、[Y6 U6 V6]、 [Y7 U7 V7] 、[Y8 U8 V8]

采样的码流:  Y0 U0 Y1 Y2 U2 Y3

             Y5 V5 Y6 Y7 U7 Y8

映射出的像素点为:
             [Y0 U0 V5]、[Y1 U0 V5]、[Y2 U2 V7]、[Y3 U2 V7]
             [Y5 U0 V5]、[Y6 U0 V5]、[Y7 U2 V7]、[Y8 U2 V7]

 

YUV常用格式

YU12/I420,YV12格式(属于YUV420)(planar方式存储,简称420p)

  • YU12:先把全部的Y分量存完,再存U分量,最后存V分量。YUV图像格式学习与灰度处理_第2张图片

 

  • YV12:先把全部的Y分量存完,再存V分量,最后存U分量,对应到上图把第五行和第六行位置互换一下就是了。

NV12,NV21 (属于YUV420) (planar和packed混合存储,简称420sp)

  • NV12:该格式是先存储全部的Y分量,然后UV分量交叉存储。
  • YUV图像格式学习与灰度处理_第3张图片

 

  • NV21:该格式与NV12唯一的区别只是UV分量交叉的顺序不同,NV12是U排前面,NV21是V排前面。
  • YUV图像格式学习与灰度处理_第4张图片
```java
I420: YYYYYYYY UU VV =>YUV420P
YV12: YYYYYYYY VV UU =>YUV420P
NV12: YYYYYYYY UVUV =>YUV420SP
NV21: YYYYYYYY VUVU =>YUV420SP //安卓Camera默认格式
```

YUV422P(属于YUV422)(planar方式存储)

  • 该格式存储方式与YU12是一样的,唯一的区别是UV分量的数量不同,YU12中四个Y共用一组UV,而该格式中两个Y共用一组UV。
  • YUV图像格式学习与灰度处理_第5张图片

YUYV/YUY2, YVYU,UYVY(属于YUV422)(packed方式存储)

  • YUYU/YUY2:每两个Y分量共用一组UV分量,存储顺序是YUYV。
  • YUV图像格式学习与灰度处理_第6张图片
  • YVYU:该格式与YUYV相似,只是存储时UV分量顺序不同而已。
  • UYVY:与上面两种方式并无大的不同。
  • YUV图像格式学习与灰度处理_第7张图片

YUV图像处理

  • 这是使用YUV格式主要是NV12和NV21。

灰度处理

  • 如果要把YUV格式像素变成灰度图像,只需要将U、V分别设置为128即可。因为U、V是图像经过偏置处理的色度分量,色度分量在偏置处理前的取值范围为-128至127,此时的无色对应的"0"值,经过偏置后色度分量取值变成了0至255,这时候无色对应的值就是128。
//读取YUV文件(格式是NV12或NV21)
bool read_yuv_one(const string path_in,const string path_out) {
    //读取YUV文件
    FILE *in, *out;
    in = fopen(path_in.c_str(), "rb");
    out = fopen(path_out.c_str(), "rb");

    //获取YUV文件的大小
    fseek(in, 0L, SEEK_END);
    int len = ftell(in);
    fseek(in, 0L, SEEK_SET);

    //创建缓存YUV文件的Buffer
    char* buff = new char[len];
    //读取YUV文件到Buffer
    fread(buff, sizeof(char), len, in);
    memset(buff + len * 2 / 3, 128, len / 3);
    fwrite(buff, sizeof(char), len, out);
    fclose(in);
    fclose(out);

    return true;
}

 

亮度减半

  • 只需要将YUV数据中的亮度分量Y的数值减半的方法,降低图像的亮度。

Linux查看YUV图像文件的方法

  • ffplay -f rawvideo -video_size 高x宽 图像名称.yuv

参考链接

https://www.cnblogs.com/daner1257/p/10767570.html

https://blog.csdn.net/qingkongyeyue/article/details/52801396

https://blog.csdn.net/leixiaohua1020/article/details/50534150

你可能感兴趣的:(图像处理,Android相机,C++,YUV图像格式,YUV图像处理)