颜色距离并不是一个精确定义的概念。因此,这里有三种方法来衡量它:
1. 检查颜色的色调,忽略饱和度和亮度。
2. 仅在RGB空间中测量直接距离。
3. 以某种方式权衡色调、饱和度和亮度。
显然,您可能想要更改第三种测量中的魔术数字:色调在0-360之间,亮度和饱和度在0-1之间,因此使用这些数字,色调比饱和度和亮度重约3.6倍。
更新:我发布的原始解决方案包含几个错误:
1. 我使用的Linq未找到最接近的匹配,而是从下面最接近;这意味着有50%的机会偏差1。
2. 在某些地方,我使用了color.GetBrightness()方法。姑且这么说吧:这完全没用。例如:蓝色和黄色具有相同的值0.5!
3. 色调的值从0-360,但当然它们会循环!我完全错过了这一点。
我已经用更正后的代码替换了大部分原始答案:
这些现在是方法的新版本,每个方法都返回找到的最接近匹配的索引:
int closestColor1(List<Color> colors, Color target)
{
var hue1 = target.GetHue();
var diffs = colors.Select(n => getHueDistance(n.GetHue(), hue1));
var diffMin = diffs.Min(n => n);
return diffs.ToList().FindIndex(n => n == diffMin);
}
int closestColor2(List<Color> colors, Color target)
{
var colorDiffs = colors.Select(n => ColorDiff(n, target)).Min(n =>n);
return colors.FindIndex(n => ColorDiff(n, target) == colorDiffs);
}
int closestColor3(List<Color> colors, Color target)
{
float hue1 = target.GetHue();
var num1 = ColorNum(target);
var diffs = colors.Select(n => Math.Abs(ColorNum(n) - num1) +
getHueDistance(n.GetHue(), hue1) );
var diffMin = diffs.Min(x => x);
return diffs.ToList().FindIndex(n => n == diffMin);
}
一些辅助函数:
float getBrightness(Color c)
{ return (c.R * 0.299f + c.G * 0.587f + c.B *0.114f) / 256f;}
float getHueDistance(float hue1, float hue2)
{
float d = Math.Abs(hue1 - hue2); return d > 180 ? 360 - d : d; }
float ColorNum(Color c) { return c.GetSaturation() * factorSat +
getBrightness(c) * factorBri; }
int ColorDiff(Color c1, Color c2)
{ return (int ) Math.Sqrt((c1.R - c2.R) * (c1.R - c2.R)
+ (c1.G - c2.G) * (c1.G - c2.G)
+ (c1.B - c2.B) * (c1.B - c2.B)); }
这是我用于截屏文本的小助手:
Brush tBrush(Color c) {
return getBrightness(c) < 0.5 ? Brushes.White : Brushes.Black; }
我已经更新了截图,不仅显示了13种颜色,还显示了一些主要偏红的颜色进行测试;所有颜色都显示其色相、饱和度和亮度值。最后三个数字是三种方法的结果。
可以看到,对于明亮和非饱和颜色来说,简单距离方法在色相方面是相当误导的:最后一种颜色(象牙色)实际上是一种明亮和苍白的黄色!
在我看来,评估所有颜色属性的第三种方法是最好的。但你应该尝试调整评估数值!
最终它真的取决于你想要实现什么;如果像看起来那样,你只关心颜色的色相,那就简单地采用第一种方法!你可以像这样使用你的数组进行调用:
int indexInArray = closestColor1(clist.ToList(), someColor)
想要了解更多关于颜色差异的知识,请参考维基百科上的相关页面!
![颜色差异](https://istack.dev59.com/3aB2Z.webp)
Color[] clist = new Color[13];
clist[0] = Color.Blue;
clist[1] = Color.BlueViolet;
clist[2] = Color.Magenta;
clist[3] = Color.Purple;
clist[4] = Color.Red;
clist[5] = Color.Tomato;
clist[6] = Color.Orange;
clist[7] = Color.Yellow;
clist[8] = Color.YellowGreen;
clist[9] = Color.Green;
clist[10] = Color.SpringGreen;
clist[11] = Color.Cyan;
clist[12] = Color.Ivory;
List<Color> targets = new List<Color>();
targets.Add(Color.Pink);
targets.Add(Color.OrangeRed);
targets.Add(Color.LightPink);
targets.Add(Color.DarkSalmon);
targets.Add(Color.LightCoral);
targets.Add(Color.DarkRed);
targets.Add(Color.IndianRed);
targets.Add(Color.LavenderBlush);
targets.Add(Color.Lavender);
(255,0,255)
和(0, 255, 255)
中哪一个更接近白色呢? - Sayse