Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Find dominant/most common color in an image

I'm looking for a way to find the most dominant color/tone in an image using python. Either the average shade or the most common out of RGB will do. I've looked at the Python Imaging library, and could not find anything relating to what I was looking for in their manual, and also briefly at VTK.

I did however find a PHP script which does what I need, here (login required to download). The script seems to resize the image to 150*150, to bring out the dominant colors. However, after that, I am fairly lost. I did consider writing something that would resize the image to a small size then check every other pixel or so for it's image, though I imagine this would be very inefficient (though implementing this idea as a C python module might be an idea).

However, after all of that, I am still stumped. So I turn to you, SO. Is there an easy, efficient way to find the dominant color in an image.

like image 956
Blue Peppers Avatar asked Jul 13 '10 22:07

Blue Peppers


People also ask

Can you identify which color dominant?

Pure hues from the color wheel are innately dominant. Primary colors, though, are the most dominant (followed by secondary, then tertiary colors) because red, blue and yellow can't be created by mixing other colors. The eye also perceives dominant colors in the foreground of images and documents.

What is the dominant color of an image?

Such colors are also called the dominant colors or the main colors as they are the most pervasive in a photo. The output color palette allows you to create beautiful designs and match the style of your JPG.


2 Answers

Here's code making use of Pillow and Scipy's cluster package.

For simplicity I've hardcoded the filename as "image.jpg". Resizing the image is for speed: if you don't mind the wait, comment out the resize call. When run on this sample image of blue peppers it usually says the dominant colour is #d8c865, which corresponds roughly to the bright yellowish area to the lower left of the two peppers. I say "usually" because the clustering algorithm used has a degree of randomness to it. There are various ways you could change this, but for your purposes it may suit well. (Check out the options on the kmeans2() variant if you need deterministic results.)

from __future__ import print_function import binascii import struct from PIL import Image import numpy as np import scipy import scipy.misc import scipy.cluster  NUM_CLUSTERS = 5  print('reading image') im = Image.open('image.jpg') im = im.resize((150, 150))      # optional, to reduce time ar = np.asarray(im) shape = ar.shape ar = ar.reshape(scipy.product(shape[:2]), shape[2]).astype(float)  print('finding clusters') codes, dist = scipy.cluster.vq.kmeans(ar, NUM_CLUSTERS) print('cluster centres:\n', codes)  vecs, dist = scipy.cluster.vq.vq(ar, codes)         # assign codes counts, bins = scipy.histogram(vecs, len(codes))    # count occurrences  index_max = scipy.argmax(counts)                    # find most frequent peak = codes[index_max] colour = binascii.hexlify(bytearray(int(c) for c in peak)).decode('ascii') print('most frequent is %s (#%s)' % (peak, colour)) 

Note: when I expand the number of clusters to find from 5 to 10 or 15, it frequently gave results that were greenish or bluish. Given the input image, those are reasonable results too... I can't tell which colour is really dominant in that image either, so I don't fault the algorithm!

Also a small bonus: save the reduced-size image with only the N most-frequent colours:

# bonus: save image using only the N most common colours import imageio c = ar.copy() for i, code in enumerate(codes):     c[scipy.r_[scipy.where(vecs==i)],:] = code imageio.imwrite('clusters.png', c.reshape(*shape).astype(np.uint8)) print('saved clustered image') 
like image 83
Peter Hansen Avatar answered Sep 29 '22 18:09

Peter Hansen


Try Color-thief. It is based on Pillow and works awesome.

Installation

pip install colorthief

Usage

from colorthief import ColorThief color_thief = ColorThief('/path/to/imagefile') # get the dominant color dominant_color = color_thief.get_color(quality=1) 

It can also find color pallete

palette = color_thief.get_palette(color_count=6) 
like image 29
Artem Bernatskyi Avatar answered Sep 29 '22 18:09

Artem Bernatskyi