Я никоим образом не специалист по цвету, но я отчаянно искал RGB/HEX/HSV для простого конвертера имен цветов в python. После некоторых исследований, я считаю, что сделал огромное решение.Согласно IfLoop в this post:
Если вы в конечном итоге с помощью декартово расстояние для сравнения цвета, обычно следует переводить вклады в линейную, воспринимаемого цветового пространства, такие как лаборатории или YUV. Ни RGB, ни HSV не являются линейными, и поэтому декартовое расстояние не очень похоже на аналогичные два цвета. - IfLoop Jul 27 '11 at 21:15
Следовательно, код Йохен Ритцеля не всегда возвращает правильный цвет, как указал Граф. Это связано с тем, что RGB и HSV являются линейными цветовыми пространствами. Нам нужно использовать линейное перцептивное цветовое пространство, такое как YUV.
Итак, что я сделал, я взял код Йохен Ритцеля и заменил код rgb на hsv кодом rgb на yuv на основе 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.')
Теперь мы, кажется, в конечном итоге с правильными цветами почти каждый раз:
>>> color_to_match = (2, 2, 0) #Graf's test
>>> print min_color_diff(color_to_match, colors)
>>>
(6.408043991348166e-05, 'BLACK')
Еще примеры:
>>> 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')
До сих пор кажется, что моя версия, кажется, работает почти отлично, но обратите внимание: Вероятно, если цвет rgb слишком яркий или слишком темный, вы, вероятно, получите «WHITE» или «BLACK». Чтобы решить эту проблему, вам нужно добавить более светлые и темные цвета в словарь цветов. Также добавление большего количества цветов, таких как «BROWN» и «GREY» (и т. Д.) В словарь цветов, также принесет лучшие результаты.
2,2,0 технически не черный, так же, как 240240240 не является технически серый. – Chris
Это приближение. Очевидно, это цель этого скрипта. –