虽然若干年前就看过了关于色彩空间的介绍,但是直到今天才自己动手写代码做这件事情。虽然网络上已经有很多现成的例子,但是一则仅仅适用于浮点型的数据,另一方面,在实现上也有一些尚可优化之处。

色彩模型除了最常见的RGB以外,还有HSB、YCbCr、XYZ、Lab等。HSB一般仅仅作为图像处理过程中的临时模式,YCbCr常常用于图像的压缩处理,而XYZ则严格按照人眼对光信号的敏感度进行分布。

这里将要稍作讨论的便是Lab模型。网络上诸多的介绍都说Lab是基于XYZ的,故人们一般也只能找到XYZ和Lab之间的转换,而RGB到Lab的转换只能使用XYZ作为中间模式间接进行。可惜的是,这种现状源于误解。而在图像处理软件中(比如Photoshop),往往采用一个更为简单的算法。

我们可以先观察RGB到XYZ的转换:

[X,Y,Z] = [M] * [R,G,B]

其中M为一3x3矩阵:
[M] = [0.4125, 0.3576, 0.1805;
0.2126, 0.7152, 0.0722;
0.0193, 0.1192, 0.9505],

RGB是经过Gamma校正的色彩分量:R=g(r),G=g(g),B=g(b)。
其中rgb为原始的色彩分量。

g是Gamma校正函数:
当 x < 0.018 时,g(x) = 4.5318 * x
当 x >= 0.018 时,g(x) = 1.099 * d^0.45 - 0.099

rgb以及RGB的取值范围则均为[0,1)。计算完成后,XYZ的取值范围则有所变化,分别是:[0, 0.9506),[0, 1),[0, 1.0890)。

以及XYZ到Lab的转换:

L = 116 * f(Y1) - 16
a = 500 * (f(X1) - f(Y1))
b = 200 * (f(Y1) - f(Z1))

其中f是一个类似Gamma函数的校正函数:
当 x > 0.008856 时,f(x) = x^(1/3)
当 x <= 0.008856 时,f(x) = ( 7.787 * x ) + ( 16 / 116 )
X1、Y1、Z1分别是线性归一化之后的XYZ值,也就是说,它们的取值范围都是[0, 1)。此外,函数f的值域也和自变量一样都是[0, 1)。

计算完成后,L的取值范围[0, 100),而a和b则约为[-169, +169)和[-160, +160)。

在观察这些貌似复杂的变换之前,我们必须确定的一个假设是:在图像处理软件中,非RGB色彩数据的绝对值并不重要,重要的是他们能够尽可能准确的还原成RGB图像以显示在屏幕等相关设备上。这个假设是我们的简化得以成立的理由。

上面的从XYZ到Lab的转换乍一看起来很奇怪,但若是仔细观察,不难发现L与Y1只是一个简单的同区间映射关系,这个映射其实可有可无(如果进行了映射反而必定导致色阶丢失)。

这样,我们取得的第一个简化是:L = Y1。

接下来接着看a和b的映射过程。大家不难发现,a和b其实是一个色差信号(跟Cb和Cr的性质差不多)。至于它们的转换系数500和200,大家可以完全忘记,因为他们的值域并不符合8位整数值的表达需要。我们将会稍后计算出合适的因数,使得a和b都处在[0, 255]的范围内。

因为XYZ必须归一化转为X1Y1Z1,那么我们其实可以在转换矩阵M中作出这个修改,令每行乘以一个系数以使得每行各数之和为1:
[M1] = [0.4339, 0.3762 0.1899;
0.2126, 0.7152, 0.0722;
0.0177, 0.1095, 0.8728]

于是乎,我们得出一个半成品:
L = Y1 = 0.2126 * R + 0.7152 * G + 0.0722 * B
a = Fa * (X1 - Y1) + Da
b = Fb * (Y1 - Z1) + Db
其中的Fx是调整值域用的系数,Dx是一个正数,用来消除a和b的负值。Fx和Dx的选取必须令a和b满足值域在[0, 255]上的分布。

接下来我们来确定Fx和Dx的值。通过M1我们很容易计算出X1-Y1的值域(极端情况)为[-86.784, +86.784),而Y1-Z1的值域则为[-204.9536, +204.9536)。于是乎,Fa的值为1.4749,Fb的值为0.6245;Da和Db则都是128。

这时,代入M1有:
L = Y1 = 0.2126 * R + 0.7152 * G + 0.0722 * B
a = 1.4749 * (0.2213 * R - 0.3390 * G + 0.1177 * B) + 128
b = 0.6245 * (0.1949 * R + 0.6057 * G - 0.8006 * B) + 128
其中RGB和Lab的取值范围都是[0,255]。

最后的一点工作是算法的优化。我们可以将这个方程组转换成常整数乘法与移位的方式(相当于使用定点数)。为了方便阅读,我仍然将移位写为除法。

所以我们的最终结果为:

L = Y1 = (13933 * R + 46871 * G + 4732 * B) div 2^16
a = 377 * (14503 * R - 22218 * G + 7714 * B) div 2^24 + 128
b = 160 * (12773 * R + 39695 * G - 52468 * B) div 2^24 + 128

至于逆变换则可以用类似的方法推导出来:

设L1=L,a1=(a-128)*174,b1=(b-128)*410,有:
R = L1 + (a1 * 100922 + b1 * 17790) div 2^23
G = L1 - (a1 * 30176 + b1 * 1481) div 2^23
B = L1 + (a1 * 1740 - b1 * 37719) div 2^23
其中RGB和Lab的取值范围都是[0,255],再经过逆Gamma函数取得原始的rgb

以上的算法在Delphi中编译通过。经测试,运算得出的直方图与图片观感和我手头的Photoshop CS的结果非常相似,但也有一些幅度上的差别,且容以后慢慢细察。

当初为了寻觅一个简单的RGB直接转Lab算法而找遍网络皆不得,万不得已只好自力更生。其间虽费时一日,幸好也算略有所得。暂记于此,以利后人。其间或许难免错漏之处,还望达人不吝指点。

经转换后得到

///////////////////////////////////////////////////////////////////////////////////////////
//L = Y1 = (13933 * R + 46871 * G + 4732 * B) div 2^16
//a = 377 * (14503 * R - 22218 * G + 7714 * B) div 2^24 + 128
//b = 160 * (12773 * R + 39695 * G - 52468 * B) div 2^24 + 128
void RGB2Lab2(double R, double G, double B, double &L, double &a, double &b)
{
      L = 0.2126007 * R + 0.7151947 * G + 0.0722046 * B;
      a = 0.3258962 * R - 0.4992596 * G + 0.1733409 * B + 128;
      b = 0.1218128 * R + 0.3785610 * G - 0.5003738 * B + 128;
}

//R = L1 + (a1 * 100922 + b1 * 17790) div 2^23
//G = L1 - (a1 * 30176 + b1 * 1481) div 2^23
//B = L1 + (a1 * 1740 - b1 * 37719) div 2^23
void Lab2RGB2(double L, double a, double b, double &R, double &G, double &B)
{
      R = L + 0.0120308 * a + 0.0021207 * b;
      G = L - 0.0035973 * a - 0.0001765 * b;
      B = L + 0.0002074 * a - 0.0044965 * b;
}
///////////////////////////////////////////////////////////////////////////////////////////

RGB转为Lab空间的更多相关文章

  1. RGB转LAB色彩空间

    1.原理 RGB无法直接转换成LAB,需要先转换成XYZ再转换成LAB,即:RGB——XYZ——LAB 因此转换公式分两部分: (1)RGB转XYZ 假设r,g,b为像素三个通道,取值范围均为[0,2 ...

  2. QT 实现彩色图亮度均衡,RGB和HSI空间互相转换

    从昨天折腾到今天.再折腾下去我都要上主楼了  大致和灰度图均衡是一样的,主要是不能像平滑什么的直接对R,G,B三个分量进行.这样出来的图像时没法看的.因此我们要对亮度进行均衡.而HSI彩色空间中的分量 ...

  3. python opencv 利用Lab空间把春天的场景改为秋天

    前一段时间实现了Reinhard颜色迁移算法,感觉挺有意思的,然后在代码上随意做了一些更改,有了一些发现,把Lab通道的a通道值改为127左右,可以将绿色改为黄色,而对其他颜色的改动非常小,因此可以将 ...

  4. WPF将RGB转为HSL的工具类

    class HSLColor     {         private int _alpha = 255;         public int _hue = 0;         public d ...

  5. 让你的软件飞起来:RGB转为YUV【转】

    转自:http://blog.csdn.net/wxzking/article/details/5905195 版权声明:本文为博主原创文章,未经博主允许不得转载. 朋友曾经给我推荐了一个有关代码优化 ...

  6. Color Transfer between Images code实现

    上计算机视觉课老师布置的作业实现论文:Color Transfer between Images 基本思路是: 1.给定srcImg和targetImg 2.将RGB空间转为Lab空间 3.根据论文中 ...

  7. 行人检測之HOG特征(Histograms of Oriented Gradients)

    之前的文章行人计数.计次提到HOG特征这个概念,这两天看了一下原版的论文,了解了一下HOG特征的原理,并依据自己的理解将这种方法的流程写了下来,假设有不正确的地方欢迎指正. HOG(Histogram ...

  8. 目标检测之hog(梯度方向直方图)---hog简介0

    梯度直方图特征(HOG) 是一种对图像局部重叠区域的密集型描述符, 它通过计算局部区域的梯度方向直方图来构成特征.Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功 ...

  9. 色彩空间RGB/CMYK/HSL/HSB/HSV/Lab/YUV基础理论及转换方法:RGB与YUV

    之前做个设计,现在从事IT,脑子里面关于RGB,RGBA,CMY,CMYK,YUV,但是具体理论还是不扎实.若干年前之前写过<水煮RGB与CMYK色彩模型—色彩与光学相关物理理论浅叙>&l ...

随机推荐

  1. 【Unity 3D】使用 2DToolkit 插件 制作2D精灵动画

    话说博客传图也太麻烦了吧,一个一个文件一个一个传....为什么不能直接粘贴了,自动上传呢... 刚直接粘贴了,结果一张图没有,又重新截一次图,在传了一次...真是太**了 好了,吐槽完了,开始博客吧 ...

  2. MVC与WebForm的简单的比较

    MVC与WebForm的简单的比较 ASP 强制程序员将业务逻辑和展示页放到一个文件中 WebForm 允许程序员将业务逻辑与页面展示分开到不同的文件中,并且提供强大的开发平台来写  业务逻辑代码  ...

  3. PHP:根据IP地址获取所在城市

    文件目录: ipLocation -----qqwry ----------QQWry.Dat -----ipCity.class.php ipCity.class.php文件代码: <?php ...

  4. Java中Timer和TimerTask的使用

    转自:http://www.cdtarena.com/javapx/201306/8893.html java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks. 一个 ...

  5. jquery Deferred使用经验

    这周做了个小活动(http://aoqi.100bt.com/zt-2016duanzi/index.html),刚开始时候没看好需求,逻辑都写一块了 最后各种坑要填补,从中也获取了些经验和教训,下面 ...

  6. Troubleshooting:oVirt-engine

    问题:执行./create_db_devel.sh -u postgres创建数据库时出错 描述: [root@localhost dbscripts]# ./create_db_devel.sh - ...

  7. 瑞蓝RL-NDVM-A16网络视频解码器 视频上墙解决方案专家--数字视频解码矩阵

    瑞蓝网络数字视频解码矩阵(简称RL-NDVM)是依据第三代开放式网络视频监控系统的实际需求,专为视频上墙显示而研制的一款新型数字解码上墙设备.RL-NDVM解码矩阵是集解码器和HDMI/DVI/VGA ...

  8. Bee Framework_百度百科

    Bee Framework_百度百科 Bee Framework 编辑   目录 1详细信息 简介 特性 2工作 主要模块 编译要求 运行要求 目录结构 运行例程 安装步骤     1详细信息 简介 ...

  9. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: SELECT command denied to user 'xxxx'@''

    这两天项目一直在报这个错误消息: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: SELECT command denied to ...

  10. DOM querySelector选择器

    原生的强大DOM选择器querySelector 在传统的 JavaScript 开发中,查找 DOM 往往是开发人员遇到的第一个头疼的问题,原生的 JavaScript 所提供的 DOM 选择方法并 ...