Mustafa Hussain
Mustafa Hussain

Reputation: 3

How to get the dominant colors using Pillow

I want to get the colors (256/8-bit) used in an image and the number of times they occur. I was hoping to get this through image.getcolors() but I don't get how to convert the 8-bit color value to RGB.

from PIL import Image

original = Image.open('image.jpg')                   # Open image
reduced = original.convert("P", palette=Image.WEB)   # Convert to WEB palette (216 colors)
color_count = reduced.getcolors()                    # Get list of (count, color)

This works fine and I get a list of tuples with the colors in range 0 to 255. How do I get the RGB value of this 8-bit pixel?

Upvotes: 0

Views: 3487

Answers (2)

Omar Khan
Omar Khan

Reputation: 319

I was looking for something understandable. Numerous stumbling blocks using histograms, palette, and getcolors.

dictc={}
im = Image.open( "top5toronto.jpg" ).convert( 'RGB' )
for i in range( im.width ):
    for j in range( im.height ) :
        h = im.getpixel( ( i,j ) )
        if h in dictc:
            dictc[h] = dictc[h] + 1
        else:
            dictc[h]=1  
#now sort it by values rather than keys descending      
print(sorted(dictc.items(), key=lambda x: x[1], reverse=True) )
im.close()
#returns [((213, 218, 240), 1792), ((213, 217, 242), 550), ((212, 218, 242), 412), ((213, 218, 238), 252), ((215, 217, 240), 142), ((222, 224, 245), 121),

Upvotes: 0

sciroccorics
sciroccorics

Reputation: 2427

PIL's getpalette method returns the list of RGB values for each color index of the image palette. Unfortunately, all RGB values are concatenated into a single list, so you have to post-process the result (i.e. group values 3 by 3) to get what you need. Here is the code:

from PIL import Image

original = Image.open('test.png') # open RGB image
reduced = original.convert("P", palette=Image.WEB) # convert to web palette (216 colors)
palette = reduced.getpalette() # get palette as [r,g,b,r,g,b,...]
palette = [palette[3*n:3*n+3] for n in range(256)] # group 3 by 3 = [[r,g,b],[r,g,b],...]
color_count = [(n, palette[m]) for n,m in reduced.getcolors()]

print(color_count)

Output:

[(111230, [1, 1, 1]), (16063, [23, 23, 23]), (7468, [16, 8, 18]),
 (15, [237, 240, 163]), (3, [253, 249, 160]), ... ]

Upvotes: 4

Related Questions