從RGB到Lab色彩空間的轉換

從RGB到Lab色彩空間的轉換

最近在看關於控件變換的一些內容,下面這個值得參考L
====================================================================================
雖然若干年前就看過了關於色彩空間的介紹,但是直到今天才自己動手寫代碼做這件事情。雖然網絡上已經有很多現成的例子,但是一則僅僅適用於浮點型的數據,另一方面,在實現上也有一些尚可優化之處。

色彩模型除了最常見的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算法而找遍網絡皆不得,萬不得已只好自力更生。其間雖費時一日,幸好也算略有所得。暫記於此,以利後人。其間或許難免錯漏之處,還望達人不吝指點。

裝載地址:http://hao.qinz.net/comments.php?y=08&m=07&entry=entry080727-033517
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章