从图像中获取最常用和最“不同”的颜色

时间:2014-04-21 06:58:49

标签: c# algorithm image-processing

我一直在浏览网页上的算法,该算法分析图像并返回最不同和最常用的颜色 - 但没有运气。

例如;

如果我在25% red (255,0,0)RGB50% fully blue (0,0,255)

中有25% pink (255,0,255)的位图

我希望算法返回在使用中排序的这三种(或更多,取决于可用颜色)颜色,所以:

1. Blue
2. Red / Pink
3. Red / Pink

任何人都知道某种方式我可以开始这个吗?也许有些文章需要阅读等等。我从未在C#中使用过像这样的图像。

2 个答案:

答案 0 :(得分:1)

  1. 最常用的颜色

    通过一点谷歌努力,你会发现直方图。如果您想将阴影用作单独的颜色,那么您有256^3种颜色。因此要么使用一些动态列表,要么忽略几个最低有效位来降低数字。您还可以通过标准化颜色来更改动态范围。

    • 黑色是黑色
    • 并且其他所有内容都将矢量大小更改为Max,例如

      Max = 2^5-1 = 31
      normalized color = color * Max / |color|
      

    现在算法:

    1. 为所有颜色组合创建一个计数器表cnt

      对于Max = 31

      的大小为2^15 = 32768。将整个表设置为零。

      int cnt[32768];
      for (int i=0;i<32768;i++) cnt[i]=0;
      
    2. 浏览整个图像和每个像素

      • 将其颜色标准化
      • 将其转换为地址(例如adr = (R) | (G<<5) | (B<<10)
      • 增加其计数器cnt[adr]++;
    3. 在此之后,您在cnt[]中有直方图。所以现在索引按cnt的值对其进行排序,你已经获得了按用途排序的颜色

    4. 最不同的颜色

      你会如何定义它?我会使用直方图中的数据并搜索其中2种颜色之间的max距离(标准化后)

      d = |color1 - color2|
      

      不需要sqrt ...如果您使用d^2,您将获得相同的结果。忽略cnt[adr]==0(未使用的颜色)的所有条目。这仍然是O(n^2) ...更像是~T(n*n/2) ...在运行时术语中,但n不是图像中的像素数。相反,它只是图像中不同使用颜色的数量远远少于...也是在索引排序直方图和删除/忽略所有cnt[adr]==0条目甚至情人之后。

答案 1 :(得分:0)

如果我正确理解了这个问题,这可能对你有所帮助(当然你必须根据你的需要阅读数据):

/// <summary>
    /// Gets the bitmap image color statistics
    /// </summary>
    /// <param name="bit">The bitmap image you want to analyze</param>
    /// <returns></returns>
    public static List<KeyValuePair<Color, int>> GetStatistics(Bitmap bit)
    {
        Dictionary<Color, int> countDictionary = new Dictionary<Color, int>();

        for (int wid = 0; wid < bit.Width; wid++)
        {//for every column in the image
            for (int he = 0; he < bit.Height; he++)
            {//for every row in the image

                //Get the color of the pixel reached (i.e. at the current column and row)
                Color currentColor = bit.GetPixel(wid, he);

                //If a record already exists for this color, set the count, otherwise just set it as 0
                int currentCount = (countDictionary.ContainsKey(currentColor) ? countDictionary[currentColor] : 0);

                if (currentCount == 0)
                {//If this color doesnt already exists in the dictionary, add it
                    countDictionary.Add(currentColor, 1);
                }
                else
                {//If it exists, increment the value and update it
                    countDictionary[currentColor] = currentCount + 1;
                }
            }
        }

        //order the list from most used to least used before returning
        List<KeyValuePair<Color, int>> l = countDictionary.OrderByDescending(o => o.Value).ToList();

        return l;
    }
}