YUV/RGB色彩空间的相互转换在算法上是很简单的,都是线性变换。但是对相关领域不熟悉的同学在第一次着手做时,往往会非常迷惑,因为网上的资料往往带着各种相似却不相同的术语,比如YUV,YCbCr,Y′CbCr,BT601/709/2020,full-range,studio-swing等等,不同术语描述的转换公式和常数又都不一样,给选择带来极大困扰。本文的目的就是尽可能简单明了地说清楚这些术语表示的意义,让我们能够正确选择转换用的公式,甚至可以根据需求自行推导。
着急的或者图方便的同学可以直接拉到本文最下面去查公式
YUV相关的术语。
YUV是一大类色彩空间的统称。由没有经过伽马矫正的RGB信号转化来的YUV色彩空间,模拟信号的称作YCC,数字信号的称作YCbCr;由经过了伽马矫正的RGB信号(记作R′G′B′)转化来的YUV色彩空间,模拟信号的称作Y′PbPr,数字信号的称作Y′CbCr。同时,作为模拟信号的RGB和R′G′B′对应的数字信号记作RdGdBd和R′dG′dB′d:
| YUV | ||
|---|---|---|
| 无伽马矫正 | 有伽马矫正 | |
| 模拟信号 | YCC | Y′PbPr |
| 数字信号 | YCbCr | Y′CbCr |
| RGB | ||
|---|---|---|
| 无伽马矫正 | 有伽马矫正 | |
| 模拟信号 | RGB | R′G′B′ |
| 数字信号 | RdGdBd | R′dG′dB′d |
而在计算机程序中所进行的YUV/RGB转换,大部分情况都是指Y′CbCr和R′dG′dB′d间的转换。在Y′CbCr的三个分量中,Y′被称作luma,即进行过伽马校正过的亮度值。另外的两个分量Cb表示blue-difference,即亮度与蓝色间的差别;Cr表示red-difference,即亮度与红色间的差别。Cb和Cr统称为chroma,即色度。
Y′CbCr和R′dG′dB′d间的转换,是由Y′PbPr和R′G′B′间的转换推导而来的。大体思路是R′dG′dB′d<=>R′G′B′<=>Y′PbPr<=>Y′CbCr。接下来从左到右分步介绍。
R′dG′dB′d<=>R′G′B′
首先是数字信号的RGB和模拟信号间的相互转换,模拟信号RGB三个分量范围是[0,1],数字信号是[0,255],相互之间的转换就是线性拉伸,因此:
l e t f = 1 255 [ R ′ G ′ B ′ ] = [ R D ′ G D ′ B D ′ ] ⋅ f [ R D ′ G D ′ B D ′ ] = [ R ′ G ′ B ′ ] ⋅ 1 f \mathit{let}~ f = \frac{1}{255} \\ \begin{bmatrix} R'\\ G'\\ B' \end{bmatrix}= \begin{bmatrix} R'_{D}\\ G'_{D}\\ B'_{D} \end{bmatrix} \cdot f \\ \begin{bmatrix} R'_{D}\\ G'_{D}\\ B'_{D} \end{bmatrix}= \begin{bmatrix} R'\\ G'\\ B' \end{bmatrix} \cdot \frac{1}{f} let f=2551⎣⎡R′G′B′⎦⎤=⎣⎡RD′GD′BD′⎦⎤⋅f⎣⎡RD′GD′BD′⎦⎤=⎣⎡R′G′B′⎦⎤⋅f1
R′G′B′<=>Y′PbPr
国际标准ITU-R定义了其所推荐的模拟信号Y′PbPr色彩空间,以及它和模拟信号的R′G′B′色彩空间的相互转换。随着技术进步,ITU-R标准推出了BT.601,BT.709,BT.2020等版本,其中BT.601用于SDTV,BT.709用于HDTV,BT.2020用于UHDTV。
各版本的转换公式都是相同的,即向量(R′, G′, B′)乘以一个3x3的转换矩阵M(后文简称M)便得出(Y′, Pb, Pr),而一个(Y′, Pb, Pr)向量乘以M的逆矩阵则得到对应的(R′, G′, B′)向量。R′G′B′三个分量的范围都是[0, 1],乘以M后得到的luma的范围是[0, 1],chroma的范围则是[-0.5, +0.5]:
[ Y ′ P B P R ] = M ⋅ [ R ′ G ′ B ′ ] [ R ′ G ′ B ′ ] = M − 1 ⋅ [ Y ′ P B P R ] \begin{bmatrix} Y'\\ P_{B}\\ P_{R} \end{bmatrix} =M\cdot \begin{bmatrix} R'\\ G'\\ B' \end{bmatrix} \\ \begin{bmatrix} R'\\ G'\\ B' \end{bmatrix} =M^{-1}\cdot \begin{bmatrix} Y'\\ P_{B}\\ P_{R} \end{bmatrix} ⎣⎡Y′PBPR⎦⎤=M⋅⎣⎡R′G′B′⎦⎤⎣⎡R′G′B′⎦⎤=M−1⋅⎣⎡Y′PBPR⎦⎤
对于矩阵M,ITU-R标准定义了Kr,Kg,Kb三个量,由这三个量就可以推导出M和它的逆矩阵:
M = [ K R K G K B − 1 2 ⋅ K R 1 − K B − 1 2 ⋅ K G 1 − K B 1 2 1 2 − 1 2 ⋅ K G 1 − K R − 1 2 ⋅ K B 1 − K R ] M − 1 = [ 1 0 2 − 2 ⋅ K R 1 − K B K G ⋅ ( 2 − 2 ⋅ K B ) − K R K G ⋅ ( 2 − 2 ⋅ K R ) 1 2 − 2 ⋅ K B 0 ] M= \begin{bmatrix} K_{R} & K_{G} & K_{B}\\ -\frac{1}{2}\cdot \frac{K_{R}}{1-K_{B}} & -\frac{1}{2}\cdot \frac{K_{G}}{1-K_{B}} & \frac{1}{2}\\ \frac{1}{2} & -\frac{1}{2}\cdot \frac{K_{G}}{1-K_{R}} & -\frac{1}{2}\cdot \frac{K_{B}}{1-K_{R}} \end{bmatrix} \\ M^{-1}= \begin{bmatrix} 1 & 0 & 2-2\cdot K_{R}\\ 1 & -\frac{K_{B}}{K_{G}}\cdot \left ( 2-2\cdot K_{B} \right ) & -\frac{K_{R}}{K_{G}}\cdot \left ( 2-2\cdot K_{R} \right )\\ 1 & 2-2\cdot K_{B} & 0 \end{bmatrix} M=⎣⎡KR−21⋅1−KBKR21KG−21⋅1−KBKG−21⋅1−KRKGKB21−21⋅1−KRKB⎦⎤M−1=⎣⎡1110−KGKB⋅(2−2⋅KB)2−2⋅KB2−2⋅KR−KGKR⋅(2−2⋅KR)0⎦⎤
同时由于Kr + Kg + Kb = 1必须恒成立,因此只要定义其中两个值即可:
| Kr | Kb | |
| BT.601 | 0.299 | 0.114 |
| BT.709 | 0.2126 | 0.0722 |
| BT.2020 | 0.2627 | 0.0593 |
Y′PbPr<=>Y′CbCr
ITU-R标准同样定义了Y′CbCr,同时其他需要使用数字YUV信号的标准也可自行定义,一般都需要将Y′PbPr进行拉伸和移位,使得新的三个分量落在对应位深度所表示的取值范围(对8bit位深度,取值范围即[0, 255])内的某一部分中。由此引出了range(也叫swing,后文统一称为range)的概念。
ITU-R标准定义了8bit位深度的Y′CbCr:Y′PbPr首先要笛卡尔乘scale向量(219, 224, 224),然后加上offset向量(16, 128, 128)。求出的Y′CbCr中luma范围是[16, 235],chroma的范围是[16, 240]。这样的range由于没有占满[0, 255]的取值范围,被称为narrow range(也叫mpeg range,video range,studio range等等,后文统一为narrow range);而对于需要占满整个位深度取值范围的Y′CbCr,Y′PbPr首先要笛卡尔乘scale向量(255, 255, 255),然后加上offset向量(0, 128, 128)。这样一来Y′CbCr三个分量取值范围都落在了[0, 255],该range被成为full range。
从Y′CbCr转换为Y′PbPr的过程是上述过程的反转,即先减去offset向量,再笛卡尔除scale向量。
l e t S c a l e = { [ 219 224 224 ] T o n n a r r o w r a n g e [ 255 255 255 ] T o n f u l l r a n g e l e t O f f s e t = { [ 16 128 128 ] T o n n a r r o w r a n g e [ 0 128 128 ] T o n f u l l r a n g e [ Y ′ C B C R ] = [ Y ′ P B P R ] × S c a l e + O f f s e t [ Y ′ P B P R ] = ( [ Y ′ C B C R ] − O f f s e t ) × S c a l e − 1 \mathit{let}~\mathit{Scale}= \left\{\begin{matrix} \begin{bmatrix} 219 & 224 & 224 \end{bmatrix}^{T} & \mathit{on~narrow~range}\\ \begin{bmatrix} 255 & 255 & 255 \end{bmatrix}^{T} & \mathit{on~full~range} \end{matrix}\right. \\ \mathit{let}~\mathit{Offset}= \left\{\begin{matrix} \begin{bmatrix} 16 & 128 & 128 \end{bmatrix}^{T} & \mathit{on~narrow~range}\\ \begin{bmatrix} 0 & 128 & 128 \end{bmatrix}^{T} & \mathit{on~full~range} \end{matrix}\right. \\ \begin{bmatrix} Y'\\ C_{B}\\ C_{R} \end{bmatrix}= \begin{bmatrix} Y'\\ P_{B}\\ P_{R} \end{bmatrix} \times \mathit{Scale} + \mathit{Offset} \\ \begin{bmatrix} Y'\\ P_{B}\\ P_{R} \end{bmatrix}= \left ( \begin{bmatrix} Y'\\ C_{B}\\ C_{R} \end{bmatrix}- \mathit{Offset} \right ) \times \mathit{Scale}^{-1} let Scale={ [219224224]T[255255255]Ton narrow rangeon full rangelet Offset={ [16128128]T[0128128]Ton narrow rangeon full range⎣⎡Y′CBCR⎦⎤=⎣⎡Y′PBPR⎦⎤×Scale+Offset⎣⎡Y′PBPR⎦⎤=⎝⎛⎣⎡Y′CBCR⎦⎤−Offset⎠⎞×Scale−1
相互转换最后需要进行四舍五入和边界剪裁(round and clamp),因此不可避免地会造成一定程度上的精度损失。也有人为此对转换矩阵进行了微调,但无法彻底避免。
总体流程
综合上面三个步骤,可得到R′dG′dB′d<=>Y′CbCr的总体流程:
l e t f = 1 255 l e t S c a l e = { [ 219 224 224 ] T o n n a r r o w r a n g e [ 255 255 255 ] T o n f u l l r a n g e l e t O f f s e t = { [ 16 128 128 ] T o n n a r r o w r a n g e [ 0 128 128 ] T o n f u l l r a n g e [ Y ′ C B C R ] = O f f s e t + M ⋅ f ⋅ [ R D ′ G D ′ B D ′ ] × S c a l e [ R D ′ G D ′ B D ′ ] = 1 f ⋅ M − 1 ⋅ ( [ Y ′ C B C R ] − O f f s e t ) × S c a l e − 1 \mathit{let}~ f = \frac{1}{255} \\ \mathit{let}~\mathit{Scale}= \left\{\begin{matrix} \begin{bmatrix} 219 & 224 & 224 \end{bmatrix}^{T} & \mathit{on~narrow~range}\\ \begin{bmatrix} 255 & 255 & 255 \end{bmatrix}^{T} & \mathit{on~full~range} \end{matrix}\right. \\ \mathit{let}~\mathit{Offset}= \left\{\begin{matrix} \begin{bmatrix} 16 & 128 & 128 \end{bmatrix}^{T} & \mathit{on~narrow~range}\\ \begin{bmatrix} 0 & 128 & 128 \end{bmatrix}^{T} & \mathit{on~full~range} \end{matrix}\right. \\ \begin{bmatrix} Y'\\ C_{B}\\ C_{R} \end{bmatrix}= \mathit{Offset} + M \cdot f \cdot \begin{bmatrix} R'_{D}\\ G'_{D}\\ B'_{D} \end{bmatrix} \times \mathit{Scale} \\ \begin{bmatrix} R'_{D}\\ G'_{D}\\ B'_{D} \end{bmatrix}= \frac{1}{f} \cdot M^{-1} \cdot \left ( \begin{bmatrix} Y'\\ C_{B}\\ C_{R} \end{bmatrix}- \mathit{Offset} \right ) \times \mathit{Scale}^{-1} let f=2551let Scale={ [219224224]T[255255255]Ton narrow rangeon full rangelet Offset={ [16128128]T[0128128]Ton narrow rangeon full range

最低0.47元/天 解锁文章
8002





