20

I need to detect the color of an online image and save it in the name of the detected color.

imageurl='http://www.example.com/'
opener1 = urllib2.build_opener()
page1=opener1.open(imageurl)
my_picture=page1.read()
fout = open('images/tony'+image[s], "wb")
fout.write(my_picture)
fout.close()
3
  • What do you mean by the image's color - is the image completely one color? Commented Feb 16, 2010 at 5:38
  • Ya the image is of completely one color...... Commented Feb 16, 2010 at 5:50
  • It is not clear - do you want average color or most frequent color ? Commented Aug 29, 2010 at 17:26

7 Answers 7

12

Use a PIL (Python Image Library) histogram. Loop over the histogram and take the average of pixel color weighed by the pixel count.

Sign up to request clarification or add additional context in comments.

1 Comment

In response to a follow up question, here is a working example demonstrating this approach: gist.github.com/1246268
11

As mentionned by others, PIL is the right library. Here is a function that open an image and look for the main color.

def get_main_color(file):
    img = Image.open(file)
    colors = img.getcolors(256) #put a higher value if there are many colors in your image
    max_occurence, most_present = 0, 0
    try:
        for c in colors:
            if c[0] > max_occurence:
                (max_occurence, most_present) = c
        return most_present
    except TypeError:
        raise Exception("Too many colors in the image")

I hope it helps

Update : passing 256 to getcolors is ok for very small images but may not work in most cases. This value must be increased for bigger images. for example, 1024*1024 is ok for 400 pixels * 300 pixel image.

Comments

6

You should use PIL's Parser from the ImageFile class to read the file in from the url. Then life is pretty easy because you said that the whole image is the same color. Here is some code that builds on your code:

import urllib2
import ImageFile

image_url = "http://plainview.files.wordpress.com/2009/06/black.jpg"
opener1 = urllib2.build_opener()
page1=opener1.open(image_url)

p = ImageFile.Parser()

while 1:
    s = page1.read(1024)
    if not s:
        break
    p.feed(s)

im = p.close()
r,g,b = im.getpixel((0,0))

fout = open('images/tony'+image[s]+"%d%_d%_d"%(r,g,b), "wb")
fout.write(my_picture)
fout.close()

This should append the red green and blue values of the color of the first pixel of the image to the end of the image name. I tested everything up until the fout lines.

2 Comments

Thanks Justin for ur reply it really helped a lot.Actually i got the filename with red green and blue values of the color of the given pixel of the image.Is it possible to get actual color name of that image for the given pixel....or can we convert the obtained pixels to corresponding color name regards Arun
you would need to make a dictionary with RGB values as the keys and the names as the values. You could use the color list at this site, en.wikipedia.org/wiki/List_of_colors, maybe. You would use urllib2 to retrieve the names and the corresponding RGB values.
4

All the answers discuss the methods to find a single color in an image but knowing how to find multiple colors in the image is always beneficial. Especially when you deal with segmentation task's images.

Let's take an image for our explanation

Segmentation Task

Clearly, every class of objects in this picture has a different color.

Let's write a function to download an image from a URL and convert it into a numpy array. It becomes very easy to deal with images in this way.

import numpy as np
import cv2
import urllib
from urllib.request import urlopen
import webcolors
import time

def getImageArray(mask):
    req = requestObject(mask) 
    arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
    im = cv2.imdecode(arr, -1) 
    im = im[:, :, :3] 
    return im

def requestObject(mask):
    temp_req = {'status': 403}
    retry_counter = 1
    while((temp_req['status'] != 200) and (retry_counter <= 10)):
        try:
            req = urlopen(mask)
            temp_req = {"status": 200}
        except:
            print("Retrying for: ", retry_counter)
            temp_req = {"status": 403}
            time.sleep(4)
        retry_counter = retry_counter + 1

    return req

Now, Let's get the image:

url = 'https://i.sstatic.net/Bi16j.jpg'
image = getImageArray(url)

Let's write a function to find all the colors:

def bgr_to_hex(bgr):
   rgb =list(bgr)
   rgb.reverse()
   return webcolors.rgb_to_hex(tuple(rgb))

def FindColors(image):
    color_hex = []
    for i in image:
        for  j in i:
            j = list(j)
            color_hex.append(bgr_to_hex(tuple(j)))
    return set(color_hex)

color_list = FindColors(image)

Try running the above script in your terminal and you'll get the list of hexadecimal codes for all colors in the variable color_list.

Let me know if the code works/doesn't for you :)

3 Comments

Thank you, it works perfectly. I have one more, how could I get several main colors in an image, for example top 10 colors?
@ahbon Happy to know it helped you. Good question, what I can think of is doing one of these approaches: <1> using "image.getcolors()" function in PIL which returns a {color,count}. <2> trying to loop over the image and use 'color_list' to maintain a dictionary for every color in 'color_list' as key with value as count. <3> I've read about Instagram using Color Palette for stories, I'm not sure how they do it but I'm sure their way must be very efficient, probably making an image histogram and picking up the top 10? You should read about it in detail. <>Let me know if any works for you :)
This can be easily achieved by using one-liner in PIL, as was suggested above
2

You could use K-means algorithm to get the K main colours of the image. Here is an example of how to do it: K-means using OpenCV (Python)

Comments

0

You could use the PIL library's Image module to do this. See: http://effbot.org/imagingbook/image.htm.

Comments

0

Trying using pillow for optimal way or quickest way.

Image(yourimagehere).convert('RGB').getcolors()

I tried answer by @Lavish but it was way to resource consuming and has worst case for speed.

REASON: It took way to long on iterating over few images having black dots. and i used pillow which result in few seconds for all images.

:)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.