19
votes

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()
6
What do you mean by the image's color - is the image completely one color?Justin Peel
Ya the image is of completely one color......user244470
It is not clear - do you want average color or most frequent color ?Agnius Vasiliauskas

6 Answers

12
votes

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

11
votes

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.

6
votes

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.

3
votes

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.stack.imgur.com/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 :)

2
votes

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)

0
votes

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