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

色彩模型除了最常见的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. javascript每日一练(四)——DOM二

    一.DOM的创建,插入,删除 createElement(标签名) appendChild(节点) insertBefore(节点,原有节点) removeChild(节点) <!doctype ...

  2. Python 获取时间戳

    Python 获取时间通过 time 模块 如下代码,是通过获取当前的时间,按照格式输出 Python默认获取当前的时间返回的都是时间的元组,下面是元组的,字符串时间的一个转换输出 # -*- cod ...

  3. Ch06 验证

    6.1  服务器端验证 6.1.1  Data Annotations验证 6.1.2  扩展ModelMetadtaProvider 6.2  客户端验证 6.2.1  客户端验证初步 6.2.2  ...

  4. FMXUI - UI.Dialog 示例

    在 FMXUI 开源库,增加了 UI.Dialog 单元.此单元实现了跨平台的基础对话框组件.使用时引用 UI.Dialog 即可.如果需要自定义对话框的样式, 可以添加一个 TDialogStyle ...

  5. static在C和C++中的用法和区别

    static主要有三个作用: (1)局部静态变量 (2)外部静态变量/函数 (3)静态数据成员/成员函数 前两种C和C++都有,第三种仅在C++中有,下面分别作以下介绍: 一.局部静态变量 在C/C+ ...

  6. 基于visual Studio2013解决C语言竞赛题之1016循环打印矩阵

         题目 解决代码及点评 /* 找规律,编程序打印6×6的矩阵: 1 2 3 5 8 13 1 4 9 17 30 51 1 6 19 45 92 173 . . . */ ...

  7. 纯CSS设置Checkbox复选框控件的样式

    Checkbox复选框是一个可能每一个网站都在使用的HTML元素,但大多数人并不给它们设置样式,所以在绝大多数网站它们看起来是一样的.为什么不把你的网站中的Checkbox设置一个与众不同的样式,甚至 ...

  8. SRM 583 Div II Level Three:GameOnABoard,Dijkstra最短路径算法

    题目来源:http://community.topcoder.com/stat?c=problem_statement&pm=12556 用Dijkstra实现,之前用Floyd算法写了一个, ...

  9. (1)前言——(10)jquery项目的历史(History of the jQuery project)

    This book covers the functionality and syntax of jQuery 1.6.x, the latest version at the time of wri ...

  10. TensorFlow实现与优化深度神经网络

    TensorFlow实现与优化深度神经网络 转载请注明作者:梦里风林Github工程地址:https://github.com/ahangchen/GDLnotes欢迎star,有问题可以到Issue ...