我绝不是一个颜色专家,但我一直在拼命寻找一个RGB/HEX/HSV到python中的简单颜色名称转换器。在做了一些研究后,我相信我提出了一个强大的解决方案。根据IfLoop在this post:
如果最终使用笛卡尔距离来比较颜色,正常的输入转换成线性,感知颜色空间,如实验室或YUV。 RGB和HSV都不是线性的,所以笛卡尔距离实际上与相似的两种颜色没有多大关系。 - IfLoop 11年7月27日在21:15
因此,乔兴Ritzel的代码不会总是返回正确的颜色,正如格拉夫指出的。这是因为RGB和HSV都是线性色彩空间。我们需要使用像YUV这样的线性感知色彩空间。
所以我做的是我拿走了Jochen Ritzel的代码,并用rgb替换了rgb到基于this post的yuv代码的hsv代码。
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颜色太亮或太暗,可能会返回'白色'或'黑色'。为了解决这个问题,你需要为你的颜色词典添加更轻更深的颜色。同时向颜色词典中添加更多颜色,如“BROWN”和“GREY”(等等)也会返回更好的结果。
2,2,0在技术上并不黑,就像240240240不技术上灰色。 – Chris 2010-08-25 10:59:06
这是一个近似值。这显然是这个脚本的目标。 – 2010-08-25 11:00:39