YUV格式详解

  • YUV
    • YUV 采样
      • YUV 4:4:4
      • YUV 4:2:2
      • YUV 4:2:0
      • YUV 4:1:1
    • planar format
      • Packed (or Interleaved)
      • Planar
      • Semi-Planar
    • 关系图
  • YUV 与 RGB 相互转换
    • 计算公式推导
      • 1. 模拟 RGB转YUV的推导公式
      • 2. 数字 RGB to YUV
    • 1. 模拟YUV→模拟RGB
    • 2. 数字YUV→数字RGB
    • YUV与RGB的相互转换会损失图象质量
  • 计算
    • YUV计算文件大小
    • YUV计算帧数
    • sample map
    • 大小端序(字节序)
  • 一些常用格式
    • YUV格式关系
    • 常见的YUV格式存储排列方式

YUV

YUV是指亮度参量和色度参量分开表示的像素格式,其中“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V”表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
Y: 表示明亮度(Luminance或Luma)
U和V: 色度(Chrominance或者Chroma), 作用是描述影像色彩及饱和度,用于指定像素的颜色。

YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。
YCbCr 则是在世界数字组织视频标准研制过程中作为ITU - R BT.601 建议的一部分,其实是YUV经过缩放偏移的翻版。其中Y与YUV 中的Y含义一致,Cb,Cr 同样都指色彩,只是在表示方法上不同而已。在YUV 家族中,YCbCr 是在计算机系统中应用最多的成员,其应用领域很广泛,JPEG、MPEG均采用此格式。一般人们所讲的YUV大多是指YCbCr。YCbCr 有许多取样格式,如4∶4∶4,4∶2∶2,4∶1∶1 和4∶2∶0。

YUV 采样

色度通道的采样率可以低于亮度通道,而不会显著降低感知质量。

4:4:4 表示完全取样。
4:2:2 表示2:1的水平取样,垂直完全采样。
4:2:0 表示2:1的水平取样,垂直2:1采样。
4:1:1 表示4:1的水平取样,垂直完全采样。

最常用Y:UV记录的比重通常1:1或2:1,Video是以YUV4:2:0的方式记录,也就是我们俗称的I420,YUV4:2:0并不是说只有U(即Cb),V(即Cr)一定为0,而是指U:V互相援引,时见时隐,也就是说对于每一个行,只有一个U或者V分量,如果一行是4:2:0的话,下一行就是4:0:2,再下一行是4:2:0…以此类推。至于其他常见的YUV格式有YUY2、YUYV、YVYU、UYVY、AYUV、Y41P、Y411、Y211、IF09、IYUV、YV12、YVU9、YUV411、YUV420等。

为了方便举例说明,这里使用ffmpeg生成一个320x320分辨率的yuvj444p

# 用ffmpeg testsrc 生成一个完全取样的的YUV文件 yuvj444p
ffmpeg  -f lavfi -i testsrc -frames 10 -pix_fmt yuvj444p -s 320x320 yuvj444p_320x320.yuv
# 基于yuvj444p转换成422、420、411等
ffmpeg -pix_fmt yuvj444p -s 320x320 -i yuvj444p_320x320.yuv -pix_fmt yuvj420p yuvj420p_320x320.yuv
ffmpeg -pix_fmt yuvj444p -s 320x320 -i yuvj444p_320x320.yuv -pix_fmt yuv422p yuv422p_320x320.yuv
ffmpeg -pix_fmt yuvj444p -s 320x320 -i yuvj444p_320x320.yuv -pix_fmt yuvj411p yuvj411p_320x320.yuv

图像效果如下图所示

YUV 4:4:4

完全取样,每个像素都有独立的Y/U/V值

为了方便对比,我们挑画面下方横条渐变色块6x5个像素放大40倍,看像素的YUV值(其它采样也取相同位置)。
从如下图所示,可以看出相邻的像素点的Y/U/V值不相等也可以看出每个像素都有独立的U/V值

YUV 4:2:2

每两个Y共用一对U/V值

422采样,水平方向每两个像素共用一对U/V值,下如图绿色框(U channel)和蓝色框(V channel)标记的一个框在内存中只有一个值。

YUV 4:2:0

每四个Y共用一对U/V值

420采样,因为是相邻的4个像素共用一对U/V,所以会出现如下图所示,每四个相邻的像素就出现4个相同的UV值。

YUV 4:1:1

与YUV 4:2:0类似,都是四个每四个Y共用一对U/V值,区别是4:1:1是水平方向的4个Y共享一对U/V,如下图所示,第1-4个Y使用同一对U/V值,第5-8个Y使用同一对U/V值,依次类推。。。

这里就不截图举例了,由于411采样的不太常用的以致于一般工具都不支持播放,有了422的例子其实也好更多,411相当于在422的基础上再在水平方向下采样,即水平方向每连续4个像素共用一对UV。

planar format

Packed (or Interleaved)

将YUV三个分量的素数值放在同一个阵列中,存储为单个阵列宏像素
将每个像素点的Y/U/V连续交叉存储
以UYVY、YUYV为例,由两个像素的Y/U/V组成一个宏像素,依次排列

  1. UYVY

U0Y0V0Y1 U2Y2V2Y3 U4Y4V4Y5 U6Y6V6Y7 …

  1. YUYV

Y0U0Y1V0 Y2U2Y3V2 Y4U4Y5V4 Y6U6Y7V6 …

Planar

每个分量存储为单独的数组,最终图像是三个单独平面的整合
以I420为例Y/U/V排列如下:

width: 图像分辨率的宽
height: 分辨率高
n = width * height
m = width * height / 4
Y0Y1Y2Y3Y4Y5…Yn U0U1U2U3…Um V0V1V2V3…Vm

Semi-Planar

介于Pakced和Planar之间,即Y分量为一个阵列,UV交叉存储
NV12

width: 图像分辨率的宽
height: 分辨率高
n = width * height
m = width * height / 4
Y0Y1Y2Y3Y4Y5…Yn U0V0U1V1U2V2U3V3…UmVm

Note:
格式的名称以“ p”结尾的一般都是planar格式,如在ffmpeg 中的yuvj420p格式
格式的名称以“ sp”结尾的一般都是semi-planar格式, 如

关系图

如下图,树的第四层只是列举部分并非全部,理论上树的第4层可以通过YUV的排列、位深、色彩范围(full range和limited range)等自由组合出来非常多的格式。

#mermaid-svg-W9HuglUe57n6b0ke .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-W9HuglUe57n6b0ke .label text{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke .node rect,#mermaid-svg-W9HuglUe57n6b0ke .node circle,#mermaid-svg-W9HuglUe57n6b0ke .node ellipse,#mermaid-svg-W9HuglUe57n6b0ke .node polygon,#mermaid-svg-W9HuglUe57n6b0ke .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-W9HuglUe57n6b0ke .node .label{text-align:center;fill:#333}#mermaid-svg-W9HuglUe57n6b0ke .node.clickable{cursor:pointer}#mermaid-svg-W9HuglUe57n6b0ke .arrowheadPath{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-W9HuglUe57n6b0ke .flowchart-link{stroke:#333;fill:none}#mermaid-svg-W9HuglUe57n6b0ke .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-W9HuglUe57n6b0ke .edgeLabel rect{opacity:0.9}#mermaid-svg-W9HuglUe57n6b0ke .edgeLabel span{color:#333}#mermaid-svg-W9HuglUe57n6b0ke .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-W9HuglUe57n6b0ke .cluster text{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-W9HuglUe57n6b0ke .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-W9HuglUe57n6b0ke text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-W9HuglUe57n6b0ke .actor-line{stroke:grey}#mermaid-svg-W9HuglUe57n6b0ke .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-W9HuglUe57n6b0ke .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-W9HuglUe57n6b0ke #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-W9HuglUe57n6b0ke .sequenceNumber{fill:#fff}#mermaid-svg-W9HuglUe57n6b0ke #sequencenumber{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke #crosshead path{fill:#333;stroke:#333}#mermaid-svg-W9HuglUe57n6b0ke .messageText{fill:#333;stroke:#333}#mermaid-svg-W9HuglUe57n6b0ke .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-W9HuglUe57n6b0ke .labelText,#mermaid-svg-W9HuglUe57n6b0ke .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-W9HuglUe57n6b0ke .loopText,#mermaid-svg-W9HuglUe57n6b0ke .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-W9HuglUe57n6b0ke .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-W9HuglUe57n6b0ke .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-W9HuglUe57n6b0ke .noteText,#mermaid-svg-W9HuglUe57n6b0ke .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-W9HuglUe57n6b0ke .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-W9HuglUe57n6b0ke .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-W9HuglUe57n6b0ke .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-W9HuglUe57n6b0ke .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke .section{stroke:none;opacity:0.2}#mermaid-svg-W9HuglUe57n6b0ke .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-W9HuglUe57n6b0ke .section2{fill:#fff400}#mermaid-svg-W9HuglUe57n6b0ke .section1,#mermaid-svg-W9HuglUe57n6b0ke .section3{fill:#fff;opacity:0.2}#mermaid-svg-W9HuglUe57n6b0ke .sectionTitle0{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke .sectionTitle1{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke .sectionTitle2{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke .sectionTitle3{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-W9HuglUe57n6b0ke .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke .grid path{stroke-width:0}#mermaid-svg-W9HuglUe57n6b0ke .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-W9HuglUe57n6b0ke .task{stroke-width:2}#mermaid-svg-W9HuglUe57n6b0ke .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke .taskText:not([font-size]){font-size:11px}#mermaid-svg-W9HuglUe57n6b0ke .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-W9HuglUe57n6b0ke .task.clickable{cursor:pointer}#mermaid-svg-W9HuglUe57n6b0ke .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-W9HuglUe57n6b0ke .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-W9HuglUe57n6b0ke .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-W9HuglUe57n6b0ke .taskText0,#mermaid-svg-W9HuglUe57n6b0ke .taskText1,#mermaid-svg-W9HuglUe57n6b0ke .taskText2,#mermaid-svg-W9HuglUe57n6b0ke .taskText3{fill:#fff}#mermaid-svg-W9HuglUe57n6b0ke .task0,#mermaid-svg-W9HuglUe57n6b0ke .task1,#mermaid-svg-W9HuglUe57n6b0ke .task2,#mermaid-svg-W9HuglUe57n6b0ke .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-W9HuglUe57n6b0ke .taskTextOutside0,#mermaid-svg-W9HuglUe57n6b0ke .taskTextOutside2{fill:#000}#mermaid-svg-W9HuglUe57n6b0ke .taskTextOutside1,#mermaid-svg-W9HuglUe57n6b0ke .taskTextOutside3{fill:#000}#mermaid-svg-W9HuglUe57n6b0ke .active0,#mermaid-svg-W9HuglUe57n6b0ke .active1,#mermaid-svg-W9HuglUe57n6b0ke .active2,#mermaid-svg-W9HuglUe57n6b0ke .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-W9HuglUe57n6b0ke .activeText0,#mermaid-svg-W9HuglUe57n6b0ke .activeText1,#mermaid-svg-W9HuglUe57n6b0ke .activeText2,#mermaid-svg-W9HuglUe57n6b0ke .activeText3{fill:#000 !important}#mermaid-svg-W9HuglUe57n6b0ke .done0,#mermaid-svg-W9HuglUe57n6b0ke .done1,#mermaid-svg-W9HuglUe57n6b0ke .done2,#mermaid-svg-W9HuglUe57n6b0ke .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-W9HuglUe57n6b0ke .doneText0,#mermaid-svg-W9HuglUe57n6b0ke .doneText1,#mermaid-svg-W9HuglUe57n6b0ke .doneText2,#mermaid-svg-W9HuglUe57n6b0ke .doneText3{fill:#000 !important}#mermaid-svg-W9HuglUe57n6b0ke .crit0,#mermaid-svg-W9HuglUe57n6b0ke .crit1,#mermaid-svg-W9HuglUe57n6b0ke .crit2,#mermaid-svg-W9HuglUe57n6b0ke .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-W9HuglUe57n6b0ke .activeCrit0,#mermaid-svg-W9HuglUe57n6b0ke .activeCrit1,#mermaid-svg-W9HuglUe57n6b0ke .activeCrit2,#mermaid-svg-W9HuglUe57n6b0ke .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-W9HuglUe57n6b0ke .doneCrit0,#mermaid-svg-W9HuglUe57n6b0ke .doneCrit1,#mermaid-svg-W9HuglUe57n6b0ke .doneCrit2,#mermaid-svg-W9HuglUe57n6b0ke .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-W9HuglUe57n6b0ke .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-W9HuglUe57n6b0ke .milestoneText{font-style:italic}#mermaid-svg-W9HuglUe57n6b0ke .doneCritText0,#mermaid-svg-W9HuglUe57n6b0ke .doneCritText1,#mermaid-svg-W9HuglUe57n6b0ke .doneCritText2,#mermaid-svg-W9HuglUe57n6b0ke .doneCritText3{fill:#000 !important}#mermaid-svg-W9HuglUe57n6b0ke .activeCritText0,#mermaid-svg-W9HuglUe57n6b0ke .activeCritText1,#mermaid-svg-W9HuglUe57n6b0ke .activeCritText2,#mermaid-svg-W9HuglUe57n6b0ke .activeCritText3{fill:#000 !important}#mermaid-svg-W9HuglUe57n6b0ke .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-W9HuglUe57n6b0ke g.classGroup text .title{font-weight:bolder}#mermaid-svg-W9HuglUe57n6b0ke g.clickable{cursor:pointer}#mermaid-svg-W9HuglUe57n6b0ke g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-W9HuglUe57n6b0ke g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-W9HuglUe57n6b0ke .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-W9HuglUe57n6b0ke .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-W9HuglUe57n6b0ke .dashed-line{stroke-dasharray:3}#mermaid-svg-W9HuglUe57n6b0ke #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke .commit-id,#mermaid-svg-W9HuglUe57n6b0ke .commit-msg,#mermaid-svg-W9HuglUe57n6b0ke .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-W9HuglUe57n6b0ke g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-W9HuglUe57n6b0ke g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-W9HuglUe57n6b0ke g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-W9HuglUe57n6b0ke .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-W9HuglUe57n6b0ke .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-W9HuglUe57n6b0ke .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-W9HuglUe57n6b0ke .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-W9HuglUe57n6b0ke .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-W9HuglUe57n6b0ke .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-W9HuglUe57n6b0ke .edgeLabel text{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-W9HuglUe57n6b0ke .node circle.state-start{fill:black;stroke:black}#mermaid-svg-W9HuglUe57n6b0ke .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-W9HuglUe57n6b0ke #statediagram-barbEnd{fill:#9370db}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-state .divider{stroke:#9370db}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-W9HuglUe57n6b0ke .note-edge{stroke-dasharray:5}#mermaid-svg-W9HuglUe57n6b0ke .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-W9HuglUe57n6b0ke .error-icon{fill:#522}#mermaid-svg-W9HuglUe57n6b0ke .error-text{fill:#522;stroke:#522}#mermaid-svg-W9HuglUe57n6b0ke .edge-thickness-normal{stroke-width:2px}#mermaid-svg-W9HuglUe57n6b0ke .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-W9HuglUe57n6b0ke .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-W9HuglUe57n6b0ke .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-W9HuglUe57n6b0ke .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-W9HuglUe57n6b0ke .marker{fill:#333}#mermaid-svg-W9HuglUe57n6b0ke .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-W9HuglUe57n6b0ke {color: rgba(0, 0, 0, 0.75);font: ;}

YUV
YUV444
YUV422
YUV420
YUV411
yuv444 Planar
yuv444 Semi-Planar
yuv444 Packed
yuv422 Planar
yuv422 Semi-Planar
yuv422 Packed
yuv420 Planar
yuv420 Semi-Planar
yuv420 Packed
yuv411 Planar
yuv411 Semi-Planar
yuv411 Packed
I444
NV24
NV42
AYUV
I422
NV16
NV61
YUYV
UYVY
I420
YV12
I010
NV12
NV21
P010
yuv410p
NV11
Y41P

YUV 与 RGB 相互转换

一般来讲,我们把YUV、Y‘UV、YCbCr, YPbPr包含在YUV颜色模型的范围内,其中Y都表示亮度,UV表示两个色度分量,但是具体的颜色模型的用途又各不相同,当然,他们与RGB的互转公式也就不相同。在电视系统发展的早期,YUV和Y’UV都是颜色信息的模拟信号编码形式,虽然Y和Y’都表示亮度,但是两种亮度的意义却天差地别,Y用来代指luminance,表示的是自然颜色的亮度,而Y‘代指luma,表示的是经过伽马压缩之后电信号的强度。在现在的计算机系统中,YUV一般用来代指YCbCr,用来表示文件的编码格式,用于数字视频的编码,而YPbPr颜色模型常常用在模拟分量视频中。所以YUV颜色模型到RGB颜色模型的转换,应该对应两种方式,分别是模拟YUV->模拟RGB、数字YUV->数字RGB。不过因为标清、高清、以及超清幅面,YUV转RGB的权重值各不相同,需要将模拟信号和数字信号再做一次幅面划分,就出现了6种转换公式。

Y、Cr、Cb信号的限制信号的限制
Y、Cr、Cb信号形式的数字编码可以表示比那些由R,、G、B信号相应范围支持的范围更大的信号值范围。正因为这样,作为电子图像生成或信号处理的结果,产生Y、CR、CB信号是可能的,尽管只是个别有效,但当转变为R、G、B时,将导致值超出范围。通过应用Y、CR、CB信号的限制,它将比在这些信号成为R、G、B形式之前一直等待来防止值超出范围更加方便和有效。限制还能在保持亮度和色调值的方法中应用,通过仅仅牺牲饱和度,来最大限度地降低主观缺陷。

计算公式推导

Kr + Kb +Kg = 1

以下参数由 ITU-R Recommendation BT.xxx 可得
BT.601:

Kr = 0.299
Kg = 0.587
Kb = 0.114

BT.709:

Kr = 0.2126
Kg = 0.7152
Kb = 0.0722

BT.2020:

Kr = 0.2627
Kg = 0.678
Kb = 0.0593

1. 模拟 RGB转YUV的推导公式

Kr + Kb +Kg = 1
Umax = Vmax = 0.5

Y = Kr * R + Kg * G + Kb * B
Pb = Umax * (B - Y) / (1 - Kb)
Pr = Vmax * (R - Y) / (1 - Kr)

2. 数字 RGB to YUV

Kr + Kb +Kg = 1
Umax = Vmax = 0.5

Y = 16 + 219 * (Kr * R + Kg * G + Kb * B) / 255
Cb = 128 + 224 * (Umax * (B - Y) / (1 - Kb)) / 255
Cr = 128 + 224 * (Vmax * (R - Y) / (1 - Kr)) / 255

1. 模拟YUV→模拟RGB

公式直接跳到下一节,以BT.601 为例,计算过程:

  1. 代入数值
    Y = 0.299 * R + 0.587 * G + 0.114 * B
    Pb = 0.5 * (B - Y) / (1 - 0.114)
    Pr = 0.5 * (R - Y) / (1 - 0.299)

  2. 化简
    Pb = 0.5 * (B - (0.299 * R + 0.587 * G + 0.114 * B)) / (1 - 0.114)
    = 0.5 * (B - (0.299 * R + 0.587 * G + 0.114 * B)) / 0.886
    = 0.5 * (B - 0.299 * R - 0.587 * G - 0.114 * B) / 0.886
    = 0.5 * (0.299 * R - 0.587 * G + 0.886 * B) / 0.886
    = (0.1495 * R - 0.2935 * G + 0.443 * B) / 0.886
    ≈\approx≈ 0.168 * R - 0.331 * G + 0.5 * B
    Pr = 0.5 * (R - (0.299 * R + 0.587 * G + 0.114 * B)) / (1 - 0.299)
    = 0.5 * (R - 0.299 * R - 0.587 * G - 0.114 * B) / 0.701
    = 0.5 * (0.701 * R - 0.587 * G - 0.114 * B) / 0.701
    = (0.3505 * R - 0.2935 * G - 0.057 * B) / 0.701
    ≈\approx≈ 0.5 * R - 0.419 * G - 0.081 * B

  1. BT.601(标清国际定义)
# RGB to YUV
Y = 0.299 * R + 0.587 * G + 0.114 * B   
Pb =-0.169 * R - 0.331 * G + 0.500 * B
Pr = 0.500 * R - 0.439 * G - 0.081 * B# YUV to RGB
R = Y + 1.402* Pr             
G = Y - 0.344 * Pb - 0.792* Pr        
B = Y + 1.772 * Pb
  1. BT.709(高清)
RGB to YUV
Y = 0.213 * R + 0.715 * G + 0.072 * B     
Pb =-0.115 * R - 0.385 * G + 0.500 * B
Pr = 0.500 * R - 0.454 * G - 0.046 * B# YUV to RGB
R = Y + 1.402* Cr            
G = Y - 0.344 * Cb - 0.792* Cr       
B = Y + 1.772 * Cb
  1. BT.2020(超高清)
# RGB to YUV
Y = 0.2627 * R + 0.678 * G + 0.0593 * B
Pb = -0.1396 * R - 0.3604 * G + 0.5 * B
Pr = 0.5 * R - 0.4598 * G - 0.0402 * B

2. 数字YUV→数字RGB

  1. BT.601
# RGB2YUV
Y = 16 + 0.257 * R + 0.504 * G+ 0.098 * B
Cb = 128 - 0.148 * R - 0.291 * G+ 0.439 * B
Cr = 128 + 0.439 * R - 0.368 * G - 0.071 * B# YUV2RGB
R = 1.164 *(Y - 16) + 1.596 *(Cr - 128)
G = 1.164 *(Y - 16) - 0.392 *(Cb - 128) - 0.812 *(Cr - 128)
B = 1.164 *(Y - 16) + 2.016 *(Cb - 128)
  1. BT.709
# RGB2YUV
Y = 16 + 0.183 * R + 0.614 * G + 0.062 * B
Cb = 128 - 0.101 * R - 0.339 * G+ 0.439 * B
Cr = 128 + 0.439 * R - 0.399 * G- 0.040 * B#YUV2RGB
R = 1.164 *(Y - 16) + 1.792 *(Cr - 128)
G = 1.164 *(Y - 16) - 0.213 *(Cb - 128) - 0.534 *(Cr - 128)
B = 1.164 *(Y - 16) + 2.114 *(Cb - 128)
  1. BT.2020
    Y = 16 + 219 * (0.2627 * R + 0.678 * G + 0.0593 * B) / 255
    ≈\approx≈ 16 + 0.226 * R + 0.582 * G + 0.051 * B

Cb = 128 + 224 * (0.5 * (B - Y) / 0.9407) / 255
Cr = 128 + 224 * (0.5 * (R - Y) / 0.7373) / 255
//TODO 有空再断续推导

YUV与RGB的相互转换会损失图象质量

不管是YUV转RGB还是RGB转YUV都会有图像质量的损失。
对于不同位深或不同采样率的转换质量损失都好理解,但对于相同位深相同采样率的转换图像质量损失就要从计算公式来理解了,如I444和RGB24都是8bit位深未经压缩处理全采样数据,无论是RGB转YUV,还是YUV转RGB都会有少量的图像质量的损失,从转换公式来看这个由于浮点计算带来的损失,可以说是微乎其微的肉眼基本上看不出来的损失。

用ffmpeg来做一验证,将yuvj444p转换成rgb24再转回yuvj444p,对比两个yuvj444p文件的差异

# 1. 用ffmpeg testsrc 生成一个完全取样的的YUV文件 yuvj444p
ffmpeg  -f lavfi -i testsrc -frames 10 -pix_fmt yuvj444p -s 320x320 yuvj444p_320x320.yuv# 2. 将生成的yuvj444p转换成rgb24
ffmpeg -pix_fmt yuvj444p -s 320x320 -i yuvj444p_320x320.yuv -pix_fmt rgb24 yuv2rgb_320x320.rgb# 3. 再将rgb24转成yuvj444p
ffmpeg -s 320x320 -pix_fmt rgb24 -i yuv2rgb_320x320.rgb -pix_fmt yuvj444p -s 320x320 rgb2yuvj444p_320x320.yuv

使用yuvj444p_320x320.yuv和rgb2yuvj444p_320x320.yuv这两个YUV对比,这两者应该是有差异的

播放YUV

ffplay -pix_fmt yuvj444p -s 320x320 rgb2yuvj444p_320x320.yuv
ffplay -pix_fmt yuvj444p -s 320x320 yuvj444p_320x320.yuv

如下图两个文件,肉眼看不出有差别

但再对比文件差异时,如下图,可以看到红色高亮的少数的16进制数有差异,如第一个差异的数字原始的文件中是98,经过yuv2rgb再rgb2yuv后,变成了96

计算

由于YUV格式是未经压缩并且只存储了Y/U/V三个通道的数据,播放或编码必须要知道分辨率和YUV具体的格式(如nv12/i420/yuvj420ple), 因此在YUV文件命名时建议名字包含YUV格式名称和分辨率信息
这里计算文件大小或者计算帧数中的采样率和位深可由YUV格式得到

YUV计算文件大小

已知YUV采样率、分辨率、和帧数
文件大小=宽 * 高 * 采样率 * 向上取整(位深/8) * 帧数

file size(byte) = width * height * rate * Ceil(bitdepth/8) * frames

以最常用的nv12/i420等8bit位深的420为例

文件大小 = 宽 * 高 * 1.5 * 帧数

YUV计算帧数

YUV帧数的计算和文件大小的计算类似
要求已知文件大小、采样率、分辨率
YUV帧数=文件大小/(宽 * 高 * 采样率 * 向上取整(位深/8))

YUV frames = file size(byte) / (width * height * rate * Ceil(bitdepth/8))

sample map

sample rate
4:4:4 3
4:2:2 2
4:2:0 1.5
4:1:1 1.5

大小端序(字节序)

当位深超过8bit时存在大小端模式的情况

big-edian(大端序): 低地址存放高位
little-endian(小端序): 低地址存放低位
格式名称以le为小端序,格式名称以be为小端序
相同名称只是后缀不一样的两种格式YUV排列是完全一样的, 如,yuv420p10le与yuv420p10be

一些常用格式

YUV格式关系

YUV格式名称比较多在不同的地方不同的名称有可能代表的是同一种格式,如在ffmpeg中的yuyv422与gstreamer 中的yuy2,以及其它不它的格式名称YUY2/YUYV/YUNV, 都是代表同一种YUV格式

ffmpeg pix_fmt gstreamer format Duplicate formats number of components Bits per pixel remark
yuvj420p i420 IYUV/YU12 3 12 full range
yuv420p - 3 12 limited range , 排列方式与yuvj420p完全一致,只是像素颜色范围是[16,235], 16表示黑色,235表示白色; UV范围[16,240]
nv12 nv12 3 12 -
nv21 nv21 3 12 -
yuyv422 yuy2 YUY2/YUYV/YUNV 3 16 YUYV 4:2:2
uyvy422 uyvy UYVY/IUYV/HDYC/ UYNV/Y422 3 16 UYVY 4:2:2
yuv420p10le i420-10le 3 15 10 bit yuv
p010le p010-10le 3 15 10 bit yuv
yv12 - 3 12 YV12 (3-planar) ——These formats are identical to YU12 except that the U and V plane order is reversed.

常见的YUV格式存储排列方式

Define:
s = width * height
n = width * height // 4
m = width * height // 2

  1. I420/IYUV/YU12: yuv420 planar 的一种, 排列方式: y1y2y3…ysu1u2u3…unv1v2v3…vn
  2. nv12: 8bit YUV420 Semi-Planar的一种格式, 排列方式: y1y2y3…ysu1v1u2v2u3v3…unvn
  3. nv21: 8bit YUV420 Semi-Planar的一种格式, 排列方式: y1y2y3…ysv1u1v2u2…vnun
  4. i420-10le: 10bit YUV420 Planar的一种格式, 排列方式与i420一样, 只是每个值都用10bit低字节序来存储
  5. p010-10le: 10bit YUV420 Semi-Planar的一种格式, 排列方式与nv12一样, 只是每个值都用高10bit低字节序来存储
  6. YUY2/YUYV/YUNV: 8bit YUV 4:2:2格式, 排列方式: y1u1y2v1 y3u2y4v2 y5u3y6v3…yn-1umynvm
  7. UYVY/IUYV/HDYC/UYNV/Y422: 8bit YUV 4:2:2格式, 排列方式: u1y1v1Y2 u2y3v2y4 u3y5v3y6…umyn-1vmyn
  8. yv12: YUV420 Planar的一种,UV的顺序与i420相反, 排列方式: y1y2y3y…ynv1v2v3…vnu1u2u3…un
  9. YUV422P/I422: y1y2y3…ysu1u2u3…umv1v2v3…vm
  10. nv16: yuv422 Semi-Planar的一种: y1y2y3…ys u1v1u2v2u3v3…umvm
  11. nv61: 与nv16类似,只是u/v的位置互换(V前U后)
  12. yv16: yuv422 Planar的一种: y1y2y3…ysu1u2u3…umv1v2v3…vm
  13. yuvj444p: Planar的一种: y1y2y3y…ys u1u2u3…us v1v2v3…vs

其它4:1:1采样的格式一般不太常见

  1. Y41P: 是一种4:1:1packed格式,其中U和V每四个像素水平采样一次。每个宏像素在三个字节中包含8个像素,并具有以下字节布局:U0 Y0 V0 Y1 U4 Y2 V4 Y3 Y4 Y5 Y6 Y7
  2. Y41T与Y41P相同,除了每个Y样本的最低有效位指定色度键(0 =透明,1 =不透明)。
  3. AI44是一种已标准化的YUV格式,每个样本8位。每个样本在4个最高有效位(MSB)中包含一个索引,在4个最低有效位(LSB)中包含一个alpha值。索引引用YUV调色板条目的数组,必须在该格式的媒体类型中定义。此格式主要用于子图片图像。

参考:
[1]: https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering
[2]:https://www.fourcc.org/yuv.php
[3]: https://baike.baidu.com/item/YUV/3430784?fr=aladdin
[4]: https://www.itu.int/rec/R-REC-BT.601
[5]: https://www.itu.int/rec/R-REC-BT.709
[6]: https://www.itu.int/rec/R-REC-BT.2020

YUV格式详解【全】相关推荐

  1. YUV 格式详解-史上最全

    YUV 格式详解 介绍 分类标准 具体分类 I420(属于 YUV 420 Plannar) YV12(属于 YUV 420 Plannar) NV12(属于 YUV 420 Semi-Planar) ...

  2. 视频与图像RGB/YUV格式详解

    计算机彩色显示器显示色彩的原理与彩色电视机一样,都是采用R(Red).G(Green).B(Blue)相加混色的原理:通过发射出三种不同强度的电子束,使屏幕内侧覆盖的红.绿.蓝磷光材料发光而产生色彩. ...

  3. RGB与YUV格式详解

    一.RGB RGB是最常见的一种颜色编码格式,它的三个通道 R.G.B分别对应红.绿.蓝三个分量.通常每个分量的位宽为8bit,值的范围是0~255,对应其256个灰阶,也即颜色的亮度,值越大表示该分 ...

  4. YUV格式详解【转】

    http://blog.csdn.net/SearchSun/article/details/2443867 http://wmnmtm.blog.163.com/blog/static/382457 ...

  5. 4-4:TCP协议之TCP头部格式详解

    文章目录 一:TCP头部格式详解 (1)4位首部长度 (2)序列号和确认应答号 A:可靠性问题 B:32位序号和确认号 (3)窗口大小 (4)标志位 (5)紧急指针 A:带外数据(out_of _ba ...

  6. 安卓camera2 API获取YUV420_888格式详解

    安卓音视频开发中的一个环节是摄像头采集数据,Android平台上摄像头采集的API有两套,camera1和camera2.本文主要讲的是camera2这套API采集数据,并指明YUV420_888格式 ...

  7. Ffmpeg快速命令使用 Ffmpeg选项详解 Ffmepg格式详解 常见视频文件格式详解

    http://www.ffmpeg.com.cn/index.php/%E9%A6%96%E9%A1%B5 Ffmpeg快速命令使用 From Ffmpeg工程组 Jump to: navigatio ...

  8. UICC 之 USIM 详解全系列——UICC协议层结构

    本人就职于国际知名终端厂商,负责modem芯片研发. 在5G早期负责终端数据业务层.核心网相关的开发工作,目前牵头6G算力网络技术标准研究. UICC 之 USIM 详解全系列--UICC协议层结构 ...

  9. ffmpeg-jpeg图片格式详解

    jpg/jpeg是24位的图像文件格式,也是一种高效率的压缩格式 JPEG格式可以分为 1.标准JPEG:只有图片完全被加载和读取完毕之后,才能看到图片的全貌 2.渐进式JPEG:(标准的改进)首先呈 ...

  10. 【图像处理】jpeg图片格式详解

    jpeg图片格式详解 1. JPEG文件简介 JPEG的全称是JointPhotographicExpertsGroup(联合图像专家小组),它是一种常用的图像存储格式, jpg/jpeg是24位的图 ...

最新文章

  1. 一杯茶的功夫,掌握Git常用命令(转载)
  2. QT多线程run函数不能使用信号与槽
  3. 问题 “cell 出栈 selectBox 已选的图标,被释放掉,再次进入屏幕时,没有了已选图标 ” 解决方案...
  4. Linux 阻塞和非阻塞IO 实验
  5. Linux网络编程(Socket)
  6. Python 框架 之 Scrapy 爬虫(二)
  7. mysql表文件创建_php文件创建mysql的表
  8. nginx linux 部署web项目名,Linux部署web项目配置Nginx
  9. Windows下 Anaconda + VScode Python 环境搭建 多图 非常详细
  10. SegNet算法详解
  11. pioneer dvr-xd50 固件_闲的蛋疼的验证:索尼 SONY WH1000XM3固件版本差异
  12. 计算机专业毕业顶岗实习周记,计算机专业毕业顶岗实习周记10篇参考).doc
  13. 568A和568B的线序
  14. 期货连续合约跳空处理
  15. Go 环境变量、go env
  16. Oracle19c 出现 ora-12514
  17. 2015阿里数据分析师校招面试经历
  18. OLED QLED LED等发光器件, IVL测试软件
  19. 习题2.4 编写程序,从键盘输入两个整数分别给变量x,y,如果x大于y,则输出x及x-y的值;否则,输出y及y-x的值
  20. 二进制与十进制互相转换的计算方法(个人向)

热门文章

  1. 【数据库】mysql日期格式转换
  2. python在虚拟解释器环境中使用pip安装第三方库出现Requirement already satisfied错误
  3. 企业如何利用OA系统轻松管理员工请休假
  4. jsp企业员工请假管理系统
  5. Java入门基础知识点总结(详细篇)
  6. 电工专业技能计算机操作,电工操作技能考核的方案.doc
  7. Bean的生命周期详解
  8. html页面网页打开乱码怎么解决方法,网页乱码怎么解决?
  9. 2022年电子考研经验分享,本科双非,一志愿南航,调剂国科大上岸
  10. ASC加密解密(笔记)