2013-09-30 69 views
10

我已在下面的代碼段:CIELAB色彩空間中座標的範圍是什麼?

public List<Tuple<double, double, double>> GetNormalizedPixels(Bitmap image) 
{ 
    System.Drawing.Imaging.BitmapData data = image.LockBits(
     new Rectangle(0, 0, image.Width, image.Height), 
     System.Drawing.Imaging.ImageLockMode.ReadOnly, 
     image.PixelFormat); 

    int pixelSize = Image.GetPixelFormatSize(image.PixelFormat)/8; 

    var result = new List<Tuple<double, double, double>>(); 

    unsafe 
    { 
     for (int y = 0; y < data.Height; ++y) 
     { 
      byte* row = (byte*)data.Scan0 + (y * data.Stride); 

      for (int x = 0; x < data.Width; ++x) 
      { 
       Color c = Color.FromArgb(
        row[x * pixelSize + 3], 
        row[x * pixelSize + 2], 
        row[x * pixelSize + 1], 
        row[x * pixelSize]); 

       // (*) 
       result.Add(Tuple.Create(
        1.0 * c.R/255, 
        1.0 * c.G/255, 
        1.0 * c.B/255); 
      } 
     } 
    } 

    image.UnlockBits(data); 

    return result; 
} 

關鍵片段(*)是這樣的:

result.Add(Tuple.Create(
    1.0 * c.R/255, 
    1.0 * c.G/255, 
    1.0 * c.B/255); 

這增加了它的組件縮放到範圍[0, 1]一個像素分類的進一步使用具有不同分類器的任務。其中一些需要將屬性像這樣歸一化,而另一些則不關心 - 因此該功能。

但是,我應該如何處理像RGB這樣的不同顏色空間中的像素,如L*a*b*?儘管RGB顏色空間中的所有座標的值落入範圍[0,256)L*a*b*顏色空間a*b*被認爲是無界的。

所以當改變片段(*)到:

Lab lab = c.ToLab(); 

result.Add(Tuple.Create(
    1.0 * lab.L/100, 
    1.0 * lab.A/?, 
    1.0 * lab.B/?); 

ToLab是一個擴展方法,實現並採用適當的算法從here

我應該怎麼放的問號?

+0

有趣的問題。注意答案取決於rgb選擇和參考白色。 BartoszKP提出的強力方法取決於這些因素,並且可能需要根據平臺重新運行。 – SeF

回答

21

在實踐中,所有可能的RGB顏色的數量是有限的,所以L*a*b*空間是有界的。用以下簡單程序很容易找到座標的範圍:

Color c; 

double maxL = double.MinValue; 
double maxA = double.MinValue; 
double maxB = double.MinValue; 
double minL = double.MaxValue; 
double minA = double.MaxValue; 
double minB = double.MaxValue; 

for (int r = 0; r < 256; ++r) 
    for (int g = 0; g < 256; ++g) 
     for (int b = 0; b < 256; ++b) 
     { 
      c = Color.FromArgb(r, g, b); 

      Lab lab = c.ToLab(); 

      maxL = Math.Max(maxL, lab.L); 
      maxA = Math.Max(maxA, lab.A); 
      maxB = Math.Max(maxB, lab.B); 
      minL = Math.Min(minL, lab.L); 
      minA = Math.Min(minA, lab.A); 
      minB = Math.Min(minB, lab.B); 
     } 

Console.WriteLine("maxL = " + maxL + ", maxA = " + maxA + ", maxB = " + maxB); 
Console.WriteLine("minL = " + minL + ", minA = " + minA + ", minB = " + minB); 

或使用任何其他語言的類似程序。

所以,CIELAB空間座標範圍如下:

L的[0,100]

甲在[-86.185,98254]

中的B [-107.863,94.482 ]

答案是:

Lab lab = c.ToLab(); 

result.Add(Tuple.Create(
    1.0 * lab.L/100, 
    1.0 * (lab.A + 86.185)/184.439, 
    1.0 * (lab.B + 107.863)/202.345); 
+4

定義RGB。 sRGB的? Adobe RGB? –

+0

@ColeJohnson非常有趣的一點。我認爲這適用於任何具體版本的RGB,但我不確定。這裏的上下文被定義爲GDI +,並且在任何其他語言中被定義爲該語言的圖形庫。 – BartoszKP

+0

FWIW CIELAB空間包括設計的'想象'顏色:http://en.wikipedia.org/wiki/Lab_color_space – theodox

8

通常,下面的值起作用,因爲它是共用顏色變換算法的標準輸出:

  • L *軸(明度)的範圍從0到100

  • a *和b * (顏色屬性)軸範圍從-128到+1212

更多信息可查詢here

0

如果Lab轉換代碼與實驗室顏色定義協議來實現(參見,例如Lab color space),則功能f(...),其被用於定義[4/29,1內Lab變化],thefore

L = 116 * f(y) - 16 is in [0,100] 
a = 500 * (f(x)-f(y)) is in [-500*25/29, 500*25/29] 
b = 200 * (f(y)-f(z)) is in [-200*25/29, 200*25/29] 

有些人(如在答辯bortizj)標準化這些值的範圍,其中一個字節變量可以保存。所以你必須分析代碼才能確定它產生的範圍。但是,Wiki中的公式會再次給出上述範圍。相同的範圍會給你code here

+0

感謝您的回答。 IIRC我使用的是你所指的EasyRGB網站的確切轉換算法(RGB - > XYZ - > LAB),結果是不同的 - 你確定你提供的值是正確的嗎? – BartoszKP