4

I am trying to come up with an algorithm to determine the dominant color in an image (either taken from a devices camera or by selecting an existing photo in the photo library). I have written an iOS 8 application in Swift that can grab the RGB value of each pixel in the image, but I don't really know what to do from there.

For pixels that have a distinct dominant color, say RGB(230, 15, 30), it's pretty easy to determine the dominant color. However, I don't really know what to do for pixels that have RGB values where 2 of the 3 values are similar, say RGB(200, 215, 30).

My original thought was to keep 3 counters (one for each color) and add each pixels corresponding RGB values to that counter. At the end I would divide each counter by the total number of pixels and the max of the 3 values would be the dominant color. However, like I mentioned before, when the results are close to each other I can't say that one color necessarily dominates the other.

Just looking for some thoughts and suggestions

steveclark
  • 537
  • 9
  • 27
  • 2
    for RGB(200, 215, 30) dominating color is yellow. Have you considered working with HSL/HSV color models? – MBo Apr 03 '15 at 06:39
  • The color model doesn't matter. I am trying to come up with an algorithm to determine the dominant color of a pixel. I could use an extremely crude algorithm and say that red is the dominant color of RGB(130, 129, 129) but that wouldn't do much for me. With over 16.5 million color combinations the most accurate model wouldn't work either. I am trying to find something that is accurate enough but isn't too specific. For instance red is the dominant color of RGB(65, 0, 0). It definitely has a red hue to it, but it's not what people would consider red. – steveclark Apr 03 '15 at 07:27
  • 1
    what is the main goal of determination the dominant color? How dominant of specific pixel corresponds to overall dominant? Is anything like arithmetic mean of colors a reliable estimation? – MBo Apr 03 '15 at 07:40
  • The arithmetic mean was just my first thought. As I thought about it I realized that I had to take a larger color spectrum (aside from red, green, and blue) into account. I've been thinking about it for hours and I think I actually came up with an acceptable solution. It's very meticulous , but if implemented correctly it should work for what I'm doing. – steveclark Apr 03 '15 at 08:11
  • 1
    now I am really confused you want dominant color of an pixel or of a image (i that case use histogram)? also what is the dominant color in your case? primary colors (R,G,B or C,M,Y) or physical colors (rainbow) or HSV colors (all saturated colors ... same intensity) or what ? ... see this http://stackoverflow.com/a/29286584/2521214 – Spektre Apr 03 '15 at 08:37
  • There is a similar question already - http://stackoverflow.com/questions/3241929/python-find-dominant-most-common-color-in-an-image?rq=1 In short, use some clustering algorithm, like k-means, and then pick the center of the biggest cluster. – vzaguskin Apr 04 '15 at 15:17

4 Answers4

2

I came up with this problem a few weeks ago, and having read many posts talking about it, I found the best method is Hierarchical Quantization presented by this post: http://aishack.in/tutorials/dominant-color/. Also, I have implemented it in python: https://github.com/wenmin-wu/dominant-colors-py . You can install it with pip:pip install dominantcolors and use it as following:

from dominantcolors import get_image_dominant_colors
dominant_colors = get_image_dominant_colors(image_path='/path/to/image_path',num_colors=3) 
Wenmin Wu
  • 1,808
  • 12
  • 24
1

An idea:

  1. First step is to reduce the number of colors, for example "Color Quantization using K-Means". In the example from the link, the number of colors was reduced to 64 from 96K.

  2. Second step is to calculate the ratio for every color and pick the biggest value.

valentin
  • 3,498
  • 15
  • 23
1

You can check my hobby project to find the dominant color in a UIImage: https://github.com/ruuki/ColorFinder

What it does basically is creating clusters of colors of the image and returns the most dominant one in a completion block. You can tweak threshold parameters within the source code. Hope it helps.

Mert Buran
  • 2,989
  • 2
  • 22
  • 34
1

i had a similar task to do, here is my python code:

import picamera
import picamera.array
import numpy as np
from math import sqrt, atan2, degrees

def get_colour_name(rgb):
    rgb = rgb / 255
    alpha = (2 * rgb[0] - rgb[1] - rgb [2])/2
    beta = sqrt(3)/2*(rgb[1] - rgb[2])
    hue = int(degrees(atan2(beta, alpha)))
    std = np.std(rgb)
    mean = np.mean(rgb)
    if hue < 0:
        hue = hue + 360
    if std < 0.055:
        if mean > 0.85:
            colour = "white"
        elif mean < 0.15:
            colour = "black"
        else:
            colour = "grey"
    elif (hue > 50) and (hue <= 160):
        colour = "green"
    elif (hue > 160) and (hue <= 250):
        colour = "blue"
    else:
        colour = "red"
    if DEBUG:
        print rgb, hue, std, mean, colour
    return str(int(hue)) + ": " + colour

def scan_colour:
    with picamera.PiCamera() as camera:
        with picamera.array.PiRGBArray(camera) as stream:
            camera.start_preview()
            camera.resolution = (100, 100)
            for foo in camera.capture_continuous(stream, 'rgb', use_video_port=False, resize=None, splitter_port=0, burst=True):
                stream.truncate()
                stream.seek(0)
                RGBavg = stream.array.mean(axis=0).mean(axis=0)
                colour = get_colour_name(RGBavg)
                print colour

scan_colour()

What i thought is to build the mean Color of all Pixels and to determine the Color out of the hue angle. For getting grayscale answers i wanted to check if the Color is near the middle line of the Color corpus.

Bernd Gewehr
  • 97
  • 1
  • 12