2013-06-19 76 views
1

我們已經在API中讀取3D Lut(Nuke格式)文件,並將轉換應用於圖像中的高度優化的類。因此,如果我使用複雜公式將RGB值轉換爲Lab(RGB-> XYZ-> Lab)值,我認爲如果我爲RGB生成一個查找表(或者XYZ到LAB)變換。這可能嗎?爲sRGB生成3DLUT(.3dl文件)以CIELAB色彩空間轉換

我明白3D Lut是如何處理從RGB到RGB的轉換的,但我對RGB與Lab感到困惑,因爲L,a和b有不同的範圍。任何提示?

編輯:

能否請你解釋一下我甩將如何工作? 繼承人一個解釋:link

例如,下面是我的3D LUT的RGB-> RGB轉換的理解: 樣本核彈3DL甩文件:

0 64 128 192 256 320 384 448 512 576 640 704 768 832 896 960 1023 
R, G, B 
0, 0, 0 
0, 0, 64 
0, 0, 128 
0, 0, 192 
0, 0, 256 
. 
. 
. 
0, 64, 0 
0, 64, 64 
0, 64, 128 
. 
. 

這裏,而不是產生一個1024 * 1024 * 1024表的源10位RGB值,每個R,G和B範圍量化爲17個值,生成4913行表。 第一行給出了可能的量化值(我認爲這裏只是長度和最大值的問題)。現在假設,如果源RGB值是(20,20,190),則輸出將是行#4(0,0,192)(使用一些內插技術)。那是對的嗎? 這是一個10位的源代碼,你可以通過改變範圍從0到255來產生一個8位的相似的?

同樣,你將如何繼續進行sRGB-> Lab轉換?

+0

*源色彩空間*中的離散值是可能的(例如,每個通道8位是合適的,> =每個通道16位導致一個令人難以置信的大表)。 *目標色彩空間*可以像您想要的那樣精確(它只決定*您在表格單元格中寫入多少*,而不是*表格的大小) – leemes

+0

可選:GPGPU(可能使用CUDA,OpenCL或GLSL) – leemes

+0

您不必量化*輸出*。你甚至可以爲你的實驗室儲存三個浮標;它只會使表格線性增大。然而,如果你比較8位的RGB到16位的RGB,你的表格有1600萬對2.8e14的條目(我甚至不知道這個數字的名字......)所以,如果你保持*輸入信號*量化少量的位(即每個通道RGB 8位24位),生成和使用表格是合適的(請參閱我的答案)。 – leemes

回答

0

假設你的源色彩空間是字節的三重峯(RGB,每個8位)和兩個顏色空間被存儲在結構分別與名稱SourceColorTargetColor,你有這樣給出的變換函數:

TargetColor convert(SourceColor color) { 
    return ... 
} 

然後你就可以創建一個表是這樣的:

TargetColor table[256][256][256]; // 16M * sizeof(TargetColor) => put on heap! 

for (int r, r < 256; ++r) 
    for (int g, g < 256; ++g) 
    for (int b, b < 256; ++b) 
     table[r][g][b] = convert({r, g, b}); // (construct SourceColor from r,g,b) 

然後,對於實際的圖像轉換,使用替代轉換功能(我建議你寫一個圖像轉換類,這需要FUNC重刑指針/ std::function在其構造,所以它很容易更換):

TargetColor convertUsingTable(SourceColor source) { 
    return table[source.r][source.g][source.b]; 
} 

注意,空間消耗16M * sizeof(TargetColor)(假設32位的Lab這將是64MBytes),所以表應該是堆分配(它可以存儲在課堂上,如果你的班級要在堆上生活,但更好地在構造函數中使用new[]進行分配並將其存儲在智能指針中)。

+0

所以,這對於L * a * b *如何工作,因爲TargetColor組件具有不同的範圍。 –

+0

我看不出有什麼問題......你如何存儲Lab值?只需在我的代碼中替換這個類型,就完成了...假設你的Lab類型被稱爲'Lab',你的RGB類型被稱爲'RGB',那麼表變量是'Lab table [256] [256] [ 256]'和函數'Lab convert(RGB color)' – leemes

1

另一種方法是利用圖形硬件,即「通用GPU計算」。爲此有一些不同的工具,例如OpenGL GLSL,OpenCL,CUDA ......與CPU解決方案相比,您應該獲得大約100倍以上的驚人加速。

最「兼容」的解決方案是使用OpenGL與特殊的片段着色器,您可以使用它執行計算。這意味着:將您的輸入圖像作爲紋理上傳到GPU,使用專門的着色​​器程序將其渲染到(目標)幀緩衝區中,該程序將RGB數據轉換爲Lab(或者也可以使用查找表,但大多數浮點計算在GPU上比表/紋理查找更快,所以我們不會在這裏做到這一點)。

首先,將您的RGB到Lab轉換函數移植到GLSL。它應該處理浮點數,所以如果您在原始轉換中使用了整數值,請將其除去。 OpenGL使用「鉗位」值,即在0.01.0之間的浮點值。它看起來像這樣:

vec3 rgbToLab(vec3 rgb) { 
    vec3 lab = ...; 
    return lab; 
} 

然後,寫着色器,其將獲取的(RGB)的紋理的像素的其餘部分,將調用轉換功能和在彩色輸出變量寫入像素(唐」忘記alpha通道):

uniform sampler2D texture; 
varying vec2 texCoord; 

void main() { 
    vec3 rgb = texture2D(texture, texCoord).rgb; 
    gl_FragColor = vec4(lab, 1.0); 
} 

相應的頂點着色器應在目標四邊形填充整個屏幕(幀緩衝器)的右上角寫入的(0,0)texCoord值在左下方和(1,1)

最後,在您的應用程序中使用此着色器程序,方法是在與圖像大小相同的幀緩衝區上進行渲染。渲染一個填充整個區域的四邊形(沒有設置任何變換,只需渲染四維從2D頂點(-1,-1)(1,1))。將統一值texture設置爲您作爲紋理上傳的RGB圖像。然後,從設備中讀回幀緩衝器,它應該在Lab色彩空間中包含您的圖像。

+0

我想我會堅持到現在好的CPU'我寫了一個圖像變換類,它使用3x3矩陣進行色彩空間變換。我已經使用了OpenMP,這足以滿足我的需求。但是,您無法使用矩陣近似RGB - > L * a * b *。因此查找表。但這聽起來很棒。 –