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

.net 如何在图像中获得多数颜色?,.net,wpf,windows,.net,Wpf,Windows,我想在.NET中检索背景图像中的主色。有可能吗?您可以遍历图像中的所有像素,并使用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++)

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

您可以遍历图像中的所有像素,并使用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]++;
    }
}
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;
    }
}
你可以做:

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);
var added=false;
对于(int i=0;i<10;i++)
{
if(列表容器(rgb+i))
{
列表[rgb+i]++;
添加=真;
打破
}
if(容器清单(rgb-i))
{
列表[rgb-i]++;
添加=真;
打破
}
}
如果(!已添加)
列表。添加(rgb,1);

您可以根据需要将阈值提高到10。

您可能还发现此堆栈溢出算法挑战非常有用:


还考虑创建图像的直方图,并将最高值的颜色作为“多数颜色”:

假设您使用(相对于,例如,)每个像素的颜色来表征,您可以构建一个3D阵列(每个维度分别为R、G和B)。然后决定你想要在每个维度上有多少个箱子——箱子越多,你对相似颜色的区分就越大

完成后,只需遍历图像的位图表示,将落入3d数组中每个单元格的#像素相加即可。总和最高的单元格将成为主色

您可能希望使算法易于为每个维度中的#bin进行配置,以便可以调整它对相似颜色的区分程度

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
      ...
   }
}
image=新位图(“C:\\test.bmp”,true);
int x,y;
//通过图像像素循环生成3d直方图

对于(x=0;x这将返回图像的平均颜色

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]++;
    }
}
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;
    }
}
静态颜色平均颜色(字符串文件名)
{
使用(var bmp=新位图(文件名))
{
int width=bmp.width;
int-height=bmp.height;
红色整数=0;
绿色整数=0;
int蓝色=0;
intα=0;
对于(int x=0;xc/(宽度*高度);
红色=平均值(红色);
绿色=平均值(绿色);
蓝色=平均值(蓝色);
α=平均值(α);
var color=color.FromArgb(阿尔法、红色、绿色、蓝色);
返回颜色;
}
}

这将返回使用不安全指针访问的图像的平均颜色。注意:代码仅适用于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);
        }
    }
不安全的静态颜色GetColor(字符串文件名)
{
使用(var image=(位图)Bitmap.FromFile(文件名))
{
如果(image.PixelFormat!=PixelFormat.Format24bppRgb)抛出新的NotSupportedException(String.Format(“不支持的像素格式:{0}”,image.PixelFormat));
var pixelSize=3;
变量边界=新矩形(0,0,image.Width,image.Height);
var数据=image.LockBits(边界,ImageLockMode.ReadOnly,image.PixelFormat);
长r=0;
长g=0;
长b=0;
对于(int y=0;y

要点:

你能澄清“多数颜色”的含义吗?你是指图像中最常用的颜色;图像的平均颜色;“最高”值颜色等效RGB?你可能需要澄清“多数颜色”的含义。对于大多数图像,任何一种颜色都不可能构成适当的多数。我假设您指的是最常见的颜色(逐像素)或主要成分(R、G或B)。是否需要速度或精度?是否需要最常用的颜色、平均颜色或趋势颜色?是否需要RGB混合或专用?如果将图像大小调整为较小的图像(如10x10像素左右),然后将颜色空间减少到16或256左右的调色板,然后构建结果图像的直方图,并找到其中的最高元素-这会起作用吗?至少应该相当快。如果这是“真彩色”jpeg…这可能是字典中大量的值,每个键的计数非常少。同意。你需要某种类型的分块或分组才能正常工作。使用这一个,你可以有2个完美的红色像素和大量黑色的细微变化,并以红色作为主要颜色。从技术上讲,红色将是主要颜色lor…这取决于什么是主要颜色。如果是一般颜色,那么在他的例子中黑色应该是主要颜色。例如(int i=0;i>10;i++)。您的操作员应该切换到+1以获得性能。在每个像素上调用GetPixel非常慢。非常慢有点夸张。我能够使用GetPixel方法以15fps 800x600的速度分析视频帧。因此,如果海报只需要分析单个图像,GetPixel就足够了。我认为分辨率不够ult被称为“多数色”,因为可能没有一个像素是平均色。非常正确……这就是为什么我在问题下的评论中要求更多细节。没有回答,所以这是我的条目。