博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
颜色空间系列4: RGB和YDbDr颜色空间的转换及优化算法
阅读量:6302 次
发布时间:2019-06-22

本文共 5801 字,大约阅读时间需要 19 分钟。

    颜色空间系列代码下载链接: (同文章同步更新)

    YDbDr颜色空间和YCbCr颜色空间类似,其和RGB空间之间的相互转换公式里取 所描述的。

     RGB转为YDbDr为:

           \begin{align} Y   &= +0.299 R +0.587 G +0.114 B\\ D_B &= -0.450 R -0.883 G +1.333 B\\ D_R &= -1.333 R +1.116 G +0.217B\\ \begin{bmatrix} Y \\ D_B \\ D_R \end{bmatrix} &= \begin{bmatrix} 0.299 & 0.587 & 0.114 \\  -0.450 & -0.883 & 1.333 \\  -1.333 & 1.116 & 0.217 \end{bmatrix} \begin{bmatrix} R \\ G \\ B \end{bmatrix}\end{align}                  (1)

      对应的YDbDr转换为RGB的公式为:

         \begin{align} R &= Y +0.000092303716148 D_B -0.525912630661865 D_R\\ G &= Y -0.129132898890509 D_B +0.267899328207599 D_R\\ B &= Y +0.664679059978955 D_B -0.000079202543533 D_R\\ \begin{bmatrix} R \\ G \\ B \end{bmatrix} &= \begin{bmatrix} 1 & 0.000092303716148 & -0.525912630661865 \\ 1 & -0.129132898890509 & 0.267899328207599 \\ 1 & 0.664679059978955 & -0.000079202543533 \end{bmatrix} \begin{bmatrix} Y \\ D_B \\ D_R \end{bmatrix}\end{align}              (2)

     由式(1)可知Y的范围是[0,255],Db的范围是[-1.333*255,1.333*255],Dr的范围亦为[-1.333*255,1.333*255]。

     为了使Db,Dr的变换量程也为255-0大小,需要将上述Db/Dr压缩1.333*2倍,即将各系数处理( 1.333*2),得到新的转换: 

   [Y  ]     [0.2990  -0.1688   -0.5000 ]    [R]

     [Db] =   [0.5870     -0.3312    0.4186  ]    [G]      
   [Dr]     [0.1140     0.5000     0.0814   ]    [B]

     对应的逆变换可用matlab求上述矩阵的逆阵即可:

   [R]     [ 1.000000000000000   0.000246081707249  -1.402083073344533 ]    [Y]

     [G] =   [ 1.000000000000000  -0.344268308442098   0.714219609001458 ]    [Db]      
   [B]     [ 1.000000000000000   1.772034373903893  -0.000211153981059 ]    [Dr]

      理论上 YDbDr和RGB之间的转换时完全无损可逆的。不过如果YDbDr采用byte类型表达会有一定的精度损失。

      附上最终的代码供大家参考:

sealed unsafe class RGBYDbDr    {        //const float YDbDrYRF = 0.299F;              // RGB转YDbDr的系数(浮点类型)        //const float YDbDrYGF = 0.587F;        //const float YDbDrYBF = 0.114F;        //const float YDbDrDbRF = -0.450F;        //const float YDbDrDbGF = -0.883F;        //const float YDbDrDbBF = 1.333F;        //const float YDbDrDrRF = -1.333F;        //const float YDbDrDrGF = 1.116F;        //const float YDbDrDrBF = 0.217F;        //const float RGBRYF = 1.00000F;            // YDbDr转RGB的系数(浮点类型)        //const float RGBRDbF = 0.000092303716148F;        //const float RGBRDrF = -0.525912630661865F;        //const float RGBGYF = 1.00000F;        //const float RGBGDbF = -0.129132898890509F;        //const float RGBGDrF = 0.267899328207599F;        //const float RGBBYF = 1.00000F;        //const float RGBBDbF = 0.664679059978955F;        //const float RGBBDrF = -0.000079202543533F;        const float YDbDrYRF = 0.299F;              // RGB转YDbDr的系数(浮点类型)        const float YDbDrYGF = 0.587F;        const float YDbDrYBF = 0.114F;        const float YDbDrDbRF = -0.1688F;        const float YDbDrDbGF = -0.3312F;        const float YDbDrDbBF = 0.5F;        const float YDbDrDrRF = -0.5F;        const float YDbDrDrGF = 0.4186F;        const float YDbDrDrBF = 0.0814F;        const float RGBRYF = 1.00000F;            // YDbDr转RGB的系数(浮点类型)        const float RGBRDbF = 0.0002460817072494899F;        const float RGBRDrF = -1.402083073344533F;        const float RGBGYF = 1.00000F;        const float RGBGDbF = -0.344268308442098F;        const float RGBGDrF = 0.714219609001458F;        const float RGBBYF = 1.00000F;        const float RGBBDbF = 1.772034373903893F;        const float RGBBDrF = 0.0002111539810593343F;        const int Shift = 20;        const int HalfShiftValue = 1 << (Shift - 1);        const int YDbDrYRI = (int)(YDbDrYRF * (1 << Shift) + 0.5);         // RGB转YDbDr的系数(整数类型)        const int YDbDrYGI = (int)(YDbDrYGF * (1 << Shift) + 0.5);        const int YDbDrYBI = (int)(YDbDrYBF * (1 << Shift) + 0.5);        const int YDbDrDbRI = (int)(YDbDrDbRF * (1 << Shift) + 0.5);        const int YDbDrDbGI = (int)(YDbDrDbGF * (1 << Shift) + 0.5);        const int YDbDrDbBI = (int)(YDbDrDbBF * (1 << Shift) + 0.5);        const int YDbDrDrRI = (int)(YDbDrDrRF * (1 << Shift) + 0.5);        const int YDbDrDrGI = (int)(YDbDrDrGF * (1 << Shift) + 0.5);        const int YDbDrDrBI = (int)(YDbDrDrBF * (1 << Shift) + 0.5);        const int RGBRYI = (int)(RGBRYF * (1 << Shift) + 0.5);              // YDbDr转RGB的系数(整数类型)        const int RGBRDbI = (int)(RGBRDbF * (1 << Shift) + 0.5);        const int RGBRDrI = (int)(RGBRDrF * (1 << Shift) + 0.5);        const int RGBGYI = (int)(RGBGYF * (1 << Shift) + 0.5);        const int RGBGDbI = (int)(RGBGDbF * (1 << Shift) + 0.5);        const int RGBGDrI = (int)(RGBGDrF * (1 << Shift) + 0.5);        const int RGBBYI = (int)(RGBBYF * (1 << Shift) + 0.5);        const int RGBBDbI = (int)(RGBBDbF * (1 << Shift) + 0.5);        const int RGBBDrI = (int)(RGBBDrF * (1 << Shift) + 0.5);public static void ToYDbDr(byte* From, byte* To, int Length = 1)        {            if (Length < 1) return;            byte* End = From + Length * 3;            int Red, Green, Blue;            while (From != End)            {                Blue = *From; Green = *(From + 1); Red = *(From + 2);                // 无需判断是否存在溢出,因为测试过整个RGB空间的所有颜色值,无颜色存在溢出                *To = (byte)((YDbDrYRI * Red + YDbDrYGI * Green + YDbDrYBI * Blue + HalfShiftValue) >> Shift);         // YDbDr和YUV的Y相同                *(To + 1) = (byte)(128 + ((YDbDrDbRI * Red + YDbDrDbGI * Green + YDbDrDbBI * Blue + HalfShiftValue) >> Shift));                     *(To + 2) = (byte)(128 + ((YDbDrDrRI * Red + YDbDrDrGI * Green + YDbDrDrBI * Blue + HalfShiftValue) >> Shift));                     From += 3;                To += 3;            }        }        public static void ToRGB(byte* From, byte* To, int Length = 1)        {            if (Length < 1) return;            byte* End = From + Length * 3;            int Red, Green, Blue;            int Y, Db, Dr;            while (From != End)            {                Y = *From; Db = *(From + 1) - 128; Dr = *(From + 2) - 128;                Red = Y + ((RGBRDbI * Db + RGBRDrI * Dr + HalfShiftValue) >> Shift);                Green = Y + ((RGBGDbI * Db + RGBGDrI * Dr + HalfShiftValue) >> Shift);                Blue = Y + ((RGBBDbI * Db + RGBBDrI * Dr + HalfShiftValue) >> Shift);                if (Red > 255) Red = 255; else if (Red < 0) Red = 0;                if (Green > 255) Green = 255; else if (Green < 0) Green = 0;                    if (Blue > 255) Blue = 255; else if (Blue < 0) Blue = 0;                *To = (byte)Blue;                                                             *(To + 1) = (byte)Green;                *(To + 2) = (byte)Red;                From += 3;                To += 3;            }        }    }

  由于有些转换系数很小,建议Shift 常数取值不得小于10,否则会有更多的损失。

     照例附上一些效果:

     原图:

    

    YDbDr综合效果图:

    

    Y通道图:

    

    Db通道:

    

    Dr通道:

    

转载于:https://www.cnblogs.com/Imageshop/archive/2013/02/15/2912907.html

你可能感兴趣的文章
订单的子单表格设置颜色
查看>>
Office365 Exchange Hybrid 番外篇 ADFS后端SQL群集(一)
查看>>
9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路...
查看>>
lvs fullnat部署手册(三)rs内核加载toa篇
查看>>
C++策略模式
查看>>
我的友情链接
查看>>
oracle表分区详解
查看>>
网络编程中常见结构体
查看>>
SSL/TLS原理详解
查看>>
Docker 自定义SSH服务镜像
查看>>
JavaScript强化教程 —— Cocos2d-JS自动JSB绑定规则修改
查看>>
configure: error: in `/root/httpd-2.2.11/srclib/apr': c
查看>>
CentOS7搭建Kubernetes-dashboard管理服务
查看>>
buildroot下查找外部编译器通过ext-toolchain-wrapper调用的参数
查看>>
MySQL Replication 主主配置详细说明
查看>>
Linux的任务调度
查看>>
在Android studio中添加jar包方法如下
查看>>
iframe 在ie下面总是弹出新窗口解决方法
查看>>
分享10款漂亮实用的CSS3按钮
查看>>
安装nginx 常见错误及 解决方法
查看>>