我有以下代码:
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}}是一种扩展方法,使用here)
中的适当算法实现我应该为问号添加什么?
答案 0 :(得分:25)
实际上,所有可能的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]
[ - 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);
答案 1 :(得分:11)
答案 2 :(得分:1)
如果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中的公式将为您提供上述范围。相同的范围将为您提供code here