Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting a Colour Scheme from an Image

I want to develop a basic tool like the one featured here. I will be taking screenshots of a number of web pages and from there I wish to take the top five most popular colours and from there somehow decide whether the colours are a good match.

I want to write this tool in C# and after a bit of research I discovered lockbits. My first idea was to take an image and then get the colour of each pixel, but I am unsure as to whether this will give me the results I desire and how to make six lists of the most popular colours.

Can anyone here provide advice as to how I would create a program to do something similar to the program above, that will take in an image and will select the top five colours used in the image?

like image 774
Mike B Avatar asked Jan 11 '10 15:01

Mike B


3 Answers

Well.. Use a thumbnail image (16x16, 32x32 etc) and select from it the colors like

updated 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

like image 95
serhio Avatar answered Sep 19 '22 22:09

serhio


The easiest way, as you said is:

  • Read in each pixel and store them in a collection.

  • The top five colours used would be the values that occur the most.

That's how I'd have ago at first trying something like this.

To further this work, you could take in colour ranges, so using RGB values (Red, Green, Blue) assign a colour to a certain approximation of colour.

For example, say that same image was used, the light blue values would get stored together, then an average could be taken of these to give the most common (yet average) light blue in the scene.

Repeat for the other pixels.

As for the scaling - the example website uses dull/bright values. A simple scale value could be used. Consider a medium red in RGB:

0.7, 0.0, 0.0

You could scale this by adding/multiplying a value. Keep the values within the limit of 0 to 1 however. As for what the scaling value should be, experimant. The higher it is, the duller/brighter the colour will become.

like image 43
Finglas Avatar answered Sep 21 '22 22:09

Finglas


This is an example of how to create a histogram (or a frequency table in another words) where you can take a look on the details on how to go about processing the image.

But my main recommendation is not to use RGB (unless the website you're looking at has mostly plain colors), but use HSB instead. The "H" (hue) component will give you a better indication of the colors used no matter how bright or dark they are.

like image 32
Padu Merloti Avatar answered Sep 22 '22 22:09

Padu Merloti