YUV与RGB互转各种公式

news/2025/1/1 10:18:45/

原创不易 转载请注明出处和作者

转载地址:https://www.cnblogs.com/luoyinjie/p/7219319.html

关于写这篇文章的原因:

  本人也是摸索了很长时间才弄懂其中的原理,里面涉及的知识点太多了, 比如色彩空间, Gamma, 什么的, 里面还会涉及到很多的协议, 比如 BT601  BT709, BT2020,RP177 等, 一不小心就会写错, 然后色彩可能就不准确了, 可能偏白 偏黑或者偏色

自己也踩过很多坑, 然后把这些经验写出来, 防止大家踩重复的坑, 如果文章有不够严谨的地方, 请及时指出。

 

YUV与RGB互转的公式有很多, 不同的色彩空间的转换公式是不一样的, 不同色彩空间的转换公式可以看我写的这篇文章: https://www.jianshu.com/p/db1caf7f2920

  除了色彩空间, 还需要注意YUV的范围, YUV 有很多种表现形式, 比如:

  YUV : YUV是一种模拟型号, Y∈ [0,1]   U,V∈[-0.5,0.5] 

  YCbCr :也叫YCC,  YCbCr 是数字信号, 它包含两种形式, 分别为TV range 和 full range, TV range 主要是广播电视采用的标准, full range 主要是pc 端采用的标准, 所以full range 有时也叫 pc range

      TV range 的各个分量的范围为: YUV  Y~[16,235]   Cb~[16-240]   Cr~[16-240] 

      full range 的各个分量的范围均为: 0-255   

  我们平时接触到的绝大多数都是 YCbCr (tv range) , ffmpeg 解码出来的数据绝大多数也是这个, 虽然ffmpeg 里面将它的格式描述成YUV420P , 实际上它是YCbCr tv range

  YUV转tv range:   Y' = 219.0*Y + 16 ;  Cb = U * 224.0 + 128;  Cr = V * 224.0 + 128;   

 

 

关于为什么要将YUV量化为tv range 16-235 ? 

  以下是维基百科摘抄的一段, 意思是tv range是为了解决滤波(模数转换)后的过冲现象,

  Y′ values are conventionally shifted and scaled to the range [16, 235] (referred to as studio swing or "TV levels") rather than using the full range of [0, 255] (referred to as full swing or "PC levels"). This practice was standardized in SMPTE-125M in order to accommodate signal overshoots ("ringing") due to filtering. The value 235 accommodates a maximal black-to-white overshoot of 255 − 235 = 20, or 20 / (235 − 16) = 9.1%, which is slightly larger than the theoretical maximal overshoot (Gibbs phenomenon) of about 8.9% of the maximal step. The toe-room is smaller, allowing only 16 / 219 = 7.3% overshoot, which is less than the theoretical maximal overshoot of 8.9%. This is why 16 is added to Y′ and why the Y′ coefficients in the basic transform sum to 220 instead of 255.[9] U and V values, which may be positive or negative, are summed with 128 to make them always positive, giving a studio range of 16–240 for U and V. (These ranges are important in video editing and production, since using the wrong range will result either in an image with "clipped" blacks and whites, or a low-contrast image.)

 

关于如何判断像素格式是否为tv range  (16-235)?

  在完全黑画面的时候打印出图像的Y数据, 如果Y=16左右    说明YCbCr 为tv range ,如果Y=0左右   说明YCbCr为 full range

 

 

以下是我推导的 BT601 与 BT2020 的公式, 包括各种形式, 比如 浮点 整形  等等。

一、 公式:基于BT.601-6 (NTSC 色域)

 

  BT601 UV(CbCr)的坐标图(量化后): (横坐标为u,纵坐标为v,左下角为原点)

 

        通过坐标图我们可以看到UV(YUV六面体投影到UV坐标系)是一个旋转了一定角度的八边形,  U越大蓝色越蓝,V越大,红色越红。

 

以下具体为各种转换公式(该转换公式基于BT601 ,NTSC色域 )

1.小数形式, YUV   (  U∈[-0.5-0.5]  ,   R,G,B∈[0,1]  )

R = Y + 1.4075 * V;  
G = Y - 0.3455 * U - 0.7169*V;  
B = Y + 1.779 * U;  


Y = 0.299*R + 0.587*G + 0.114*B;

U = (B-Y)/1.772;    

V = (R-Y)/1.402;      
                                         
或写为:
Y =  0.299*R + 0.587*G + 0.114*B;

U = -0.169*R - 0.331*G + 0.5  *B ;

V =  0.5  *R - 0.419*G - 0.081*B;

 

2.整数形式(减少计算量)未量化     R,G,B~[0,255]   U,V~[-128,128]

R= Y + ((360 * (V - 128))>>8) ; 
G= Y - (( ( 88 * (U - 128)  + 184 * (V - 128)) )>>8) ; 
B= Y +((455 * (U - 128))>>8) ;


Y = (77*R + 150*G + 29*B)>>8;

U = ((-44*R  - 87*G  + 131*B)>>8) + 128;

V = ((131*R - 110*G - 21*B)>>8) + 128 ;


3. 量化为 tv range 后的公式( Y~(16,235)  U/V ~(16,240)  ) 

  [Y,U,V,1]T =  M[R,G,B,1]T 其中 M =  

[ 0.2568, 0.5041, 0.0979, 16    

-0.1479, -0.2896, 0.4375, 128    

0.4375, -0.3666, -0.0709, 128,  

0, 0, 0, 1 ]

  [R,G,B,1]T = M[Y,U,V,1]T      M =  

1.1644   0              1.6019   -223.5521   

1.1644   -0.3928   -0.8163   136.1381   

1.1644   2.0253   0              -278.0291   

0.0000   0.0000   0.0000     1.0000   


4  tv range的公式写成整数的形式(减小计算量)   ( Y~(16,235)  U/V ~(16,240)  )

 yuv --> rgb

R = (298*Y + 411 * V - 57344)>>8
G = (298*Y - 101* U - 211* V+ 34739)>>8
B = (298*Y + 519* U- 71117)>>8

 

rgb --> yuv 

Y= (  66*R + 129*G  +  25*B)>>8 + 16 

U= (-38*R  -    74*G  + 112*B)>>8 +128

V= (112*R -    94*G  -   18*B)>>8   + 128

 

5. YUV量化 与 非量化 互转

tvrange  转 fullrange

Y=(Y'-16   )*255/219 ; 

U=(U'-128)*128/112;

V=(V'-128)*128/112;

 

full range 转 tv range  U~(-128-127)  ----->   U~(16-240)

Y' = ((219*Y)>>8)   +   16;

U' = ((219*U)>>8)   + 128;

V' = ((219*V)>>8)   + 128;

 

7. 矩阵形式(BT601):

YUV

       [Y,U,V]T =  M[R,G,B]T   其中 M = 0.299 , 0.587, 0.114,  -0.169,   - 0.331,   0.5,       0.5,  - 0.419    - 0.081

     [R,G,B]T =  M[Y,U,V]T  其中 M = 1    0   1.4017       1   -0.3437   -0.7142       1   1.7722   0

YCbCr  tv range

  [Y,U,V,1]T =  M[R,G,B,1]T 其中 M =  [ 0.2568, 0.5041, 0.0979, 16    -0.1479, -0.2896, 0.4375, 128    0.4375, -0.3666, -0.0709, 128,  0, 0, 0, 1 ]

  [R,G,B,1]T = M[Y,U,V,1]T            M =  1.1644   0   1.6019   -223.5521   1.1644   -0.3928   -0.8163   136.1381   1.1644   2.0253   0   -278.0291   0.0000   0.0000   0.0000   1.0000   

                                                          

tvrange的公式写成整数形式

  [Y,U,V,1]T =  (M[R,G,B,1]T)>>8 其中 M =  66, 129, 25, 4096,    -38, -74, 112, 32768,    112, -94, -18, 32768,    0, 0, 0, 256

  [R,G,B,1]T = (M[Y,U,V,1]T)>>8            M = 298, 0, 410, -57229,    298,     -101, -209, 34851,    298, 518, 0, -71175,    0, 0, 0, 256

 

 

二、. Rec2020 (BT2020) 下的YUV与RGB转换公式  (写成矩阵形式)

 

  BT2020 UV 的坐标图(量化后为CbCr): (横坐标为Cb,纵坐标为Cr,左下角为原点)

1.  BT2020 文档上的公式

即:

Y = 0.2627*R + 0.6780*G + 0.0593*B;

U = -0.1396*R - 0.3604*G + 0.5*B;

V = 0.5*R - 0.4598*G -0.0402*B;

 

矩阵形式

YUV RGB互转公式

       [Y,U,V]T =  M[R,G,B]T   其中 M = 0.2627   0.6780   0.0593 ,     -0.1396   -0.3604   0.5000,    0.5000   -0.4598   -0.0402        

       [R,G,B]T =  M[Y,U,V]T  其中 M = 1.0000   -0.0000   1.4746   1.0000   -0.1645   -0.5713   1.0000   1.8814   -0.0001   

YCbCr(tv range) RGB互转公式

  [Y,U,V,1]T =  M[R,G,B,1]T   其中 M = 0.2256, 0.5823, 0.05093, 16,       -0.1222, -0.3154, 0.4375, 128 ,        0.4375, -0.4023, -0.0352, 128,       0,0,0,1

  [R,G,B,1]T = M[Y,U,V,1]T            M =1.1644,   0,   1.6853,   -234.3559,       1.1644,   -0.1881,   -0.6529,   89.0206,       1.1646,   2.1501,   0.0000,   -293.8542,       0.0000,   0.0000,   0.0000,   1.0000

                                                          

tv range 互转公式写成整数形式

  [Y,U,V,1]T =  (M[R,G,B,1]T)>>8 其中 M  =  

58, 149, 13, 4096,

-31,-81, 112, 32768,

112, -103, -9, 32768,

0, 0, 0, 256

  [R,G,B,1]T = (M[Y,U,V,1]T)>>8            M =  

298, 0, 431, -59995,    

298, -48, -167, 22789,    

298, 550, 0, -75227,    

0, 0, 0, 256


http://www.ppmy.cn/news/194104.html

相关文章

PyTorch 第六章

文章目录 一 Neural Style Transfer1图片风格迁移2.图片表示3.Content Loss4.Style Loss 二 Generative Adversarial Networks1 基本含义2 DCGAN 三 CycleGAN1. Network2.模型架构3.损失函数 四 代码实战1.图片风格迁移 Neural Style Transfer2.Generative Adversarial Network…

C++:多重继承:虚函数表、指针的位置问题

文章目录 建议多重继承虚函数表虚函数表的存放位置,二进制文件 建议 需要看《深入理解C对象模型》 这本书。 多重继承 多重继承就不应该存在,因为严重违反“简单原则”;不易理解,不易维护,不易开发。 就C Primer pl…

语义分割yolov5 v4.0 baseline快速复现 快速跑通 图像分割 图像分类 重新训练,训练结果,测试结果,实验图片-20210227

本机环境说明 操作系统版本 :~$ cat /etc/*release DISTRIB_IDUbuntu DISTRIB_RELEASE18.04 DISTRIB_CODENAMEbionic DISTRIB_DESCRIPTION"Ubuntu 18.04.5 LTS" NAME"Ubuntu" VERSION"18.04.5 LTS (Bionic Beaver)" IDubuntu ID_LIKEdebian PR…

【异步电机系列】电机参数离线辨识(含源码实现)

【一、闲话 很久没有认真更新自己的博客了!正好这段时间在学习异步电机控制,所以把过程中的一些东西写下来,当是回顾也是备忘。本来想是把整个过程的问题和收获都记录下来的(包括硬件设计、mcu控制、算法等)&#xff0…

二进制包20分钟快速安装部署 Kubernetes v1.14.0 集群

文章目录 二进制包20分钟快速安装部署 Kubernetes v1.14.0 集群一 环境二 架构三 安装过程3.1 初始化脚本3.2 安装脚本3.3 安装失败回滚脚本 四 总结 二进制包20分钟快速安装部署 Kubernetes v1.14.0 集群 一 环境 操作系统Docker版本Kubernetes版本Etcd版本Flannel版本CentO…

bluetoothd源码剖析(一)启动流程

蓝牙系列: bluez调试笔记_weixin_41069709的博客-CSDN博客_bluezbluez移植https://blog.csdn.net/weixin_41069709/article/details/125168114?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22125168114%22%2C%22sour…

海思HI35XX之----音频模块使用总结

HI3518C /海思音频编解码 /海思音频数据帧头 /HI35XX音频编解码流程 /HI35XX音频属性配置 7722 https://blog.csdn.net/zqj6893/article/details/25562633 AUDIO 模块包括音频输入、音频输出、音频编码、音频解码四个子模块。音频输入和 输出模块通过对 Hi35xx 芯片 SIO …

PHP全栈学习笔记33

javascript能做什么? 语句与注解,标识符,字面量,变量命名规范 JavaScript中的数据类型,其它类型如何转为数据型,操作符 字符方法,数组方法,函数与对象,函数表达式&#…