如何在图像中获得多数颜色?

时间:2010-03-30 14:04:19

标签: .net wpf windows

我想在.NET中检索背景图像中的大部分颜色。有可能吗?

5 个答案:

答案 0 :(得分:6)

您可以遍历图像中的所有像素,并使用getPixel方法确定RGB值。然后,您可以使用字典存储ARGB值以及计数。然后,您可以查看图像中最常出现的ARGB值。

var list = new Dictionary<int, int>();
Bitmap myImage = (Bitmap)Bitmap.FromFile("C:/test.jpeg");
for (int x = 0; x < myImage.Width; x++)
{
    for (int y = 0; y < myImage.Height; y++)
    {
        int rgb = myImage.GetPixel(x, y).ToArgb();
        if (!list.ContainsKey(rgb))
            list.Add(rgb, 1);
        else
            list[rgb]++;
    }
}

正如所指出的,这并没有对类似的颜色表示同情。如果你想要一个更“普通”的多数颜色,你可以在相似性上有一个阈值。例如而不是:

if (!list.ContainsKey(rgb))
        list.Add(rgb, 1);
    else
        list[rgb]++;
你可以这样做:

var added = false;
for (int i = 0; i < 10; i++)
{
    if (list.ContainsKey(rgb+i))
    {
        list[rgb+i]++;
        added = true;
        break;
    }
    if (list.ContainsKey(rgb-i))
    {
        list[rgb-i]++;
        added = true;
        break;
    }
}
if(!added)
    list.Add(rgb, 1);

你可以将10的门槛提高到你需要的任何值。

答案 1 :(得分:5)

你也可以在Stack Overflow上找到这个算法挑战:

Algorithm challenge: Generate color scheme from an image

还要考虑创建图像的直方图 - 并将最高值的颜色作为“多数颜色”:http://www.phpclasses.org/browse/file/15953.html

答案 2 :(得分:5)

这将返回图像的平均颜色。

static Color AverageColor(string fileName)
{
    using (var bmp = new Bitmap(fileName))
    {
        int width = bmp.Width;
        int height = bmp.Height;
        int red = 0;
        int green = 0;
        int blue = 0;
        int alpha = 0;
        for (int x = 0; x < width; x++)
            for (int y = 0; y < height; y++)
            {
                var pixel = bmp.GetPixel(x, y);
                red += pixel.R;
                green += pixel.G;
                blue += pixel.B;
                alpha += pixel.A;
            }

        Func<int, int> avg = c => c / (width * height);

        red = avg(red);
        green = avg(green);
        blue = avg(blue);
        alpha = avg(alpha);

        var color = Color.FromArgb(alpha, red, green, blue);

        return color;
    }
}

答案 3 :(得分:4)

这将使用不安全的指针访问返回图像的平均颜色。注意:代码仅适用于24bppRgb,可以适用于其他像素格式。

    unsafe static Color GetColor(string filename)
    {
        using (var image = (Bitmap)Bitmap.FromFile(filename))
        {
            if (image.PixelFormat != PixelFormat.Format24bppRgb) throw new NotSupportedException(String.Format("Unsupported pixel format: {0}", image.PixelFormat));

            var pixelSize = 3;
            var bounds = new Rectangle(0, 0, image.Width, image.Height);
            var data = image.LockBits(bounds, ImageLockMode.ReadOnly, image.PixelFormat);

            long r = 0;
            long g = 0;
            long b = 0;

            for (int y = 0; y < data.Height; ++y)
            {
                byte* row = (byte*)data.Scan0 + (y * data.Stride);
                for (int x = 0; x < data.Width; ++x)
                {
                    var pos = x * pixelSize;
                    b += row[pos];
                    g += row[pos + 1];
                    r += row[pos + 2];
                }
            }

            r = r / (data.Width * data.Height);
            g = g / (data.Width * data.Height);
            b = b / (data.Width * data.Height);
            image.UnlockBits(data);

            return Color.FromArgb((int)r, (int)g, (int)b);
        }
    }

要点:http://gist.github.com/349210

答案 4 :(得分:3)

假设您使用RGB(相对于CMYK)来表征每个像素的颜色,您可以构建一个3d数组(R,G和B各一个)。然后决定你想要在每个维度中拥有的箱子数量 - 箱子越多,你在相似色调之间的差异就越大。

完成后,只需迭代图像的位图表示,即对落入3d数组中每个单元格的#像素求和。具有最高总和的单元格将是主要颜色。

您可能希望使您的算法可以轻松配置为每个维度中的#bins,以便您可以调整它在相似颜色之间的区别。

image = new Bitmap("C:\\test.bmp", true);
int x, y;
// Loop through the images pixels to product 3d histogram
for(x=0; x<image.Width; x++)
{
   for(y=0; y<image.Height; y++)
   {
      Color pixelColor = image.GetPixel(x, y);

      // Increment color count in appropriate cell of your 3d histogram here
      ...
   }
}