【图像处理】-小议YUV色彩空间-YUV和RGB格式的来由,相互关系以及转换方式,并对编程实现的YUV转为RGB程序进行介绍

本文主要是介绍【图像处理】-小议YUV色彩空间-YUV和RGB格式的来由,相互关系以及转换方式,并对编程实现的YUV转为RGB程序进行介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

小议YUV色彩空间
摘要:
在视频图像处理等相关相关领域,YUV是一个经常出现的格式。本文主要以图解的资料形式详细描述YUV和RGB格式的来由,相互关系以及转换方式,并对编程实现的YUV转为RGB程序进行介绍。
1 引言
自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用的过程,所以在不同的应用领域中为了更好更准确的满足各自的需求,就出现了各种各样的色彩空间模型来量化的描述颜色。我们比较常接触到的就包括 RGB / CMYK / YCbCr/ YUV / HSI等等。
即使只是RGB、 YUV这两大类色彩空间,所涉及到的知识也是十分丰富复杂的,自知具备的相关专业知识有限,所以本文主要针对自己所了解的相关知识以及项目开发中遇到的相关问题对YUV色彩空间相关进行讨论。

2 理论分析
2.1 RGB、YUV色彩空间模型介绍
RGB与YUV有着千丝万缕的联系与区别,其中RGB是按三基色加光系统的原理来描述颜色,而YUV则是按照亮度、色差的原理来描述颜色。
2.1.1 RGB 颜色空间
RGB 颜色空间是我们最常见的颜色空间,是一种简单鲁棒性较好的定义颜色的空间。RGB 颜色空间由红、绿、蓝三个基本颜色通道组成,由这些颜色通道组合代表一种颜色。RGB 颜色模型可以通过一个立方体颜色模型,如图 1 表示,其三个轴分别代表红、绿、蓝 3 个颜色分量。对于一张 24 位真彩色的图片,R、G、B 三个通道各自具有 8 位宽,像素的取值范围为0-255,红色为(255,0,0),绿色为(0,255,0),蓝色为(0,0,255)。
在这里插入图片描述

图 1 RGB颜色模型
2.1.2 YUV颜色空间
在现代彩色电视系统中,通常采用三管彩色摄像机或彩色CCD(点耦合器件)摄像机,它把摄得的彩色图像信号,经分色、分别放大校正得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号R-Y、B-Y,最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这就是我们常用的YUV色彩空间。

2.1.2.1 RGB 颜色空间过渡到YUV色彩空间
对于视频捕获和编解码等应用来讲,RGB这样的表示方式数据量太大了。需要想办法在不太影响感觉的情况下,对原始数据的表示方法进行更改,减少数据量。
在RGB色彩空间中,三个颜色的重要程度相同,所以需要使用相同的分辨率进行存储, 3个颜色通道需要按照相同的分辨率进行存储,数据量还是很大的。所以,利用人眼睛对亮度比对颜色更加敏感,将图像的亮度信息和颜色信息分离,并使用不同的分辨率进行存储,这样可以在对主观感觉影响很小的前提下,更加有效的存储图像数据。
YCbCr色彩空间和它的变形(也就是YUV)是最常用的有效的表示彩色图像的方法。Y是图像的亮度(luminance/luma)分量,使用以下公式计算,为R,G,B分量的加权平均值:
Y = kr R + kgG + kbB,其中k是权重因数。
上面的公式计算出了亮度信息,还有颜色信息,使用色差(color difference/chrominance或chroma)来表示,其中每个色差分量为R,G,B值和亮度Y的差值:
  Cb = B -Y Cr = R -Y Cg = G- Y
其中,Cb+Cr+Cg是一个常数(其实是一个关于Y的表达式),所以,只需要其中两个数值结合Y值就能够计算出原来的RGB值。所以,我们仅保存亮度和蓝色、红色的色差值,这就是(Y,Cb,Cr)。
相比RGB色彩空间,YCbCr色彩空间有一个显著的优点。Y的存储可以采用和原来画面一样的分辨率,但是Cb,Cr的存储可以使用更低的分辨率。这样可以占用更少的数据量,并且在图像质量上没有明显的下降。所以,将色彩信息以低于量度信息的分辨率来保存是一个简单有效的图像压缩方法。
注释:YCbCr进行不同的取样就是所谓的YUV了。

2.1.2.2 YUV与RGB相互转换
YUV 空间和RGB空间存在如下转换关系:
在这里插入图片描述

注释:
1、从公式中,我们关键要理解的一点是,UV / CbCr信号实际上就是蓝色差信号和红色差信号,进而言之,实际上一定程度上间接的代表了蓝色和红色的强度,理解这一点对于我们理解各种颜色变换处理的过程会有很大的帮助。
2、我们在数字电子多媒体领域所谈到的YUV格式,实际上准确的说,是以YcrCb色彩空间模型为基础的具有多种存储格式的一类颜色模型的家族(包括YUV444 / YUV422 / YUV420 / YUV420P等等)。并不是传统意义上用于PAL制模拟电视的YUV模型。这些YUV模型的区别主要在于UV数据的采样方式和存储方式

2.2 RGB、YUV色彩空间模型内存分布
在RGB24格式中,对于宽度为w,高度为h的画面,需要wh3个字节来存储其每个像素的rgb信息,画面的像素数据是连续排列的。按照r(0,0),g(0,0),b(0,0);r(0,1),g(0,1),b(0,1);…;r(w-1,0),g(w-1,0),b(w-1,0);…;r(w-1,h-1),g(w-1,h-1),b(w-1,h-1)这样的顺序存放起来。
在YUV格式中,以YUV420格式为例。宽度为w高度为h的画面,其亮度Y数据需要wh个字节来表示(每个像素点一个亮度)。而Cb和Cr数据则是画面中4个像素共享一个Cb,Cr值。这样Cb用wh/4个字节,Cr用wh/4个字节。
YUV文件中,把多个帧的画面连续存放。就是YUV YUV YUV……这样的不断连续的形式,而其中每个YUV,就是一幅画面。
在这单个YUV中,前w
h个字节是Y数据,接着的wh/4个字节是Cb数据,再接着的wh/4个字节为Cr数据。

2.3 RGB、YUV色彩空间模型数据表达方式
以320240的一帧图像为例RGB24的排列方式如下图所示:
每个像素点有三个字节组成分别表示R,G,B分量上的颜色值。在数据中的表示方式为一个像素 一个像素表示。字节流可以表述如下:
BGRBGRBGRBGRBGR……
|---------------320
2403-------|
每一个字母表示一个字节,也就是该颜色分量的数值,相邻的三个BGR字节表示一个像素点。在我们做计算时,通常一次取三个字节,也就是一个像素点。
相应的YV12的排列方式如下图所示:
每个像素点都有一个Y分量,每隔一列就有一个U或者V分量,U和V交替出现。YV12的字节流表示方式和RGB24有很大区别,YV12并不是按照像素依次排列的,而是先放置Y空间,然后放置整个V空间,最后放置U空间,那么字节流如下所示:
YYYYYYY……VVVV……UUUU……
|-----320
240----|-320240/4-|-320240/4-|
在320240个字节的Y后,紧跟着320240/4个V和320240/4个U。
YV12和RGB24同样都有320
240个像素点,但是在数据结构和字节流上有着很大区别。单纯从数据大小来看,RGB24的数据大小为3202403Bytes,而YV12为3202401.5Bytes,可见YV12的数据量为RGB24的一半。

2.4 YCbCr色彩空间模型取样格式
对YCbCr色彩空间,进行不同格式的取样就得到不同的YUV格式了,如下图3所示。
在这里插入图片描述

2.5 RGB、YUV色彩空间模型转换示例
核心编程示例
//RGB转YUV
bool RGB2YUV(byte* RgbBuf,int nWidth,int nHeight,byte* yuvBuf,unsigned long len)
{
int i, j;
byte
bufY, *bufU, *bufV, *bufRGB,bufYuv;
memset(yuvBuf,0,(unsigned int )len);//len表示yuvBuf长度(WH3/2)
bufY = yuvBuf;//Y首址
bufV = yuvBuf + nWidth * nHeight;//V首址
bufU = bufV + (nWidth * nHeight
1/4);//U首址
*len = 0;
byte y, u, v, r, g, b,testu,testv;
unsigned int ylen = nWidth * nHeight; //Y长度
unsigned int ulen = (nWidth * nHeight)/4;//U长度
unsigned int vlen = (nWidth * nHeight)/4; //V长度

for (j = 0; j < nHeight;j++)
{bufRGB = RgbBuf + nWidth * (nHeight - 1 - j) * 3 ;for (i = 0;i < nWidth;i++){int pos = nWidth * i + j;r = *(bufRGB++);g = *(bufRGB++);b = *(bufRGB++);y = (byte)( ( 66 * r + 129 * g +  25 * b + 128) >> 8) + 16  ;          u = (byte)( ( -38 * r -  74 * g + 112 * b + 128) >> 8) + 128 ;          v = (byte)( ( 112 * r -  94 * g -  18 * b + 128) >> 8) + 128 ;*(bufY++) = max( 0, min(y, 255 ));if (j%2==0&&i%2 ==0){	//存u分量if (u>255){u=255;}if (u<0){u = 0;}*(bufU++) =u;}else{//存v分量if (i%2==0){ if (v>255){v = 255;}if (v<0){v = 0;}

*(bufV++) =v;
}
}
}
}
*len = nWidth * nHeight+(nWidth * nHeight)/2;
return true;
}

//YUV4转RGB
static void YUV420p_to_RGB24(unsigned char *yuv420[3], unsigned char *rgb24, int width, int height)
{
int R,G,B,Y,U,V,x,y;
int nWidth = width>>1; //色度信号宽度
for (y=0;y<height;y++)
{
for (x=0;x<width;x++)
{
Y = (yuv420[0] + ywidth + x);
U = (yuv420[1] + ((y>>1)nWidth) + (x>>1));
V = (yuv420[2] + ((y>>1)nWidth) + (x>>1));
R = Y + 1.402
(V-128);
G = Y - 0.34414
(U-128) - 0.71414
(V-128);
B = Y + 1.772
(U-128);
//防止越界
if (R>255)R=255;if (R<0)R=0;
if (G>255)G=255;if (G<0)G=0;
if (B>255)B=255;if (B<0)B=0;
*(rgb24 + ((height-y-1)*width + x)*3) = B;
*(rgb24 + ((height-y-1)*width + x)*3 + 1) = G;
*(rgb24 + ((height-y-1)*width + x)*3 + 2) = R;
}
}
}

2.4 RGB、YUV色彩空间模型转换示例实验结果
为了验证转换的效果,从RGB色彩空间转换到YUV420色彩空间再转换到RGB色彩空间,结果如下图4所示。

在这里插入图片描述

                      图4 RGB与YUV转换结果图

从上图看出,转换的效果还是可以的,部分地方出现色彩失真,算法还需优化。
3 结语
在视频监控领域,YUV是一个经常出现的格式。本文主要以图解的资料形式详细描述YUV和RGB格式的来由,相互关系以及转换方式,并对编程实现的YUV转为RGB程序进行介绍。

这篇关于【图像处理】-小议YUV色彩空间-YUV和RGB格式的来由,相互关系以及转换方式,并对编程实现的YUV转为RGB程序进行介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/888184

相关文章

Django中的函数视图和类视图以及路由的定义方式

《Django中的函数视图和类视图以及路由的定义方式》Django视图分函数视图和类视图,前者用函数处理请求,后者继承View类定义方法,路由使用path()、re_path()或url(),通过in... 目录函数视图类视图路由总路由函数视图的路由类视图定义路由总结Django允许接收的请求方法http

Python yield与yield from的简单使用方式

《Pythonyield与yieldfrom的简单使用方式》生成器通过yield定义,可在处理I/O时暂停执行并返回部分结果,待其他任务完成后继续,yieldfrom用于将一个生成器的值传递给另一... 目录python yield与yield from的使用代码结构总结Python yield与yield

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

pandas数据的合并concat()和merge()方式

《pandas数据的合并concat()和merge()方式》Pandas中concat沿轴合并数据框(行或列),merge基于键连接(内/外/左/右),concat用于纵向或横向拼接,merge用于... 目录concat() 轴向连接合并(1) join='outer',axis=0(2)join='o

shell脚本批量导出redis key-value方式

《shell脚本批量导出rediskey-value方式》为避免keys全量扫描导致Redis卡顿,可先通过dump.rdb备份文件在本地恢复,再使用scan命令渐进导出key-value,通过CN... 目录1 背景2 详细步骤2.1 本地docker启动Redis2.2 shell批量导出脚本3 附录总

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Oracle查询表结构建表语句索引等方式

《Oracle查询表结构建表语句索引等方式》使用USER_TAB_COLUMNS查询表结构可避免系统隐藏字段(如LISTUSER的CLOB与VARCHAR2同名字段),这些字段可能为dbms_lob.... 目录oracle查询表结构建表语句索引1.用“USER_TAB_COLUMNS”查询表结构2.用“a

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1