2010-01-11 3 views
9

Ich möchte ein Basiswerkzeug wie dieses entwickeln featured here. Ich werde Screenshots von einer Reihe von Webseiten machen und von dort möchte ich die fünf beliebtesten Farben nehmen und von dort aus irgendwie entscheiden, ob die Farben gut passen.Ermitteln eines Farbschemas aus einem Bild

Ich möchte dieses Werkzeug in C# schreiben und nach ein wenig Forschung entdeckte ich Lockbits. Meine erste Idee war, ein Bild zu machen und dann die Farbe jedes Pixels zu bekommen, aber ich bin mir nicht sicher, ob dies mir die gewünschten Ergebnisse bringt und wie man sechs Listen der beliebtesten Farben macht.

Kann jemand hier Rat geben, wie ich ein Programm erstellen würde, um etwas ähnlich dem oben genannten Programm zu machen, das ein Bild aufnimmt und die obersten fünf Farben auswählt, die im Bild verwendet werden?

+2

serhio machte einen ausgezeichneten Punkt über die Verwendung eines Miniaturbilds. Auf diese Weise würde die für die Auswertung eines Bildes benötigte Zeit schnell verbessert werden. +1 – Finglas

Antwort

16

Nun .. Verwenden Sie ein thumbnail image (16x16, 32x32 usw.) und wählen Sie aus, die Farben wie

aktualisiert Code:

private void button1_Click(object sender, EventArgs e) 
    { 
     int thumbSize = 32; 
     Dictionary<Color, int> colors = new Dictionary<Color, int>(); 

     Bitmap thumbBmp = 
      new Bitmap(pictureBox1.BackgroundImage.GetThumbnailImage(
       thumbSize, thumbSize, ThumbnailCallback, IntPtr.Zero)); 

     //just for test 
     pictureBox2.Image = thumbBmp;    

     for (int i = 0; i < thumbSize; i++) 
     { 
      for (int j = 0; j < thumbSize; j++) 
      { 
       Color col = thumbBmp.GetPixel(i, j); 
       if (colors.ContainsKey(col)) 
        colors[col]++; 
       else 
        colors.Add(col, 1); 
      }     
     } 

     List<KeyValuePair<Color, int>> keyValueList = 
      new List<KeyValuePair<Color, int>>(colors); 

     keyValueList.Sort(
      delegate(KeyValuePair<Color, int> firstPair, 
      KeyValuePair<Color, int> nextPair) 
      { 
       return nextPair.Value.CompareTo(firstPair.Value); 
      }); 

     string top10Colors = ""; 
     for (int i = 0; i < 10; i++) 
     { 
      top10Colors += string.Format("\n {0}. {1} > {2}", 
       i, keyValueList[i].Key.ToString(), keyValueList[i].Value); 
      flowLayoutPanel1.Controls[i].BackColor = keyValueList[i].Key; 
     } 
     MessageBox.Show("Top 10 Colors: " + top10Colors); 
    } 

    public bool ThumbnailCallback() { return false; } 

alt text http://lh3.ggpht.com/_1TPOP7DzY1E/S0uZ6GGD4oI/AAAAAAAAC5k/3Psp1cOCELY/s800/colors.png

+1

Ich dachte nicht, ein Thumbnail zu verwenden, gute Sachen. – Finglas

+2

Das ist Genie! Das hätte ich nie gedacht. Ich kann den Code noch nicht testen, weil mein Laptop kaputt ist, aber ich akzeptiere die Antwort irgendwie. Vielen Dank! –

+0

Ummm, war der Blog, auf dem das Image gehostet wurde, down? Das Bild scheint nicht mehr zu existieren. Wenn Sie es noch haben, sollten Sie es mit dem Bild-Button im Editor hochladen. –

2

Der einfachste Weg, wie Sie gesagt ist:

  • Lesen Sie in jedem Pixel und speichern sie in eine Sammlung.

  • Die oberen fünf verwendeten Farben wären die Werte, die am häufigsten auftreten.

So hätte ich zuerst versucht, so etwas zu versuchen.

Um diese Arbeit weiter zu führen, könnten Sie Farbbereiche berücksichtigen, also unter Verwendung von RGB Werte (Red, Green, Blue) eine Farbe einer bestimmten Näherung der Farbe zuordnen.

Sagen wir zum Beispiel, dass das gleiche Bild verwendet wurde, die hellblauen Werte würden zusammen gespeichert werden, dann könnte ein Durchschnitt daraus genommen werden, um das gebräuchlichste (noch durchschnittliche) Hellblau in der Szene zu erhalten.

Wiederholen Sie für die anderen Pixel.

Wie für die Skalierung - die Beispiel-Website verwendet dumpfe/helle Werte. Ein einfacher Skalenwert könnte verwendet werden. Betrachten Sie ein mittleres Rot in RGB:

0.7, 0.0, 0.0 

Sie können dies skalieren, indem Sie einen Wert hinzufügen/multiplizieren. Bewahren Sie die Werte jedoch innerhalb der Grenzen von 0 bis 1 auf. Wie für den Skalierungswert sollte experimentell sein. Je höher es ist, desto matter/heller wird die Farbe.

+0

Ich sollte hinzufügen, dass bei Verwendung von BMP-Bildern, Lesen in einem einzelnen Pixel und Verarbeitung ist es ziemlich einfach, so ein Prototyp zusammen mit einigen der Vorschläge, die Sie in diesem erhalten, sollte ziemlich machbar sein. – Finglas

+0

@Dockers, die Plattform ist C# /. NET. Aus diesem Grund haben alle gängigen Dateien eine einzige API, GetPixel/SetPixel mit X/Y. – Dykam

+0

GetPixel/SetPixel ist jedoch langsam. Ich ziehe es vor, einfach das Backing-Daten-Array zu durchlaufen. – Nyerguds

2

This ist ein Beispiel für das Erstellen eines Histogramms (oder einer Häufigkeitstabelle in anderen Worten), in dem Sie die Details zur Verarbeitung des i ansehen können Magier.

Aber meine wichtigste Empfehlung ist nicht RGB zu verwenden (es sei denn, die Website, die Sie betrachten, hat meist unifarben), sondern HSB stattdessen verwenden. Die Komponente "H" (Farbton) gibt Ihnen eine bessere Anzeige der verwendeten Farben, egal wie hell oder dunkel sie sind.

+0

Codebeispiele oder Links zum Abrufen von HSB-Werten? –

+0

Das Framework stellt die .GetHue(), .GetSaturation() und .GetBrightness() für jedes gegebene Color-Objekt bereit. Es gibt eine sehr gute Post um hier zu erklären mit Details: http://stackoverflow.com/questions/2942/hsl-in-net –