【问题标题】:trying to convert rgb from a .net Color to a string such as "red" or "blue"尝试将 rgb 从 .net Color 转换为字符串,例如“red”或“blue”
【发布时间】:2010-09-26 19:51:16
【问题描述】:

我所有的方法都以各种方式失败了。 不同的灯光也会把事情搞砸。

有没有人试图返回一个给定 rgb 值的名称? “红色”“绿色”“蓝色”足以满足我今天的需求。

我对来自网络摄像头的图像进行了不安全的字节处理。

【问题讨论】:

  • 所以问题可以重新表述为给定的颜色和名称字典,对于给定的颜色找到最接近颜色的名称?

标签: c# .net image colors system.drawing.color


【解决方案1】:

如果您有一个带有名称的已知颜色列表,您可以使用沿着(F# 代码)行的“closeness”函数来查看给定目标颜色与哪些已知颜色“最接近”:

let Diff (c1:Color) (c2:Color) =
    let dr = (c1.R - c2.R) |> int
    let dg = (c1.G - c2.G) |> int
    let db = (c1.B - c2.B) |> int
    dr*dr + dg*dg + db*db

哪一种已知颜色与您要命名的目标颜色的差异最小,请使用该名称。

【讨论】:

  • 一段漂亮的代码。这个解决方案只是给你最大。 rgbs 的差异。不是我问的。我想给一个颜色并找到关闭。但是写这篇文章我在脑海中回答了它。我稍后会发布代码
【解决方案2】:

你可以试试这个代码

static char[] hexDigits = {
         '0', '1', '2', '3', '4', '5', '6', '7',
         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};



public static string ColorToHexString(Color color)
        {
            byte[] bytes = new byte[4];
            bytes[0] = color.A;
            bytes[1] = color.R;
            bytes[2] = color.G;
            bytes[3] = color.B;
            char[] chars = new char[bytes.Length * 2];
            for (int i = 0; i < bytes.Length; i++)
            {
                int b = bytes[i];
                chars[i * 2] = hexDigits[b >> 4];
                chars[i * 2 + 1] = hexDigits[b & 0xF];
            }
            return new string(chars);
        }

【讨论】:

    【解决方案3】:

    我个人觉得用hue/saturation/brightness 来考虑颜色比用 RGB 值来考虑颜色更自然,我认为在这种情况下这对你很有效。试试这个:

    按照您认为合适的方式将颜色名称分配给光谱的特定范围。例如,红色可能是 0-39,橙色是 40-79,等等(这些是任意数字 - 我不知道它们是否适合任何规模)。然后根据你的 RGB 值计算色调(你可以找到一个公式 here,尽管可能还有其他公式)。一旦你知道了色调,你就知道它在光谱的哪个范围内,你可以给它一个名字。

    【讨论】:

    • 这是这里唯一的好答案!要找到颜色,HSV 和 HSL 颜色空间是唯一不错的选择。您的代码在 OpenCV 中可能需要 5 行!
    【解决方案4】:

    这是一个使用两个限定符和一个颜色名称的简单名称方案:

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

    如果您希望蓝调更加与众不同等,您可以轻松适应它。

    【讨论】:

      【解决方案5】:

      嗯,红色/绿色/蓝色很容易通过检查来识别;您需要支持什么范围的值?

      问题是除非你从一个命名的颜色开始,否则很难返回到一个;即使您通过 FromArgb 创建了明显的颜色,IsNamedColor 也会返回 false。

      如果您只需要实际预期的标准颜色,您可以通过反射枚举已知颜色吗?

              Color test = Color.FromArgb(255,0,0);
              Color known = (
                         from prop in typeof(Color)
                             .GetProperties(BindingFlags.Public | BindingFlags.Static)
                         where prop.PropertyType == typeof(Color)
                         let color = (Color)prop.GetValue(null, null)
                         where color.A == test.A && color.R == test.R
                           && color.G == test.G && color.B == test.B
                         select color)
                         .FirstOrDefault();
      
              Console.WriteLine(known.Name);
      

      您也许还可以使用这种方法作为已知颜色的来源,用于更复杂的算法。

      【讨论】:

      • 全谱我有来自我的网络摄像头的字节图像处理。 i35.tinypic.com/2yvorau.png
      • 一个稍微简单的标准颜色来源是 KnownColors 枚举。这样您就不必使用 GetProperties 等。(使用 Color.FromKnownColor。)
      猜你喜欢
      • 2013-12-24
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 2018-10-26
      • 2011-07-26
      • 2015-07-19
      • 2017-01-18
      • 1970-01-01
      相关资源
      最近更新 更多