【问题标题】:How do I get the background color of Bitmap Image in c#?如何在c#中获取位图图像的背景颜色?
【发布时间】:2014-05-13 08:10:47
【问题描述】:

我有以下代码-

Bitmap img = new Bitmap(ControlsMap.BtnYes.CaptureImage());
img.Save(@"E:\images\btnyes.png");

图像也被正确捕获和保存 -


我想获取图片的背景颜色。

我尝试了以下行的几种变体 -

var a = img.Palette.Entries;

但我无法获得图像的背景颜色。有没有其他办法?

【问题讨论】:

  • 如果您自己创建了位图,那么您一定已经定义了颜色,那么您为什么要取回颜色代码,否则如果您没有并从某个地方加载图像,.Net没有任何方法。
  • 这也有点困难。图像应该作为二进制文件受到威胁 - 想象一下你有一个洒落的背景 - c#/.net 应该如何知道你需要这些颜色中的哪一种?在您的按钮中:您想要深绿色还是浅绿色边框?
  • @christian.s 我想要深绿色
  • @user3164272 我知道 - 但你必须用你的语言来表达。也许这有帮助:stackoverflow.com/questions/19808743/… 看看代码 sn-ps
  • @user3164272 我想说的是你需要处理整个图像,你不会找到像“背景颜色”这样的属性,你的问题听起来就像你在看为。

标签: c# image visual-studio-2010 background


【解决方案1】:

【讨论】:

  • 是的,我知道获取特定像素的颜色。但我想要一些存储图像中存在的颜色数组的东西。我以为 img.Palette 会给我那个,但它没有。
  • 不过,您可以使用 GetPixel() 方法逐个像素地遍历整个图像。喜欢这里:stackoverflow.com/questions/13748781/… 但这可能需要一些时间。 LockBits 可能会帮助你.. 看看这里。 stackoverflow.com/questions/3795268/…
【解决方案2】:

只需遍历整个图像并对找到的每种颜色进行计数,然后获取计数最多的颜色。

执行此操作的最简单方法可能是使用 GetPixel,但对于可能需要很长时间的大图像。因此,您可以将图像粘贴到 32bppARGB 图像上,以确保它采用特定的已知格式,然后使用 LockBits 和 Marshal.Copy 取出原始字节,然后遍历这些字节,将它们组合成每四个颜色,然后检查那些颜色。

为了真正获得最大值,我会使用字典,其中颜色作为键,数量作为值。

所有的一切,你得到这个:

public static Color FindMostCommonColor(Image image)
{
    // Avoid unnecessary getter calls
    Int32 height = image.Height;
    Int32 width = image.Width;
    Int32 stride;
    Byte[] imageData;
    // Expose bytes as 32bpp ARGB
    BitmapData sourceData = image.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    stride = sourceData.Stride;
    imageData = new Byte[stride * bm.Height];
    Marshal.Copy(sourceData.Scan0, imageData, 0, imageData.Length);
    image.UnlockBits(sourceData);
    // Store colour frequencies in a dictionary.
    Dictionary<Color,Int32> colorFreq = new Dictionary<Color, Int32>();
    for (Int32 y = 0; y < height; y++)
    {
        // Reset offset on every line, since stride is not guaranteed to always be width * pixel size.
        Int32 inputOffs = y * stride;
        //Final offset = y * line length in bytes + x * pixel length in bytes.
        //To avoid recalculating that offset each time we just increase it with the pixel size at the end of each x iteration.
        for (Int32 x = 0; x < width; x++)
        {
            //Get colour components out. "ARGB" is actually the order in the final integer which is read as little-endian, so the real order is BGRA.
            Color col = Color.FromArgb(imageData[inputOffs + 3], imageData[inputOffs + 2], imageData[inputOffs + 1], imageData[inputOffs]);
            Color bareCol = Color.FromArgb(255, col);
            // Only look at nontransparent pixels; cut off at 127.
            if (col.A > 127)
            {
                if (!colorFreq.ContainsKey(bareCol))
                    colorFreq.Add(bareCol, 1);
                else
                    colorFreq[bareCol]++;
            }
            // Increase the offset by the pixel width. For 32bpp ARGB, each pixel is 4 bytes.
            inputOffs += 4;
        }
    }
    // Get the maximum value in the dictionary values
    Int32 max = colorFreq.Values.Max();
    // Get the first colour that matches that maximum.
    return colorFreq.FirstOrDefault(x => x.Value == max).Key;
    // In case you want to know if there are multiple with the exact same frequency,
    // this could be expanded to give an array with all maxima like this:
    // Color[] maxCols = colorFreq.Where(x => x.Value == max).Select(kvp => kvp.Key).ToArray();
}

请注意,如果图像是 jpeg 之类的,这可能效果不太好,因为它在所有颜色上都有轻微的褪色。然后你必须以某种方式减少相似的颜色,或阈值系统。不过,那是完全不同的蠕虫罐头。

【讨论】:

    猜你喜欢
    • 2012-06-04
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    相关资源
    最近更新 更多