9
votes

Obtenir une palette de couleurs d'une image

Je veux développer un outil de base comme celui de présenté ici . Je prendrai des captures d'écran d'un certain nombre de pages Web et de là, je souhaite prendre les cinq couleurs les plus populaires les plus populaires et à partir de là, décidez si les couleurs sont une bonne correspondance.

Je veux écrire cet outil en C # et après un peu de recherche, j'ai découvert des verrouillements. Ma première idée était de prendre une image puis d'obtenir la couleur de chaque pixel, mais je ne suis pas sûr de savoir si cela me donnera les résultats que je désire et comment faire six listes des couleurs les plus populaires.

Quelqu'un peut-il offrir des conseils sur la manière dont je créerais un programme de faire quelque chose de similaire au programme ci-dessus, qui prendra une image et sélectionnera les cinq principales couleurs utilisées dans l'image?


1 commentaires

Sergio a fait un excellent point sur l'utilisation d'une image miniature. De cette façon, le temps nécessaire pour évaluer une image serait rapidement amélioré. +1


3 Réponses :


2
votes

Le moyen le plus simple, comme vous l'avez dit est:

  • lire dans chaque pixel et stockez-les dans une collection. P> li>

  • Les cinq top cinq couleurs utilisées seraient les valeurs qui se produisent le plus. p> li> ul>

    C'est comme ça que je voudrais il y a d'abord essayer quelque chose comme ça. p>

    Pour plus de ce travail, vous pouvez prendre des gammes de couleurs, donc en utilisant RVB valeurs ( rouge, vert, bleu code>) Attribuez une couleur à une certaine approximation de la couleur. p>

    Par exemple, disons que la même image a été utilisée, les valeurs bleues claires seraient stockées ensemble, puis une moyenne pourrait être prise en moyenne pour donner le bleu clair (encore moyen) bleu clair dans la scène. P >

    Répéter pour les autres pixels. p>

    comme pour la mise à l'échelle - Le site d'exemple utilise des valeurs ternes / lumineuses. Une valeur d'échelle simple pourrait être utilisée. Considérez un rouge moyen dans RVB: P>

    0.7, 0.0, 0.0
    


3 commentaires

Je devrais ajouter, que lorsque vous utilisez des images BMP, la lecture dans un seul pixel et le traitement est assez simple, alors jetant ainsi un prototype en utilisant certaines des suggestions que vous obtenez dans cela devrait être équitablement à faire.


@Dockers, la plate-forme est c # /. Net. Étant donné que tous les fichiers communs ont une seule API, GetPixel / SetPixel avec X / Y.


GetPixel / SetPixel est lent cependant. Je préfère simplement boucler à travers la matrice de données de support.



16
votes

Eh bien .. Utilisez une image de vignette (forte> (16x16, 32x32 etc.) et sélectionnez-la des couleurs telles que

Code mis à jour: strong> p>

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


3 commentaires

C'est génie! Je n'aurais jamais pensé à faire ça. Je ne peux pas tester le code juste parce que mon ordinateur portable est cassé mais j'accepterai la réponse. Merci beaucoup!


Ummm, le blog a-t-il fait que l'image était hébergée? L'image ne semble plus exister. Si vous l'avez toujours, vous devez envisager de le télécharger avec le bouton Image de l'éditeur.


Est-ce que cela ne se débarrassera pas des points saillants à contraste élevé simplement parce qu'ils ne sont pas utilisés dans une grande partie de l'image? J'aimerais quelque chose qui préserve de tels détails et filtre les couleurs trop similaires.



2
votes

Ce est un exemple de la manière de créer un histogramme (ou un Table de fréquence dans d'autres mots) Où vous pouvez jeter un coup d'œil sur les détails sur la manière de traiter l'image.

Mais ma recommandation principale est de ne pas utiliser RVB (à moins que le site Web que vous envisagez a surtout des couleurs simples), mais utilisez plutôt HSB. Le composant "H" (Hue) vous donnera une meilleure indication des couleurs utilisées, peu importe la luminosité ou la nuit.


1 commentaires

Le cadre fournit le .GETHUE (), .getsaturation () et .getBrightness () pour tout objet couleur donné. Il y a un très bon post ici expliquant avec des détails: Stackoverflow.com/questions/2942/hsl-in-net