RGB与YUV公式转换推导

news2024/12/23 3:23:51

目录

 

简介

Full Range公式推导

Limit Range推导

验证测试

参考资料

简介

RGB与YUV之间的转换有很多种标准,不同标准系数不一样,而且经常容易搞混淆,另外还有full range和limitrange的不同。其实这些转换系数都是推导出来的,有理论支撑的,并不是标准里直接给出来的系数。本篇文章主要是来介绍公式的推导。

Full Range公式推导

从YUV的定义中可知Y代表红绿蓝的比例混合,U代表蓝色与亮度Y的差量,V代表红色与亮度Y的差量,那么求RGB转YUV就是求混合比例。求YUV转RGB就是它的逆变化。如下图所示用公式展现了如何用混合比例实现RGB转YUV,其中KrKgKb就是RGB的混合比例。

f9de473af5574d8592c143fd74efc300.png

其中,KrKgKb三个系数是RGB转XYZ矩阵的第二行,RGB转XYZ可以参考【精选】颜色空间转换-从RGB到LCH-亮度饱和度色度_rgb转lch-CSDN博客。有了这三个系数,RGB转YUV的系数就确定了,所以RGB转YUV完全是由色域的色坐标决定的。计算RGB2YUV的系数只要对YUV2RGB求逆即可。

109bd823ffab4c44a5d9669033fd8aad.png

参考代码如下:

def GetFullRangeCoef(xy):
    matRGB2XYZ, matXYZ2RGB = GetRGBXYZMatrices(xy)

    rgb2yuv_coef = np.zeros((3,3), np.float32)
    rgb2yuv_coef[0, :] = matRGB2XYZ[1, :]
    kr = matRGB2XYZ[1, 0]
    kg = matRGB2XYZ[1, 1]
    kb = matRGB2XYZ[1, 2]
    rgb2yuv_coef[1, 0] = kr / (2*(kb - 1))
    rgb2yuv_coef[1, 1] = kg / (2*(kb - 1))
    rgb2yuv_coef[1, 2] = 0.5
    rgb2yuv_coef[2, 0] = 0.5
    rgb2yuv_coef[2, 1] = kg / (2*(kr - 1))
    rgb2yuv_coef[2, 2] = kb / (2 * (kr - 1))

    yuv2rgb_coef = np.linalg.inv(rgb2yuv_coef)

    return rgb2yuv_coef, yuv2rgb_coef

Limit Range推导

YCbCr的范围又叫limit range,tv range,YUV的范围又叫full range、pc range。

电视机中的YUV又叫YCbCr(Cb是ColorBlue缩写,Cr是ColorRed缩写),YCbCr为了解决吉布斯现象对范围进行了调整,下图说明了正弦函数模拟原始信号时波形的峰值超过原始信号8.9%,需要缩小YCbCr的范围防止溢出,譬如8位YUV的范围是[0,255],那么8位YCbCr的范围就是Y[16,235]UV[16,240],(255−235)/(235−16)=9.1略大于大于8.9%,16/(235−16)=7.3略小于8.9%。

62c49712e58c4eff9d166f6a11c4795a.png

limit range的YCbCr转RGB的流程如下:

f47c09e4c47c4cfab471782a8b024812.png

以8bit为例,Yscale=255 / (235 - 16),Uscale=255 / (240 - 16),Vscale=255 / (240 - 16),Yoffset=-16,Uoffset=-128,Voffset=-128。RGB2YCbCr只要对其进行求逆即可。

limit range公式推导参考代码如下:

def GetLimitRangeCoef(yuv2rgb_full):
    scale_mat = np.zeros((3, 3), np.float)

    scale_mat[0, 0] = 255 / (235 - 16)
    scale_mat[1, 1] = 255 / (240 - 16)
    scale_mat[2, 2] = 255 / (240 - 16)

    yuv2rgb_limit = yuv2rgb_full @ scale_mat
    rgb2yuv_limit = np.linalg.inv(yuv2rgb_limit)
    return rgb2yuv_limit, yuv2rgb_limit

验证测试

我们常用的YUV与RGB转换的标准主要有BT709,BT601,BT2020,他们的色坐标分别为:

#BT709
    xysRGB = np.array([
        [0.64, 0.33],
        [0.30, 0.60],
        [0.15, 0.06],
        [0.3127, 0.3290]
    ])
    #BT2020
    xyBT2020 = np.array([
        [0.708, 0.292],
        [0.17, 0.797],
        [0.131, 0.046],
        [0.3127, 0.3290]
    ])
    #BT601
    xyNTSC = np.array([
        [0.67, 0.33],
        [0.21, 0.71],
        [0.14, 0.08],
        [0.3101, 0.3162]
    ])

然后参考代码如下:

def TestsRGB709():
    #BT709
    xysRGB = np.array([
        [0.64, 0.33],
        [0.30, 0.60],
        [0.15, 0.06],
        [0.3127, 0.3290]
    ])
    #BT2020
    xyBT2020 = np.array([
        [0.708, 0.292],
        [0.17, 0.797],
        [0.131, 0.046],
        [0.3127, 0.3290]
    ])
    #BT601
    xyNTSC = np.array([
        [0.67, 0.33],
        [0.21, 0.71],
        [0.14, 0.08],
        [0.3101, 0.3162]
    ])

    rgb2yuv_coef, yuv2rgb_coef = GetFullRangeCoef(xyNTSC)
    print('rgb2yuv_full:', np.round(rgb2yuv_coef, 4))
    print('yuv2rgb_full:', np.round(yuv2rgb_coef, 4))

    rgb2yuv_limit, yuv2rgb_limit = GetLimitRangeCoef(yuv2rgb_coef)
    print('rgb2yuv_limit:', np.round(rgb2yuv_limit, 4))
    print('yuv2rgb_limit:', np.round(yuv2rgb_limit, 4))

BT601得到的结果如下:

rgb2yuv_full: 
[[ 0.2989  0.5866  0.1144]
 [-0.1688 -0.3312  0.5   ]
 [ 0.5    -0.4184 -0.0816]]
yuv2rgb_full: 
[[ 1.     -0.      1.4021]
 [ 1.     -0.3455 -0.7145]
 [ 1.      1.7711  0.    ]]
rgb2yuv_limit: 
[[ 0.2567  0.5038  0.0983]
 [-0.1483 -0.291   0.4392]
 [ 0.4392 -0.3675 -0.0717]]
yuv2rgb_limit: 
[[ 1.1644 -0.      1.5962]
 [ 1.1644 -0.3933 -0.8134]
 [ 1.1644  2.0162  0.    ]]

 BT709得到的结果:

rgb2yuv_full: 
[[ 0.2126  0.7152  0.0722]
 [-0.1146 -0.3854  0.5   ]
 [ 0.5    -0.4542 -0.0458]]
yuv2rgb_full: 
[[ 1.     -0.      1.5747]
 [ 1.     -0.1873 -0.4682]
 [ 1.      1.8556 -0.    ]]
rgb2yuv_limit: 
[[ 0.1826  0.6142  0.062 ]
 [-0.1007 -0.3386  0.4392]
 [ 0.4392 -0.3989 -0.0403]]
yuv2rgb_limit: 
[[ 1.1644 -0.      1.7927]
 [ 1.1644 -0.2132 -0.533 ]
 [ 1.1644  2.1124 -0.    ]]

BT2020得到的结果:

rgb2yuv_full: 
[[ 0.2627  0.678   0.0593]
 [-0.1396 -0.3604  0.5   ]
 [ 0.5    -0.4598 -0.0402]]
yuv2rgb_full: 
[[ 1.     -0.      1.4746]
 [ 1.     -0.1646 -0.5714]
 [ 1.      1.8814  0.    ]]
rgb2yuv_limit: 
[[ 0.2256  0.5823  0.0509]
 [-0.1227 -0.3166  0.4392]
 [ 0.4392 -0.4039 -0.0353]]
yuv2rgb_limit: 
[[ 1.1644 -0.      1.6787]
 [ 1.1644 -0.1873 -0.6504]
 [ 1.1644  2.1418  0.    ]]

可以看到得到的系数和我们常用的是一样的,这样只要给定色域,其实就有一组对应的转换系数,完全是由色域大小决定的。

参考资料:

HDR转SDR实践之旅(四)YUV转RGB矩阵推导 - 掘金

网上流传的矩阵错了?浅谈如何正确推导视频YUV转RGB矩阵 - 知乎

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1126358.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【通览一百个大模型】Baize(UCSD)

【通览一百个大模型】Baize(UCSD) 作者:王嘉宁,本文章内容为原创,仓库链接:https://github.com/wjn1996/LLMs-NLP-Algo 订阅专栏【大模型&NLP&算法】可获得博主多年积累的全部NLP、大模型和算法干货…

【数据结构与算法】two X 树的遍历以及功能实现

前言: 前面我们已经提到过树、二叉树的概念及结构、堆排序、Top-k问题等的知识点,这篇文章我们来详解一下二叉树的链式结构等问题。 💥🎈个人主页:​​​​​​Dream_Chaser~ 🎈💥 ✨✨专栏:htt…

JVM工具使用(jstat + jmap)

命令格式 jstat -gcutil pid interval(ms) 举例: jstat -gcutil 16361 1000 线上服务器的GC情况如下: 参数说明如下: S0: 新生代中Survivor space 0区已使用空间的百分比S1: 新生代中Survivor space 1区已使用空间的百分比E: 新生代已使用空…

ETL实现实时文件监听

一、实时文件监听的作用及应用场景 实时文件监听是一种监测指定目录下的文件变化的技术,当产生新文件或者文件被修改时,可实时提醒用户并进行相应处理。这种技术广泛应用于数据备份、日志管理、文件同步和版本控制等场景,它可以帮助用户及时…

Nacos 下载运行及配置

Nacos 服务注册与配置中心,兼顾两者 文章目录 Nacos 服务注册与配置中心,兼顾两者一、简介二、相关文档2.1 Nacos官网2.2 官方文档 三、下载并运行Nacos3.1 下载压缩包3.2 解压缩3.3 运行命令3.4 访问Nacos控制台 附录:各种注册中心比较 Naco…

CAS是“Compare and Swap“(比较并交换)

CAS是"Compare and Swap"(比较并交换) 一,介绍 CAS是"Compare and Swap"(比较并交换)的缩写,是一种多线程同步的原子操作。它基于硬件的原子性保证,用于解决并发环境下的…

在前台页面中console怎么查vue.prototype

在测试项目接口时发现调用接口调用异常,怀疑可能是网省配置问题 1. 打开前台页面。 2. 右键点击页面,选择"检查元素"或者"审查元素"。 3. 在打开的开发者工具中,选择"控制台"选项卡。 4. 在控制台中输入以下代…

TCP通信实战案例-即时通信

即时通信是什么含义,要实现怎么样的设计? 即时通信,是指一个客户端的消息发出去,其他客户端可以接收到。 即时通信需要进行端口转发的设计思想。 服务端需要把在线的Socket管道存储起来。 一旦收到一个消息要推送给其他管道。…

05-01 jdk,tomcat,mariadb数据库和profile多环境

1.卸载系统默认安装jdk # java -version # rpm -qa|grep openjdk -i # rpm - e --nodeps 需要删除的软件2.安装jdk 2.1新建jdk安装目录并解压 # mkdir /usr/java # cd /usr/ # tar -zxvf jdk-8u191-linux-x64.tar.gz # mv jdk-8u191/ /usr/java/2.2配置环境变量 # vim /etc/…

【Javascript】等于与全等于

var a1;if(a1){console.log(你好!!);} 如果a赋值为 1 的时候 var a1;if(a1){console.log(你好!!);}仍然会执行 console.log(你好!!); 所以在开发中如果if语句里要使用等于的时候使用 var a1;if(a1)…

编程小白的自学笔记十七(python办公自动化操作EXCEL表格之作图)

系列文章目录 编程小白的自学笔记十六(python办公自动化操作EXCEL表格) 编程小白的自学笔记十五(python办公自动化操作EXCEL表格) 编程小白的自学笔记十四(python办公自动化创建、复制、移动文件和文件夹 编程小白…

Qt 项目实战 | 多界面编辑器

Qt 项目实战 | 多界面编辑器 Qt 项目实战 | 多界面编辑器界面设计创建子窗口类 官方博客:https://www.yafeilinux.com/ Qt开源社区:https://www.qter.org/ 参考书:《Qt 及 Qt Quick 开发实战精解》 Qt 项目实战 | 多界面编辑器 开发环境&…

运行segment anything模型的web demo 教程

这个web应用放在在源码的demo文件夹里: 这个前端仅基于React的web演示了如何加载固定图像和相应的SAM image embedding的.npy文件。 运行需要配置npm环境。 首先导出onnx的模型: import torch import numpy as np import cv2 import matplotlib.pyplo…

解决 Vue3 + Element Plus 树形表格全选多选以及子节点勾选的问题

原文链接: 解决 Vue3 Element Plus 树形表格全选多选以及子节点勾选的问题 前言 最近用到了 Element Plus 组件库的中的树形表格,但官网例子只能做到一层勾选,不能做到多层勾选,无法满足业务需求,所以研究了下&#…

PHP 预定义超全局变量 笔记/练习

预定义超全局数组变量 $_FILES 练习在最后 其他练习跟在每条笔记后 概述 预定义:预定义变量是 PHP 已定义,可以直接使用超全局:作用域是全局,可以在脚本的任何地方(包括函数内部、外部)都可以进行访问 常…

CSS必学:你需要知道的盒子模型的秘密

作者:WangMin 格言:努力做好自己喜欢的每一件事 CSDN原创文章 博客地址 👉 WangMin 作为前端开发来说,要掌握的CSS基础一定很多,那么CSS中盒子模型肯定是必考必问必掌握的前端知识点,因为它是CSS基础中非常重要的内容,…

分步实现编写LED驱动,实现特备文件和设备的绑定

通过字符设备驱动的分步实现编写LED驱动,另外实现特备文件和设备的绑定,发布到CSDN head.h #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct {unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int ID…

photoshop2024免费插件Portraiture3

随着手机摄影的普及,修图可以说是现代人的必备生活技能之一了,现在谁发个朋友圈不把自己的照片修的美美的呢?那么如何拥有一张氛围感满满的照片呢?这不得不提图片处理软件中的王牌——photoshop。作为专业的图片处理软件&#xff…

Node.js与npm版本比对

Node.js与npm版本比对 Node.js与npm版本比对版本对比表Node版本对比 Node.js与npm版本比对 我们在项目开发过程中,经常会遇到公司一些老的前端工程项目,而我们当前的node及npm版本都是相对比较新的了。 在运行以前工程时,会遇到相关环境不匹…

2023年中国汽车差速器需求量、竞争现状及行业市场规模分析[图]

差速器是汽车驱动系统的主要部件,它的作用就是在向两边半轴传递动力的同时,允许两边半轴以不同的转速旋转,满足两边车轮尽可能以纯滚动的形式作不等距行驶,减少轮胎与地面的摩擦。汽车差速器是驱动车轮差速转弯或复杂路面强力通过…