使用Python将RGB颜色转换为英语颜色名称,例如“green”

75

我想将一个颜色元组转换为颜色名称,例如 'yellow' 或 'blue'

>>> im = Image.open("test.jpg")
>>> n, color = max(im.getcolors(im.size[0]*im.size[1]))
>>> print color
(119, 172, 152)

Python中是否有一种简单的方法来做到这一点?


2
我觉得我找到了你要找的机器人... http://pypi.python.org/pypi/webcolors/1.3#conversions-from-integer-rgb-triplets - mVChr
1
我不知道是否已经有一个解决方案,但是任何这样的映射都必然是启发式的并且完全主观的...不过这是一个有趣的问题! - Will Vousden
2
你想要“精确”的颜色名称还是近似值?例如,“绿色”显然是(0,255,0)。你希望color((0,254,0))是什么颜色? - Katriel
1
@WillVousden 不一定:有些颜色有官方名称。 - Katriel
你想要的颜色是在HTML中设置字体颜色时使用的相同颜色吗(例如,<font color="red">示例文本</font>)? - Anderson Green
6个回答

120

看起来webcolors可以帮助你做到这一点:

rgb_to_name(rgb_triplet, spec='css3')

将适用于rgb()颜色三元组的3个整数转换为其对应的规范化颜色名称,如果存在任何这样的名称,则有效值为html4、css2、css21和css3,默认值为css3。

例子:

>>> rgb_to_name((0, 0, 0))
'black'

它是可逆的:

>>> name_to_rgb('navy')
(0, 0, 128)

#查找最接近的颜色名称:

然而webcolors会在无法找到所请求的颜色匹配项时引发异常。我编写了一个小的修复程序,可以为所请求的RGB颜色提供最接近匹配的名称。它通过在RGB空间中的欧几里得距离进行匹配。

import webcolors

def closest_colour(requested_colour):
    min_colours = {}
    for key, name in webcolors.CSS3_HEX_TO_NAMES.items():
        r_c, g_c, b_c = webcolors.hex_to_rgb(key)
        rd = (r_c - requested_colour[0]) ** 2
        gd = (g_c - requested_colour[1]) ** 2
        bd = (b_c - requested_colour[2]) ** 2
        min_colours[(rd + gd + bd)] = name
    return min_colours[min(min_colours.keys())]

def get_colour_name(requested_colour):
    try:
        closest_name = actual_name = webcolors.rgb_to_name(requested_colour)
    except ValueError:
        closest_name = closest_colour(requested_colour)
        actual_name = None
    return actual_name, closest_name

requested_colour = (119, 172, 152)
actual_name, closest_name = get_colour_name(requested_colour)

print("Actual colour name:", actual_name, ", closest colour name:", closest_name)

输出:

Actual colour name: None , closest colour name: cadetblue

2
它并不适用于所有RGB组合,例如: print(webcolors.rgb_to_name((231, 201, 186))) 会抛出错误,即“ValueError: '#e7c9ba'在css3中没有定义的颜色名称”。 - Asim
4
@Asim,看起来这段代码是针对早期的版本(可能是Py2)的。 对于webcolors-1.11.1,您需要将for key, name in webcolors.css3_hex_to_names.items():替换为for name, key in webcolors.CSS3_HEX_TO_NAMES.items():。 然后,剩下的代码(除了print语句只需要用f-string和括号包裹)就应该可以工作了。 - Andrew Stewart
5
对我来说,webcolors.CSS3_HEX_TO_NAMES.items()中的for key, name对于使用webcolors-1.11.1的我非常有效。我只是交换了keyname的位置。 - Rajab Shakirov

12

有一个名为pynche的程序,可以将Python中的RGB转换为英文颜色名称。

您可以尝试使用ColorDB.py中的ColorDB.nearest()方法,该方法可以实现您想要的功能。

您可以在此处找到有关此方法的更多信息:ColorDB Pynche


1
提供的链接已经失效。在这里,您可以找到文件ColorDB.py - ands
如果将来有人查看此帖子,这是我为Python3修改的ColorDB.py的修改版本:https://github.com/EricPanDev/python3-colordb/blob/main/ColorDB.py - Eric

12

对于像我这样想要更熟悉颜色名称的人,可以使用由 webcolors 提供的 CSS 2.1 颜色名称

  • aqua: #00ffff
  • black: #000000
  • blue: #0000ff
  • fuchsia: #ff00ff
  • green: #008000
  • grey: #808080
  • lime: #00ff00
  • maroon: #800000
  • navy: #000080
  • olive: #808000
  • purple: #800080
  • red: #ff0000
  • silver: #c0c0c0
  • teal: #008080
  • white: #ffffff
  • yellow: #ffff00
  • orange: #ffa500

只需使用 fraxel 的出色答案和代码来获取最接近的颜色,适配到 CSS 2.1 即可:

def get_colour_name(rgb_triplet):
    min_colours = {}
    for key, name in webcolors.css21_hex_to_names.items():
        r_c, g_c, b_c = webcolors.hex_to_rgb(key)
        rd = (r_c - rgb_triplet[0]) ** 2
        gd = (g_c - rgb_triplet[1]) ** 2
        bd = (b_c - rgb_triplet[2]) ** 2
        min_colours[(rd + gd + bd)] = name
    return min_colours[min(min_colours.keys())]

4
您可以使用matplotlib.colors提供的CSS4列表来获得更高的准确性。例如,import matplotlib.colors as mcmycss4list = mc.CSS4_COLORS - loved.by.Jesus
我不得不使用常量CSS21_HEX_TO_NAMES(大写)才能使其工作。 - John Hunt

3
您的问题的解决方案在于将RGB值映射到HSL颜色空间中。
一旦您将颜色转换到HSL颜色空间,就可以使用H(色调)成分来进行颜色映射。需要注意的是颜色是一个相对主观的概念,因此您需要定义哪些H范围对应于给定的颜色。

2
我发现解决这个问题的最佳方案是来自tux21b在以下帖子中提供的方案:
find the colour name from a hexadecimal colour code
结合我所做的修补(避免除以零的错误)。
从我的理解来看,这是一种近似计算方法,不需要加载大量数据表以获得一个接近的值,并且可以设置您自己所需的颜色集。

1
我会使用字典来确定基础颜色,然后找到最接近的一个。
def get_color_name(rgb):
colors = {
    "red": (255, 0, 0),
    "green": (0, 255, 0),
    "blue": (0, 0, 255),
    "yellow": (255, 255, 0),
    "magenta": (255, 0, 255),
    "cyan": (0, 255, 255),
    "black": (0, 0, 0),
    "white": (255, 255, 255)
}
min_distance = float("inf")
closest_color = None
for color, value in colors.items():
    distance = sum([(i - j) ** 2 for i, j in zip(rgb, value)])
    if distance < min_distance:
        min_distance = distance
        closest_color = color
return closest_color

# Testing
print(get_color_name((255, 0, 0)))  # red
print(get_color_name((0, 255, 0)))  # green
print(get_color_name((0, 0, 255)))  # blue

无法工作。尝试使用(0,5,0)这个颜色,是深绿色。你的脚本说是灰色。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接