No soy de ninguna manera un experto en color, pero he estado buscando desesperadamente un convertidor de nombres de color RGB/HEX/HSV en python. Después de investigar un poco, creo que hice una solución formidable.De acuerdo con IfLoop en this post:
Si al final utilizando la distancia cartesiana para comparar colores, que normalmente debe traducir los elementos de entrada en forma lineal, el espacio de color de percepción, tales como laboratorio o YUV. Ni RGB ni HSV son lineales, por lo que la distancia cartesiana no se relaciona mucho con dos colores similares realmente. - IfLoop Jul 27 '11 a las 21:15
Por lo tanto, el código de Jochen Ritzel no siempre devolverá el color adecuado, como señaló Graf. Esto se debe a que tanto RGB como HSV son espacios de color lineales. Necesitamos usar un espacio de color perceptual lineal como YUV.
Lo que hice fue tomar el código de Jochen Ritzel y reemplazar el rgb al código hsv con el código rgb a yuv basado en this post.
colors = dict((
((196, 2, 51), "RED"),
((255, 165, 0), "ORANGE"),
((255, 205, 0), "YELLOW"),
((0, 128, 0), "GREEN"),
((0, 0, 255), "BLUE"),
((127, 0, 255), "VIOLET"),
((0, 0, 0), "BLACK"),
((255, 255, 255), "WHITE"),))
def rgb_to_ycc(r, g, b): #http://bit.ly/1blFUsF
y = .299*r + .587*g + .114*b
cb = 128 -.168736*r -.331364*g + .5*b
cr = 128 +.5*r - .418688*g - .081312*b
return y, cb, cr
def to_ycc(color):
""" converts color tuples to floats and then to yuv """
return rgb_to_ycc(*[x/255.0 for x in color])
def color_dist(c1, c2):
""" returns the squared euklidian distance between two color vectors in yuv space """
return sum((a-b)**2 for a,b in zip(to_ycc(c1),to_ycc(c2)))
def min_color_diff(color_to_match, colors):
""" returns the `(distance, color_name)` with the minimal distance to `colors`"""
return min(# overal best is the best match to any color:
(color_dist(color_to_match, test), colors[test]) # (distance to `test` color, color name)
for test in colors)
if __name__ == "__main__":
r = input('r: ')
g = input('g: ')
b = input('b: ')
color_to_match = (r, g, b)
print min_color_diff(color_to_match, colors)
input('Press enter to exit.')
Ahora nos parece terminar con los colores de la derecha casi todo el tiempo:
>>> color_to_match = (2, 2, 0) #Graf's test
>>> print min_color_diff(color_to_match, colors)
>>>
(6.408043991348166e-05, 'BLACK')
Más ejemplos:
>>> color_to_match = (131, 26, 26)
>>> print min_color_diff(color_to_match, colors)
>>>
(0.027661314571288835, 'RED')
>>> color_to_match = (69, 203, 136)
>>> print min_color_diff(color_to_match, colors)
>>>
(0.11505647737959283, 'GREEN')
Hasta ahora parece que mi versión parece estar funcionando casi perfectamente, pero tenga en cuenta: Es probable que si un color rgb es demasiado brillante o demasiado oscuro, es probable que le devuelvan 'BLANCO' o 'NEGRO'. Para resolver esto, deberá agregar colores más claros y más oscuros a su diccionario de colores. Además, agregar más colores como 'BROWN' y 'GRAY' (y así sucesivamente) al diccionario de colores también arrojará mejores resultados.
2,2,0 técnicamente no es negro, al igual que no es 240240240 técnicamente gris. – Chris
Es una aproximación. Es el objetivo de este guión, obviamente. –