【问题标题】:show most used color in an image显示图像中最常用的颜色
【发布时间】:2016-12-12 21:32:51
【问题描述】:

所以有人帮我制作了这段代码,它会告诉我照片中最常用的颜色:

class PictureAnalysis
{
    public static List<Color> TenMostUsedColors { get; private set; }
    public static List<int> TenMostUsedColorIncidences { get; private set; }

    public static Color MostUsedColor { get; private set; }
    public static int MostUsedColorIncidence { get; private set; }

    private static int pixelColor;

    private static Dictionary<int, int> dctColorIncidence;

    public static void GetMostUsedColor(Bitmap theBitMap)
    {
        TenMostUsedColors = new List<Color>();
        TenMostUsedColorIncidences = new List<int>();

        MostUsedColor = Color.Empty;
        MostUsedColorIncidence = 0;

        // does using Dictionary<int,int> here
        // really pay-off compared to using
        // Dictionary<Color, int> ?

        // would using a SortedDictionary be much slower, or ?

        dctColorIncidence = new Dictionary<int, int>();

        // this is what you want to speed up with unmanaged code
        for (int row = 0; row < theBitMap.Size.Width; row++)
        {
            for (int col = 0; col < theBitMap.Size.Height; col++)
            {
                pixelColor = theBitMap.GetPixel(row, col).ToArgb();

                if (dctColorIncidence.Keys.Contains(pixelColor))
                {
                    dctColorIncidence[pixelColor]++;
                }
                else
                {
                    dctColorIncidence.Add(pixelColor, 1);
                }
            }
        }

        // note that there are those who argue that a
        // .NET Generic Dictionary is never guaranteed
        // to be sorted by methods like this
        var dctSortedByValueHighToLow = dctColorIncidence.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value);

        // this should be replaced with some elegant Linq ?
        foreach (KeyValuePair<int, int> kvp in dctSortedByValueHighToLow.Take(10))
        {
            TenMostUsedColors.Add(Color.FromArgb(kvp.Key));
            TenMostUsedColorIncidences.Add(kvp.Value);
        }

        MostUsedColor = Color.FromArgb(dctSortedByValueHighToLow.First().Key);
        MostUsedColorIncidence = dctSortedByValueHighToLow.First().Value;
    }

}

我正在尝试这样实现,但我真的不知道该怎么做才能向我展示最常用的颜色?

string filep = @"C:\Users\User\Desktop\Gallery\image" + NumberOfClick.ToString() + "cropped.png";

                Bitmap bMap = Bitmap.FromFile(filep) as Bitmap;

                PictureAnalysis.GetMostUsedColor(bMap);

我想从这样一张“真实”照片中确定最常用的颜色:I am cropping her "jacket" from the photo and I want a program that determines it as it is black

【问题讨论】:

  • 你想怎么展示?
  • 作为字符串,就像在消息框中一样
  • MessageBox.Show("Most used color is " + PictureAnalysis.MostUsedColor.ToString()); ...但说真的。你想如何显示这种颜色?显示一个新对话框,把它放在 UI 中的某个地方(比如用这种颜色填充的矩形)?
  • 在这种情况下,给它一个颜色返回类型,或者使用Color 作为ref 变量。然后您可以将 textBox 文本更改为 theColor.r.ToString() + " " + theColor.g.ToString() + " " + theColor.b.ToString();
  • @m.rogalski 我试过这种方式,但它显示在任何照片上 Color[A=0; R=0; G = 0; B =0] 我想要红色、蓝色等。

标签: c#


【解决方案1】:

有两种方式:

第一 将 GetMostUsedColor 方法的返回类型从 void 更改为 int

public static int GetMostUsedColor(Bitmap theBitMap)
{
    TenMostUsedColors = new List<Color>();
    /*unchangeable code here*/
    return dctSortedByValueHighToLow.First().Value;
}

之后,此方法将返回最常用的颜色。

如果你在控制台中运行你的程序,

您可以将最后一行 PictureAnalysis.GetMostUsedColor(bMap) 替换为 Console.WriteLine(PictureAnalysis.GetMostUsedColor(bMap)) 以获得最常用的颜色

第二种方式 (如果你使用控制台) 只换一行

public static void GetMostUsedColor(Bitmap theBitMap)
{
    /*unchangeable code here*/
     Console.WriteLine(dctSortedByValueHighToLow.First().Value);
}

【讨论】:

  • 好的,我用的是第一个,它显示了十六进制颜色,我想把它变成深蓝色、红色等。
  • 所以在你最喜欢的搜索引擎上搜索C# get color from hex,阅读第一个结果,获利。
【解决方案2】:

这个类是静态的,方法调用是静态的,结果也是……

所以要使用这个:

string filep = @"C:\Users\User\Desktop\Gallery\image" + NumberOfClick.ToString() + "cropped.png";
Bitmap bMap = Bitmap.FromFile(filep) as Bitmap;
PictureAnalysis.GetMostUsedColor(bMap);

//Here you get the most used color
var Color MostUsed = PictureAnalysis.MostUsedColor;
//Here you get the ten most used colors
var List<Color> TenMostUsed = PictureAnalysis.TenMostUsedColor;

将颜色显示为字符串

在 System.Drawing 命名空间中,微软在Color 结构中定义了很多颜色。所以有可能从known color name 创建颜色。

但是,您必须了解所有颜色都没有名称。因为他们有很多。因此,并非总是可以在颜色上加上名称。

您可以尝试编写一个方法来获取颜色并返回颜色名称...但请记住,有超过 1600 万种可能性...

一种解决方案

我要做的是将颜色放入ColorDialog 中。 然后将其 Color 属性设置为您最常用的颜色。

这样,用户至少可以看到颜色

另一种选择是在 PropertyGrid 中查看它,因为它们的 ColorPicker 也不错。

【讨论】:

    【解决方案3】:

    有几种方法可以做到这一点。

    这里有两种解决方案:

    1.

    列出您要比较的所有颜色。 我会列出 Color 中的所有颜色。*

    然后循环遍历所有像素并将每种颜色与列表进行比较以获取最接近的颜色,然后将该颜色保存为 1 出现次数,然后取下一个,依此类推,最后你有一个最主要颜色的列表列表中的那些。 然后取那个颜色并得到名字,因为它是一个真正的颜色。 喜欢:

    string nameOfColorRed = Color.Red.Name;
    

    要遍历图像中的所有像素,您可以使用 GetPixel() 但这有点慢,因此您应该使用更快的方法,如您可以在此处找到的:Travel through pixels in BMP

    2.

    另一个应该可行的简单解决方案是稍微作弊并将图像大小调整为 1x1 像素大小,然后您就可以在该单个像素上获得最主要的颜色。这对我进行的一些简单测试有效,可能足够好?否则使用第一种解决方案。

    然后将该颜色与列表进行比较。

    这是最后一个解决方案的示例:

            var listOfColors = GetAllColors();
    
            var filename = @"D:\Nature-View.jpg";
            var image = Image.FromFile(filename);
    
            var smallImage = ResizeImage(image, 1, 1);
    
            var index = ClosestColor2(listOfColors, smallImage.GetPixel(0, 0));
    
            var closestColorName = listOfColors[index].Name;
    

    查找 ClosestColor 的方法取自这里:How to compare Color object and get closest Color in an Color[]?

    剩下的方法如下:

        private List<Color> GetAllColors() {
            var list = new List<Color>();
            var colorType = typeof(Color);
            var propInfos = colorType.GetProperties(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public);
            foreach (var propInfo in propInfos) {
                var color = Color.FromName(propInfo.Name);
                list.Add(color);
            }
            return list;
        }
    
        // closed match in RGB space
        private int ClosestColor2(List<Color> colors, Color target) {
            var colorDiffs = colors.Select(n => ColorDiff(n, target)).Min(n => n);
            return colors.FindIndex(n => ColorDiff(n, target) == colorDiffs);
        }
    
        // distance in RGB space
        private static int ColorDiff(Color c1, Color c2) {
            return (int) Math.Sqrt((c1.R - c2.R)*(c1.R - c2.R)
                                   + (c1.G - c2.G)*(c1.G - c2.G)
                                   + (c1.B - c2.B)*(c1.B - c2.B));
        }
    
        public static Bitmap ResizeImage(Image image, int width, int height) {
            var destRect = new Rectangle(0, 0, width, height);
            var destImage = new Bitmap(width, height);
    
            destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
    
            using (var graphics = Graphics.FromImage(destImage)) {
                graphics.CompositingMode = CompositingMode.SourceCopy;
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
    
                using (var wrapMode = new ImageAttributes()) {
                    wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                    graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
                }
            }
    
            return destImage;
        }
    

    【讨论】:

      猜你喜欢
      • 2018-07-15
      • 2011-05-24
      • 2018-12-16
      • 2012-01-02
      • 2016-11-12
      • 2010-12-19
      • 1970-01-01
      • 2015-11-02
      • 2011-05-04
      相关资源
      最近更新 更多