Python - Find dominant/most common color in an image Python - Find dominant/most common color in an image python python

Python - Find dominant/most common color in an image


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_functionimport binasciiimport structfrom PIL import Imageimport numpy as npimport scipyimport scipy.miscimport scipy.clusterNUM_CLUSTERS = 5print('reading image')im = Image.open('image.jpg')im = im.resize((150, 150))      # optional, to reduce timear = np.asarray(im)shape = ar.shapear = 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 codescounts, bins = scipy.histogram(vecs, len(codes))    # count occurrencesindex_max = scipy.argmax(counts)                    # find most frequentpeak = 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 coloursimport imageioc = ar.copy()for i, code in enumerate(codes):    c[scipy.r_[scipy.where(vecs==i)],:] = codeimageio.imwrite('clusters.png', c.reshape(*shape).astype(np.uint8))print('saved clustered image')


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

Installation

pip install colorthief

Usage

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

It can also find color pallete

palette = color_thief.get_palette(color_count=6)


Python Imaging Library has method getcolors on Image objects:

im.getcolors() => a list of (count, color) tuples or None

I guess you can still try resizing the image before that and see if it performs any better.