2016-11-30 2 views
-1

So jemand mir geholfen, diesen Code zu machen, die mir am meisten verwendete Farbe in einem Foto sagen werden:zeigen am häufigsten verwendete Farbe in einem Bild

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; 
    } 

} 

und ich versuche, so zu implementieren, aber ich weiß nicht wirklich wissen, was ich tun soll, um mir die am häufigsten verwendete Farbe zu zeigen?

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

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

       PictureAnalysis.GetMostUsedColor(bMap); 

Ich mag das am häufigsten verwendete Farbe von einem „echten“ Foto wie dies bestimmen: I am cropping her "jacket" from the photo and I want a program that determines it as it is black

+1

Wie Willst du es zeigen? –

+3

als String, wie in einer Messagebox –

+3

'MessageBox.Show (" Meist verwendete Farbe ist "+ PictureAnalysis.MostUsedColor.ToString());' ... aber ernst. Wie möchten Sie diese Farbe anzeigen? Einen neuen Dialog anzeigen, irgendwo in UI einfügen (wie ein Rechteck, das mit dieser Farbe gefüllt ist)? –

Antwort

0

Es gibt zwei Möglichkeiten:

Erste Änderung des Rückgabetyp der Methode GetMostUsedColor von void nach int

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

Danach wird diese Methode die m zurückgeben ost verwendete Farbe.

Wenn Sie Ihr Programm in der Konsole ausführen,

Sie letzte Zeile PictureAnalysis.GetMostUsedColor(bMap) mit Console.WriteLine(PictureAnalysis.GetMostUsedColor(bMap)) ersetzen, um die am häufigsten verwendete Farbe

Zweiter Weg (wenn Sie Konsole) zu erhalten nur eine Zeile ersetzen

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

ok, ich benutzte die erste und es zeigt mir die Hex-Farbe und ich möchte es in dunkelblau, rot etc .. –

+0

So Suche nach 'C# bekommen Farbe von Hex 'auf Ihrer bevorzugten Suchmaschine, lesen Sie die erste Ergebnis, Gewinn. – Equalsk

0

Diese Klasse ist statisch, ist der Aufruf der Methode statisch, und die Ergebnisse sind auch ...

Also diese verwenden:

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; 

Anzeige der Farbe als String

Im System.Drawing-Namespace Microsoft definierte viele Farben in der Struktur Color. Es besteht also die Möglichkeit, eine Farbe aus einer known color name zu erstellen.

Allerdings müssen Sie verstehen, dass alle Farben keinen Namen haben. Weil es viele von ihnen gibt. Es ist also nicht immer möglich, einer Farbe einen Namen zu geben.

Sie können versuchen, eine Methode zu schreiben, die eine Farbe und gibt die Farbbezeichnung nehmen würde ... Aber denken Sie daran gibt es über 16 Millionen Möglichkeiten ...

Eine Art von Lösung

Was Ich würde tun, ist die Farbe in eine ColorDialog. Sie legen dann die Eigenschaft Farbe auf die am häufigsten verwendete Farbe fest.

Auf diese Weise wird der Benutzer zumindest der Lage sein, um die Farbe zu sehen

Eine weitere Option ist es in einem Property zu sehen, weil ihre Colorpicker zu schön ist.

0

Es gibt mehrere Möglichkeiten, dies zu tun.

Hier sind zwei Lösungen:

1.

Machen Sie eine Liste aller Farben, die Sie gegen vergleichen möchten. Ich würde eine Liste aller Farben in Farbe nehmen. *

Dann durchlaufen Sie alle Pixel und vergleichen Sie jede Farbe gegen die Liste, um die nächste zu nehmen und speichern Sie dann diese Farbe mit einem Wert von 1 Vorkommen, dann nehmen Sie die Als nächstes und so weiter und schließlich haben Sie eine Liste der dominantesten Farbe der Liste. Dann nehmen Sie einfach diese Farbe und erhalten Sie den Namen, da es eine echte Farbe ist. Like:

string nameOfColorRed = Color.Red.Name; 

Um Schleife durch alle Pixel in einem Bild, das Sie GetPixel verwenden könnten(), aber das ist ein bisschen langsam, so sollten Sie schnelle Methoden wie finden Sie hier: Travel through pixels in BMP

2.

Eine andere einfache Lösung, die funktionieren sollte, ist ein bisschen zu schummeln und das Bild auf die Größe 1x1 Pixel zu skalieren und dann erhalten Sie die dominanteste Farbe auf diesem einzelnen Pixel. Dies hat zu ein paar einfachen Tests funktioniert, die ich gemacht habe und es könnte gut genug sein? Ansonsten verwende die 1. Lösung.

Dann vergleichen Sie einfach diese Farbe mit der Liste. Hier

ist ein Beispiel für die letzte Lösung:

 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; 

Die Methoden für die Suche nach ClosestColor von hier genommen wird: How to compare Color object and get closest Color in an Color[]?

Hier sind die restlichen Methoden:

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; 
    } 
Verwandte Themen