颜色空间系列4: RGB和YDbDr颜色空间的转换及优化算法

来源:互联网 发布:大数据相关期刊 编辑:程序博客网 时间:2024/05/16 14:11

  颜色空间系列代码下载链接:http://files.cnblogs.com/Imageshop/ImageInfo.rar (同文章同步更新)

    YDbDr颜色空间和YCbCr颜色空间类似,其和RGB空间之间的相互转换公式里取http://en.wikipedia.org/wiki/YDbDr 所描述的。

     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通道:

    

分类: [09] 图像颜色空间,[03] 图像算法优化
标签: RGB, YDbDr, 颜色空间。
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 噜噜看 噜噜噜噜 狠狠生噜噜噜 噜噜吧 免费看 日日 拍拍 妈妈打什么意思 打孩子要多少钱啊 10195558打过来 须要打 打哦 打关 啊打 多打 打啊 啊杜 桐梓特产 梓墨这个名字的寓意 东山梓园青年旅舍 苗芳梓颜 坑梓二手房 季梓潼宴北辰免费阅读 深圳坑梓花店 我有药啊衣落成火 啊火六间房 我也不想火啊 xary 啊哲骂天佑很火的一段话 火币 火的 啊西吧什么意思 啊西巴什么意思 啊西洛韦乳膏 啊西巴是什么意思 达文西啊 西巴 啖怎么读