Каковы диапазоны координат в цветовом пространстве 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
это метод расширения, реализованный с использованием соответствующих алгоритмов здесь)
что я должен поставить для вопросительных знаков?
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 в [0, 100]
А в [-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);
Обычно следующие значения работают, потому что это стандартный вывод общих алгоритмов преобразования цветов:
Ось L* (легкость) колеблется от 0 до 100
Диапазон значений оси a* и b* (атрибуты цвета) от -128 до +127
Более подробную информацию можно найти здесь.
Если код преобразования Lab реализован в соответствии с определением Lab-colors (см., Например, цветовое пространство 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 в своем ответе) нормализуют эти значения в диапазоне, который может содержать байтовая переменная. Таким образом, вы должны проанализировать код, чтобы определить, какой диапазон он производит. Но опять же, формулы в вики дадут вам диапазон выше. Тот же диапазон даст вам код здесь