【问题标题】:Add pale/vivid/light/dark before the color name depending on brightness and saturation根据亮度和饱和度在颜色名称前添加淡色/鲜艳/浅色/深色
【发布时间】:2017-04-26 11:49:08
【问题描述】:

我想得到最接近这个列表的颜色:

static List<Color> clist = new List<Color>()
    {
        Color.Black, Color.Brown, Color.Blue, Color.Green, Color.Red, Color.Yellow,
        Color.Gray, Color.Indigo, Color.Orange, Color.Pink, Color.Turquoise, Color.White
    };

我得到了最接近的颜色,但我想添加:苍白/深色/鲜艳/浅色,具体取决于颜色的亮度和饱和度:

        static string closestColor2(List<Color> colors, Color target)
        {
            var colorDiffs = colors.Select(n => ColorDiff(n, target)).Min(n => n);
            int x = colors.FindIndex(n => ColorDiff(n, target) == colorDiffs);
            return colors[x].ToString();
        }

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

【问题讨论】:

  • 您绝对必须计算 HSL 或 HSV 颜色空间中的距离(或者,如果您想获得真正的花哨,CIE 或 YUV 之类的)。如果您想获得有意义的结果,您不能使用 RGB 颜色空间。如果单独的色调还不够,也可以使用其他组件。分配给每个组件的相对权重取决于您。可能想要比其他人更重视亮度/价值。也许接下来是色调,最后是饱和度。
  • 还有哪些其他组件?我是色彩操作编程的新手……
  • 对于 HSL,组件将是色相、饱和度和亮度。就像 RGB 一样,分量是红色、绿色和蓝色。搜索“color distance c#”,前面有很多关于这个话题的讨论。

标签: c# colors


【解决方案1】:

在比较颜色时需要考虑很多事情。 但是这个问题已经回答了。

您可以在这里找到解决方案:

How to compare Color object and get closest Color in an Color[]?

【讨论】:

  • 据我所知,您已经有代码可以找到最接近的颜色,但不是返回像 Color.Cyan 这样的值,而是像“浅绿色”这样的值?在 Color.* 中有 141 种颜色,因为颜色不会改变,我想我会浏览所有这些颜色的列表并手动设置每种颜色的名称。然后,您可以设置任何您认为合适的名称并使用它来代替设置名称。我认为很难做出一个好的解决方案,如果您自己设置名称,您将完全按照您的意愿得到它们。
  • 我在想一些可以计算亮度的东西,然后根据它要么把黑暗变得生动等等?
  • Color.GetBrightness() - msdn.microsoft.com/en-us/library/…
  • 嗯,我在和@FSDaniel 交谈。甚至不确定,但我猜你也可以这样做:点击关闭并选择重复.. - 至于你的问题,你可能想研究this post..
  • See here 但请注意我之前已经给过你那个链接了..
【解决方案2】:

我找到了这段代码:

    string ColorName(Color c)
{
    List<float> hues = new List<float>()
    { 0, 15, 35, 44, 54, 63, 80, 160, 180, 200, 244, 280, 350, 360};
    List<string> hueNames = new List<string>()
        { "red", "orange-red", "orange", "yellow-orange", "yellow",
          "yellow-green",   "green"  , "blue-green" , "cyan", "blue", 
          "violet", "purple", "red" };

    float h = c.GetHue();
    float s = c.GetSaturation();
    float b = (c.R * 0.299f + c.G * 0.587f + c.B *0.114f) / 256f;

    string name = s < 0.35f ? "pale " : s > 0.8f ? "vivid " : "";
    name += b < 0.35f ? "dark " : b > 0.8f ? "light " : "";
    for (int i = 0; i < hues.Count - 1; i++)
        if (h >= hues[i] && h <= hues[i+1] )
        {
            name += hueNames[i];
            break;
        }
    return name;
}

Here

我尝试将它实现到您的代码中,如下所示:

static string 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);
        var x = diffs.ToList().FindIndex(n => n == diffMin);

        Color c = colors[x];

        float h = c.GetHue();
        float s = c.GetSaturation();
        float b = (c.R * 0.299f + c.G * 0.587f + c.B * 0.114f) / 256f;

        string name = s < 0.35f ? "pale " : s > 0.8f ? "vivid " : "";
        name += b < 0.35f ? "dark " : b > 0.8f ? "light " : "";

        name += colors[x].ToString();

        return name;
    }

但有些解决方案有时会同时显示两者,例如:“淡深红色”/“淡深蓝色”等。这真的很令人困惑..而您只想显示其中之一...您应该尝试类似的东西..还是想想怎么只放1个..

【讨论】:

    【解决方案3】:

    我的建议是首先列出颜色。在您的答案中,您有一小部分颜色,但如果您以后愿意,您也可以添加所有 141 种颜色。

    所以创建一个颜色列表:

        //List of Colors
        static List<Color> clist = new List<Color>{
            Color.Black, Color.Brown, Color.Blue, Color.LightSteelBlue, Color.Green, Color.Red, Color.Yellow,
            Color.Gray, Color.Indigo, Color.Orange, Color.Pink, Color.Turquoise, Color.White
        };
    

    然后是另一个列表,其中包含您想要的颜色名称,包括“鲜艳”、“深色”等。

        //List of Color Names
        static List<string> cnlist = new List<string>{
            "Black", "Brown", "Blue", "Pale Light Blue", "Green", "Red", "Yellow",
            "Gray", "Indigo", "Orange", "Pink", "Turquoise", "White"
        };
    

    您可以使用这些方法找到最接近的颜色:

        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);
        }
    
    
        // distance in RGB space
        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));
        }
    

    上述方法将返回列表中最接近颜色的索引,然后您可以使用相同的索引并从颜色名称列表中获取您指定的名称。这样您就可以在每种颜色上准确地使用您想要的名称,并且不需要依赖不是 100% 的算法,并且由于颜色很少,因此只需要很少的时间来编写名称,正如您所提到的会按照您的意愿得到它们。

    如果要添加 Color.* 中存在的所有颜色,可以使用此方法获取它们:

    private List<Color> GetAllColors() {
            var list = new List<Color>();
            var colorType = typeof(Color);
            var propInfos = colorType.GetProperties(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public);
            foreach (var propInfo in propInfos) {
                var color = Color.FromName(propInfo.Name);
                list.Add(color);
            }
            return list;
        }
    

    【讨论】:

    • 如果我想添加自定义 RGB,我该怎么做?
    猜你喜欢
    • 2023-03-25
    • 2012-01-31
    • 2016-09-25
    • 1970-01-01
    • 2014-07-06
    • 2020-10-29
    • 2018-03-22
    • 1970-01-01
    • 2018-04-01
    相关资源
    最近更新 更多