Каковы диапазоны координат в цветовом пространстве 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- это метод расширения, реализованный с использованием соответствующих алгоритмов из здесь)

что я должен поставить для вопросительных знаков?

Ответ 1

На практике количество всех возможных цветов 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]

A в [-86.185, 98, 254]

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

Ответ 2

Как правило, следующие значения работают, потому что это стандартный вывод общих алгоритмов преобразования цветов:

  • Ось L * (легкость) колеблется от 0 до 100

  • a * и b * (цветовые атрибуты) диапазон остов от -128 до +127

Более подробную информацию можно найти здесь.

Ответ 3

Если код Lab-conversion реализован в соответствии с определением Lab-colors (см., например, Lab color space), затем выполните функцию f(...), который используется для определения L, a и b изменений внутри [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 дадут вам диапазон выше. Тот же диапазон даст вам здесь