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

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


person BartoszKP    schedule 30.09.2013    source источник
comment
Интересный вопрос. Имейте в виду, что ответ зависит от выбора RGB и эталонного белого. Подход грубой силы, предложенный BartoszKP, зависит от этих факторов и может потребовать повторного запуска в зависимости от платформы.   -  person SeF    schedule 22.01.2017


Ответы (3)


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

A in [-86.185, 98.254]

B in [-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);
person BartoszKP    schedule 30.09.2013
comment
Дайте определение RGB. sRGB? Адоб RGB? - person Cole Johnson; 06.10.2013
comment
@ColeJohnson Очень интересный момент. Я бы сказал, что это работает для любой конкретной версии RGB, но я не уверен. Здесь контекст определяется как GDI+, а на любом другом языке — как графическая библиотека этого языка. - person BartoszKP; 06.10.2013
comment
FWIW Пространство CIELAB включает «воображаемые» цвета по дизайну: en.wikipedia.org/wiki/Lab_color_space - person theodox; 18.10.2013
comment
Я просто хотел добавить, что, возможно, использование maxA.ToString(R) вместо maxA даст вам более подробный (хотя, возможно, и не более точный) результат. Имея небольшой опыт работы с цветами Lab* (используя .NET), я обнаружил, что переключение между значениями RGB-›Lab*-›RGB не работает. всегда работают из-за ошибок вычисления с плавающей запятой. Мой код выдает значения за пределами диапазона, поэтому мне пришлось немного изменить значения матрицы с сайта easyrgb.com. Мои результаты оказались такими: L в [0, 100] A в [-86.188001161251748, 98.249414905267] B в [-107.85362559736171, 94.487327241851375] - person skataben; 15.05.2014
comment
Почему в большинстве ответов используются разные границы? Например, Adobe использует -128-127 для A и B, здесь это 184, а в других местах, как я заметил, они различаются. Это как-то связано с цветовыми профилями или это особая форма LAB? - person ; 25.01.2017
comment
Adobe реализует множество вещей странным образом, чтобы немного повысить производительность, поэтому они, вероятно, выбрали от -128 до 127, потому что это диапазон знаков со знаком в c/c++ - person nemesit; 29.01.2017
comment
Я подозреваю, что приведенные выше границы Lab* связаны с числовыми эффектами. При использовании чисел с плавающей запятой диапазон значений a* и b*, вероятно, составляет от -100,0 до 100,0, тогда как диапазон L* должен быть от 0 до 100,0. Обратите внимание, что Lab* — это теоретическое цветовое пространство, которое не может быть создано ни одним практическим устройством. При представлении Lab* в виде 24-битных целых чисел для каждого компонента используется 8 бит, поэтому L* составляет от 0 до 255, a* и b* оба равны от -128 до 127. - person U. Windl; 07.03.2019

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

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

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

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

person bortizj    schedule 27.04.2015

Если код преобразования Lab реализован в соответствии с определением цветов Lab (см., например, цветовое пространство Lab), то функция 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 дадут вам диапазон выше. Тот же диапазон даст вам код здесь

person John Smith    schedule 21.04.2016
comment
Спасибо за Ваш ответ. IIRC Я использовал точные алгоритмы преобразования с веб-сайта EasyRGB, на который вы ссылаетесь (RGB -> XYZ -> LAB), и результат отличается - вы уверены, что предоставленные вами значения верны? - person BartoszKP; 21.04.2016
comment
Я думаю, что ваш вывод о диапазонах a * и b * неверен: коэффициенты 200 и 500 просто отражают разницу в цветовом разрешении человека относительно сине-желтого и красно-зеленого. - person U. Windl; 07.03.2019