Many photo sites allow you to search images by their primary colors, at first glance it looks like magic to me, but I don’t believe in magic, so I gave it a second thought and quickly found out that it is quite simple.
The HSV color model describes color (hue) in terms of their shades and their brightness (to read more about how to convert RGB to HSV see this wikipedia link). We can ignore the shades and the brightness and use only the hue. The hue is a number between 0 to 359 and can be represented by a color circle. By looking at this circle, you can easily divide it into color segments, I found 17 colors.
This theory can be easy transformed into a code, first let’s start by converting the image from RGB to HSV, I used the OpenCV library to do that. Then I ignored the S and V, put hue buffer in a histogram by using the numpy library, and then I looped through it using a color range array and created a dictionary of color names and appearances, after that I simply sorted it.
The following python code returns the image’s 3 most dominent colors:
import numpy np import cv2 def getPrimaryColor(img): Hue_color_name =[ [355,360, "Red"], [346,355, "Pink-Red"], [331,345,"Pink"], [321,330,"Magenta-Pink"], [281,320,"Magenta"], [241,280,"Blue-Magenta"], [221,240,"Blue"], [201,220,"Cyan-Blue"], [170,200,"Cyan"], [141,169,"Green-Cyan"], [81,140,"Green"], [61,80,"Yellow-Green"], [51,60,"Yellow"], [41,50,"Orange-Yellow"], [21,40,"Orange-Brown"], [11,20,"Red-Orange"], [1,10, "Red"] ] hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hue , s , v = cv2.split(hsv) hue_hist , bins = np.histogram(hue, 360) hues =defaultdict() i=0 while i<len(Hue_color_name): if Hue_color_name[i] in hues: hues[Hue_color_name[i]]=hues.get(Hue_color_name[i])+np.sum(hue_hist[Hue_color_name[i]:Hue_color_name[i]]) else: hues[Hue_color_name[i]]=(np.sum(hue_hist[Hue_color_name[i]:Hue_color_name[i]])) i+=1 s_hues = sorted(hues, key=hues.get, reverse=True) return s_hues , s_hues , s_hues