views:

534

answers:

7

Hi,

I want to find the most used colour in an image using python. for example detect the colour of the object in the following image

http://www.shopcrazy.com.ph/wp-content/images/2007/02/shiny-bags-01.jpg.

how to detect the base colour from the RGB codes(example - red in the above image).

+1  A: 

The brute force approach is to loop over all pixels in the image and keep count of R, G, B values. A more refined approach is to use Python Image Library histogram function and calculate the average of all colors.

Martin Wickman
It might be sufficient to just take a random sample of the pixels and count those.
Tom Dignan
+3  A: 

Since you will most likely not want a histogram of all the million colors that are possible using a 24-bit color space, I suggest transforming the image into HSV space instead. Then you can partition the Hue part of that space into a number of bins that describe the hues you want to find ("dark red", "orange red", or whatever). Then make a histogram of these bins and find which is the dominant hue, which is the "color".

The wikipedia article http://en.wikipedia.org/wiki/HSL_and_HSV should get you started. IF you are using an image processing library chances are that a rgb-to-hsv/hsl function exists.

Also, if the images are large and speed is an issue, you might consider downsampling the image to a smaller size before histogramming.

kigurai
Good advice, although on H alone you can not see the difference between deep red and pink, for example.
AVB
True. But I guess it is easier dividing bins based on H and S, instead of partitioning R, G and B :)
kigurai
how to convert the image to HSV using python code?
Sreejith
+1  A: 

If you are really sure that you will always have only one dominant color (no bags in two colors, e.g.), then a crude histogram on the H&S dimensions of HSV should suffice.

Otherwise, you can (and should ) use mean shift. It's fairly simple, does exactly what you want, and there are libraries you can use, although I could not find anything in Python. You can either implement it, or call C++ code.

The basic idea of the algorithm is this: each pixel looks at nearby pixels of similar color, and changes its color to the weighted mean of all their colors; rinse and repeat. Pretty soon you have all the colors in the image clustered very tightly around a few predominant colors.

AVB
A: 

Sort the pixels in-place, then loop through the image and find the longest run.

Paul Hankin
-1: This will not produce good results for natural images. Given a 24-bit color space you have 16 million colors. A big photo has maybe 10 million pixels this means that there is a quite substantial chance that every pixel has a unique color.Without thresholding I don't think this will give the expected result.
kigurai
I answered the question as asked - if the problem is badly stated, vote down the problem, not the solution. Also, your assertion that a 10M pixel has a substantial chance of having every pixel a unique color is flat wrong. You only need 12-13 thousand random pixels for the probability to be less than 1%, and 10M gives a chance many orders of magnitude smaller.
Paul Hankin
A: 

As suggested, it will be handier to convert your image from RGB to HSV. The standard library module colorsys contains the function rgb_to_hsv to that effect. Then, you can map colors on an image, say with H as x and S as y. Select points in that space, and give them names; the more points, the better. Then, for every pixel in your image, find the closest of the points you selected and use its name as the pixel value. Count which name occurs most times.

Do you want me to supply code?

ΤΖΩΤΖΙΟΥ
A: 

I would use the Python Image Library. This is a piece of code that computes the number of white pixels/non-white pixels in an image.

import sys

from PIL import Image

im = Image.open(sys.argv[1])
white = 0
black = 0
for i in im.getdata():
  if i == (255,255,255):
    white += 1
  else:
    # we assume black everything that is not white:
    black += 1
print im.size[0],im.size[1],white,black

In your case, I would do a dictionary to keep every rgb triple against a counter, so I would rework the program like this (not tested)

import sys

from PIL import Image

im = Image.open(sys.argv[1])
count= {}
for i in im.getdata():
  if not count.has_key(i):
      count[i] = 0

  count[i] += 1

You can now check the one with the highest count and get the most used rgb triple. Of course, if you want to check also vicinal colors, you will have to convert to HSV and check the distances between different HSV points, then decide which distance is too much. Points sufficiently near in HSV space (and in particular the hue component) are most likely the same color and consequently can be summed together.

Stefano Borini