6

I'm using Python and PIL.

I have images in RGB and I would like to know those who contain only one color (say #FF0000 for example) or a few very close colors (#FF0000 and #FF0001).

I was thinking about using the histogram but it is very hard to figure out something with the 3 color bands, so I'm looking for a more clever algorithm.

Any ideas?

ImageStat module is THE answer! Thanks Aaron. I use ImageStat.var to get the variance and it works perfectly.

Here is my piece of code:

from PIL import Image, ImageStat

MONOCHROMATIC_MAX_VARIANCE = 0.005

def is_monochromatic_image(src):
    v = ImageStat.Stat(Image.open(src)).var
    return reduce(lambda x, y: x and y < MONOCHROMATIC_MAX_VARIANCE, v, True)
Grégoire Cachet
  • 2,547
  • 3
  • 29
  • 27

3 Answers3

6

Try the ImageStat module. If the values returned by extrema are the same, you have only a single color in the image.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

First, you should define a distance between two colors. Then you just have to verify for each pixel that it's distance to your color is small enough.

SmuK
  • 1
  • 1
  • Computing the Euclidian distance between each pixel in the 3 dimensions RGB space is theoreticaly fine, but I think it won't work with multi million pixels images... (at least in Python) – Grégoire Cachet Mar 24 '09 at 13:47
  • Why Euclidian distance? You can imagine something else depending on what you want. – SmuK Mar 24 '09 at 13:51
  • The problem is not in the type of distance, but in the fact that the algorithm is O(N^2), N being the number of pixels in the image (I have cases with N=10,000,000) – Grégoire Cachet Mar 24 '09 at 13:59
  • Perhaps i misunderstood your question. If you have to check that each pixel is close enough to a given color, it's linear time. – SmuK Mar 24 '09 at 14:06
  • @Smuk: I don't think it's a given color -- the color they are all closest to could be anything, specific to each image, right? – Doug Kavendek Mar 24 '09 at 14:09
0

Here's a little snippet you could make use of :


import Image

im = Image.open("path_to_image")
width,height = im.size

for w in range(0,width):
  for h in range(0,height):
     # this will hold the value of all the channels
     color_tuple = im.getpixel((w,h))
     # do something with the colors here

Maybe use a hash and store the tuples as the key and it's number of appearances as value?

Geo
  • 93,257
  • 117
  • 344
  • 520