1.原理
rgb無法直接轉換成lab,需要先轉換成xyz再轉換成lab,即:rgb——xyz——lab
因此轉換公式分兩部分:
(1)rgb轉xyz
假設r,g,b為畫素三個通道,取值範圍均為[0,255],轉換公式如下:
等同於如下公式:
x= var_r * 0.4124 + var_g * 0.3576 + var_b * 0.1805
y= var_r * 0.2126 + var_g * 0.7152 + var_b * 0.0722
z= var_r * 0.0193 + var_g * 0.1192 + var_b * 0.9505
上面的gamma函式,是用來對圖象進行非線性色調編輯的,目的是提高影象對比度。這個函式不是唯一的,但是我在網上查到的基本都使用上式。
(2)xyz轉lab
上面兩個公式中,l*,a*,b*是最終的lab色彩空間三個通道的值。x,y,z是rgb轉xyz後計算出來的值,xn,yn,zn一般預設是95.047,100.0,108.883。
2.**實現
inline float gamma(floatx);上面是完全按照轉換演算法做的無優化的實現,裡面涉及了大量的浮點運算,在pc上可能沒什麼問題,但是如果是在android作業系統的移動端上,即使利用jni,把轉換演算法寫成c++版本進行加速,速度也不理想,因為這個操作時逐畫素的,每個畫素做幾十次浮點運算,耗時還是十分巨大的。void rgbtolab(unsigned char*rgbimg,float*labimg)
(2)犧牲一些精度的快速實現
首先可以把gamma函式去掉,因為經過我的測試,這個函式帶來的影響很小。
其次,m矩陣中的值都為小數,可以通過放大變成整數,接下來的計算就可以變成整數計算(在手機上浮點計算一般耗時是整形計算的幾倍)。在這裡,可以把m矩陣的值都擴大2^20倍變為整數,在計算得到x,y,z分量時再縮小回來。但是,xyz的小數部分會消失,會引入誤差,而在公式(5)(6)中(尤其是(6),涉及到指數運算和閾值運算,之前xyz的誤差在這裡會被放大),這種誤差還會繼續傳遞給最終的l,a,b值。那怎麼才能保證一定的準確率呢?
在這裡我的方法是引入了乙個查表機制。過程如下:
a.在計算xyz的時候,引數擴大2^20倍,但最後縮小時只縮小2^18,這樣計算出來的xyz值範圍是[0,1023]
b.建立乙個table,用於將取值為[0,1023]的xyz通過f(t)函式對映到中間結果,記為:labtable(m)
c.將labtable(m)代入公式(5)計算最終的lab分量值
**如下:
const建立labtable的**如下:static
int big_shift=18
;const
static
int halfshiftvalue=512
;const
static
int shift=10
;const
static
int offset=128
<
const
static
int scalelc = (16 * (1
<
const
static
int scalelt = 116
;const
static
int scaley= 903
;const
static
int para1=500
;const
static
int para2=200
;const static int thpara=9;
void rgbtolab(unsigned char*rgbimg,int*labimg)
int labtable[1024];for (int i = 0; i < 1024; i++)
RGB轉LAB色彩空間
1.原理 rgb無法直接轉換成lab,需要先轉換成xyz再轉換成lab,即 rgb xyz lab 因此轉換公式分兩部分 1 rgb轉xyz 假設r,g,b為畫素三個通道,取值範圍均為 0,255 轉換公式如下 等同於如下公式 x var r 0.4124 var g 0.3576 var b 0....
RGB轉LAB色彩空間
1.原理 rgb無法直接轉換成lab,需要先轉換成xyz再轉換成lab,即 rgb xyz lab 因此轉換公式分兩部分 1 rgb轉xyz 假設r,g,b為畫素三個通道,取值範圍均為 0,255 轉換公式如下 0.4124,0.3576,0.1805 0.2126,0.7152,0.0722 0....
RGB轉LAB色彩空間
1.原理 rgb無法直接轉換成lab,需要先轉換成xyz再轉換成lab,即 rgb xyz lab 因此轉換公式分兩部分 1 rgb轉xyz 假設r,g,b為畫素三個通道,取值範圍均為 0,255 轉換公式如下 等同於如下公式 x var r 0.4124 var g 0.3576 var b 0....