Python PIL - Finding Nearest Color (Rounding Colors)
Create a list of colors in your table (I call it colors). Sort the list by the distance to the r, g, b point you are questioning The first element in the list is the closest color
def distance(c1, c2):
(r1,g1,b1) = c1
(r2,g2,b2) = c2
return math.sqrt((r1 - r2)**2 + (g1 - g2) ** 2 + (b1 - b2) **2)
colors = list(rgb_code_dictionary.keys())
closest_colors = sorted(colors, key=lambda color: distance(color, point))
closest_color = closest_colors[0]
code = rgb_code_dictionary[closest_color]
Expanding on mattsap's answer:
We don't need to sort all the colours, since we're only looking for the closest. i.e. We can avoid the computationally expensive sort
and use min
instead.
We also don't need to calculate the absolute distance between the colours, since we're only interested in relative distance. i.e. We can also avoid the "square root" part of Pythagoras.
This gives:
colours = ( (255, 255, 255, "white"),
(255, 0, 0, "red"),
(128, 0, 0, "dark red"),
(0, 255, 0, "green") )
def nearest_colour( subjects, query ):
return min( subjects, key = lambda subject: sum( (s - q) ** 2 for s, q in zip( subject, query ) ) )
print( nearest_colour( colours, (64, 0, 0) ) ) # dark red
print( nearest_colour( colours, (0, 192, 0) ) ) # green
print( nearest_colour( colours, (255, 255, 64) ) ) # white
Of course, once you consider different colour spaces and the contributions of each colour component to its perception of the human eye, there's a whole rabbit hole to go down, as per this question, but that's probably overly overkill for most cases.