RGB和YUV

 

 RGB和YUV都是色彩空间,用于表示颜色,两者可以相互转化。   YUV(亦称YCrCb)是被欧洲电视系统所采用的一种颜色编码方法(属于PAL)。YUV主要用于优化彩色视频信号的传输,使其向后兼容老式黑白电视。与R GB视频信号传输相比,它最大的优点在于只需占用极少的带宽(RGB要求三个独立的视频信号同时传输)。
     中"Y"表示明亮度(Lumina nce或Luma),也就是灰阶值;是个基带信号。而"U"和"V"表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。U和V不是基带信号,它俩是被正交调制了的。
     "亮度"是通过RGB输入信号来创建的,方法是将RGB信号的特定部分叠加到一起。"色度"则定义了颜色的两个方面-色调与饱和度,分别用Cr和CB来表示。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而CB反映的是RGB输入信号蓝色部分与RGB信号亮度值之同的差异。。通过运算,YUV三分量可以还原出R(红),G(绿),B(兰)。

一、和rgb之间换算公式的差异

yuv<-->rgb

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

U''= -0.147*R'' - 0.289*G'' + 0.436*B'' = 0.492*(B''- Y'')

V''= 0.615*R'' - 0.515*G'' - 0.100*B'' = 0.877*(R''- Y'')

R'' = Y'' + 1.140*V''

G'' = Y'' - 0.394*U'' - 0.581*V''

B'' = Y'' + 2.032*U''

yCbCr<-->rgb

Y’ = 0.257*R'' + 0.504*G'' + 0.098*B'' + 16

Cb'' = -0.148*R'' - 0.291*G'' + 0.439*B'' + 128

Cr'' = 0.439*R'' - 0.368*G'' - 0.071*B'' + 128

R'' = 1.164*(Y’-16) + 1.596*(Cr''-128)

G'' = 1.164*(Y’-16) - 0.813*(Cr''-128) - 0.392*(Cb''-128)

B'' = 1.164*(Y’-16) + 2.017*(Cb''-128)

Note: 上面各个符号都带了一撇,表示该符号在原值基础上进行了gamma correction



二、来源上的差异

yuv色彩模型来源于 rgb模型,

该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。

第一个公式是YUV转换RGB(范围0-255)时用的,第二个公式是用在YUV(601)也成为YCbCr转换RGB(范围0-255)时用的。

1.Y =   0.299R + 0.587G + 0.114B
   U = -0.147R - 0.289G + 0.436B
   V = 0.615R - 0.515G - 0.100B

   R = Y             + 1.14V
   G = Y - 0.39U - 0.58V
   B = Y + 2.03U

2.B= 1.164 * (Y - 16) + 2.018 * (U - 128)
   G= 1.164 * (Y - 16) -   0.38 * (U - 128) - 0.813 * (V - 128)
   R= 1.164 * (Y - 16)                             + 1.159 * (V - 128)

 

### RGB YUV 颜色空间转换的算法及代码实现 #### 转换公式 RGBYUV转换可以通过以下线性变换公式完成[^1]: \[ Y = 0.299R + 0.587G + 0.114B \] \[ U = -0.147R - 0.289G + 0.436B \] \[ V = 0.615R - 0.515G - 0.100B \] 反向转换(即从 YUVRGB)可以使用以下公式[^3]: \[ R = Y + 1.14 \cdot V \] \[ G = Y - 0.395 \cdot U - 0.581 \cdot V \] \[ B = Y + 2.032 \cdot U \] 需要注意的是,在实际应用中,由于计算过程中涉及浮点运算以及最终存储时通常需要将结果强制转换为整数类型 `unsigned char`,这可能导致一定的精度损失。 --- #### C++ 实现代码 以下是基于上述公式的 C++ 实现代码示例: ```cpp #include <iostream> #include <vector> using namespace std; // 定义结构体表示像素 struct Pixel { unsigned char R, G, B; }; void RGBtoYUV(const vector<Pixel>& rgbPixels, vector<vector<float>>& yuvPixels) { for (const auto& pixel : rgbPixels) { float R = pixel.R / 255.0f; // 归一化到 [0, 1] float G = pixel.G / 255.0f; float B = pixel.B / 255.0f; float Y = 0.299 * R + 0.587 * G + 0.114 * B; float U = -0.147 * R - 0.289 * G + 0.436 * B; float V = 0.615 * R - 0.515 * G - 0.100 * B; yuvPixels.push_back({Y, U, V}); } } void YUVtoRGB(const vector<vector<float>>& yuvPixels, vector<Pixel>& rgbPixels) { for (const auto& yuv : yuvPixels) { float Y = yuv[0]; float U = yuv[1]; float V = yuv[2]; float R = Y + 1.14 * V; float G = Y - 0.395 * U - 0.581 * V; float B = Y + 2.032 * U; // 将值裁剪回 [0, 255] 并转换为无符号字符 R = max(0.0f, min(R, 1.0f)) * 255.0f; G = max(0.0f, min(G, 1.0f)) * 255.0f; B = max(0.0f, min(B, 1.0f)) * 255.0f; rgbPixels.push_back({static_cast<unsigned char>(R), static_cast<unsigned char>(G), static_cast<unsigned char>(B)}); } } ``` 此代码实现了两种颜色空间之间的双向转换。注意在实际操作中可能还需要考虑字节对齐等问题。 --- #### 文件读取与保存 为了验证转换效果,可以加载原始 RGB 图像文件并将其转换YUV 格式后再转回 RGB 进行对比。具体流程包括但不限于以下几个步骤: 1. 使用库(如 OpenCV 或 FFmpeg)读取图像数据; 2. 应用前述函数执行颜色空间转换; 3. 存储生成的数据以便进一步观察或测试其一致性。 --- #### 结果分析 通过实验发现,当从 RGB 转换YUV 后再返回到 RGB 时,可能会引入一定误差[^4]。主要原因包括: - 浮点运算后的截断错误。 - 数据类型的强制转换过程中的舍入问题。 这些因素共同影响了最终重建图片的质量。 --- 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值