web-dev-qa-db-ja.com

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]にスケーリングされたピクセルを追加して、さまざまな分類子を使用した分類タスクでさらに使用されます。それらのいくつかは、属性をこのように正規化する必要がありますが、他の人は気にしません-したがって、この関数。

ただし、L*a*b*のようにRGBとは異なる色空間でピクセルを分類したい場合は、どうすればよいですか? 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は拡張メソッドであり、 ここ から適切なアルゴリズムを使用して実装されます)

疑問符には何を付ければよいですか?

16
BartoszKP

実際には、可能なすべての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空間座標範囲は次のとおりです。

[0、100]のL

[-86.185、98.254]のA

[-107.863、94.482]のB

答えは次のとおりです。

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);
28
BartoszKP

通常、次の値は、一般的な色変換アルゴリズムの標準出力であるため、機能します。

  • L *軸(明度)の範囲は0〜100

  • a *およびb *(色属性)軸の範囲は-128〜 + 127

詳細については、 ここ を参照してください。

12
bortizj

Lab変換コードがLab-colors定義に従って実装されている場合(たとえば、 Lab color space を参照)、関数f(...)は、Lの定義に使用されます。 abは[4/29,1]内で変更されます。

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の数式は上記の範囲を示します。同じ範囲で ここにコード

1
John Smith