哪种方法可以区分8种颜色中的一种?

Gra*_*raf 7 python rgb

想象一下我们如何使用一些基本颜色:

RED = Color ((196, 2, 51), "RED")
ORANGE = Color ((255, 165, 0), "ORANGE")
YELLOW = Color ((255, 205, 0), "YELLOW")
GREEN = Color ((0, 128, 0), "GREEN")
BLUE = Color ((0, 0, 255), "BLUE")
VIOLET = Color ((127, 0, 255), "VIOLET")
BLACK = Color ((0, 0, 0), "BLACK")
WHITE = Color ((255, 255, 255), "WHITE")
Run Code Online (Sandbox Code Playgroud)

我想要一个函数,它获得一个3元组作为参数(如(206,17,38)),它应该返回它的颜色.例如,(206,17,38)是红色,(2,2,0)是黑色,(0,255,0)是绿色.哪种选择8种颜色最精确?

Bol*_*olo 12

简答:在设备无关的颜色空间中使用欧几里德距离(来源:维基百科中的色差文章).由于RGB与设备有关,因此您应首先将颜色映射到与设备无关的颜色空间之一.

我建议将RGB转换为L a b*.再次引用维基百科:

与RGB和CMYK颜色模型不同,Lab颜色设计用于近似人类视觉.

这是进行转换的方法.一旦你的L,a,b值,计算出你的色彩和所有参考颜色之间的欧氏距离,选择最接近的一个.


实际上,Google Code上的python-colormath Python模块(在GPL v3下)能够在许多不同的颜色空间之间进行转换并计算颜色差异.


Him*_*Das 5

我绝不是色彩专家,但我一直在拼命寻找RGB / HEX / HSV到python中的简单颜色名称转换器。经过一些研究,我相信我提出了一个强大的解决方案。根据IfLoop在这篇文章中

如果最终使用笛卡尔距离比较颜色,则通常应将输入转换为线性的,可感知的颜色空间,例如Lab或Yuv。RGB和HSV都不是线性的,因此笛卡尔距离与相似的两种颜色实际上并没有太大关系。– IfLoop 11年7月27日在21:15

因此,正如Graf指出的那样,Jochen Ritzel的代码不会总是返回正确的颜色。这是因为RGB和HSV都是线性色彩空间。我们需要使用线性感知色彩空间,例如YUV。

因此,根据这篇文章,我所做的是我接受了Jochen Ritzel的代码,并用rgb转换为yuv代码替换了rgb到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.')
Run Code Online (Sandbox Code Playgroud)

现在,我们似乎几乎每次都能获得正确的颜色:

>>> color_to_match = (2, 2, 0) #Graf's test
>>> print min_color_diff( color_to_match, colors)
>>> 
(6.408043991348166e-05, 'BLACK')
Run Code Online (Sandbox Code Playgroud)

更多示例:

>>> 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')
Run Code Online (Sandbox Code Playgroud)

到目前为止,我的版本似乎工作得几乎完美,但是请注意:如果rgb颜色太亮或太暗,则很可能会返回“白”或“黑”。要解决此问题,您需要在颜色字典中添加较浅和较深的颜色。在颜色字典中添加更多颜色,例如“棕色”和“灰色”(等等)也将返回更好的结果。