【问题标题】:Calculating the closest color in a dictionary to an input计算字典中最接近输入的颜色
【发布时间】:2018-08-29 13:08:30
【问题描述】:

我有一个颜色字典(如下)和一个颜色,例如 #4a7dac,它是 'steelblue'。我想在字典中找到最接近这种颜色的十六进制颜色的名称。所以算法将决定#0000ff 并返回'blue'

colors= {
    "red":"#FF0000",
    "yellow":"#FFFF00",
    "green":"#008000",
    "blue":"#0000FF",
    "black":"#000000",
    "white":"#FFFFFF",
    "gray":"#808080",
}

我曾想过计算某种颜色之间的“距离”,但不知道该怎么写。

【问题讨论】:

  • 我怀疑这是你想要的,但如果你有名字,你可以进行字符串搜索。即“钢蓝”中的“蓝色”。它在您的示例结果中完美运行!

标签: python opencv colors


【解决方案1】:

我们可以创建一个函数,它接受两个十六进制字符串并返回各个颜色分量之间差异的总和。如果您无法理解以下内容的工作原理,请发表评论。

def diff(h1, h2):
    def hexs_to_ints(s):
        return [int(s[i:i+2], 16) for i in range(1,7,2)]
    return sum(abs(i - j) for i, j in zip(*map(hexs_to_ints, (h1, h2))))

我们可以测试它:

>>> diff('#ff00ff', '#0000ff')
255
>>> diff('#0000ff', '#00000a')
245

那么现在,我们可以创建一个函数,使用这个函数来完成任务:

def get_col_name(hex, colors):
    return min([(n,diff(hex,c)) for n,c in colors.items()], key=lambda t: t[1])[0]

不幸的是,这不适用于您的颜色,因为它选择 gray[128, 128, 128] 非常接近 steelblue[74, 125, 172] - 比 blue 更接近 @987654330 @。这意味着与gray 的差异小于与blue 的差异。我会尝试想一个更好的方法,但也许有人有一些见识并可以发表评论?

【讨论】:

  • 也许在 HSV 或类似的色彩空间中工作可能会更好?
  • @DanMašek 我是这么想的,但是gray 的色调毫无意义(可以是任何东西)所以它仍然会搞砸。
  • 是的...饱和度首先检测灰色阴影? |或者en.wikipedia.org/wiki/Color_difference
  • 我尝试了 5 种不同的指标,灰色总是最接近。我想如果 OP 真的想得到蓝色作为结果,那么他们必须定义自己的自定义指标来满足他们的愿望。
  • @DanMašek Yepp,HSV 只是让我们更接近结果:D。
【解决方案2】:

如何将它们转换为 RGB 并找到主导颜色?

例如

RED FF0000         rgb(255,0,0)
BLUE 0000FF        rgb(0,0,255)
steelblue 4A7DAC   rgb(74,125,172)

您最有可能使用 RGB 而不是 HEX 来实现此目标

其余的你可以看到这个算法:https://stackoverflow.com/a/9018100/6198978

编辑 问题是 RGB 和 HEX 计算将无法使用灰色,因为每种颜色与灰色的距离最近。为此,您可以使用颜色的 HSV 值,我正在使用 HSV 编辑代码:D

学到了很多:D

我在这里玩得很开心:

    import math
    colors= {
    "red":"#FF0000",
    "yellow":"#FFFF00",
    "green":"#008000",
    "blue":"#0000FF",
    "black":"#000000",
    "white":"#FFFFFF",
    "grey": "#808080"
}

# function for HSV TAKEN FROM HERE: https://gist.github.com/mathebox/e0805f72e7db3269ec22
def rgb_to_hsv(r, g, b):
    r = float(r)
    g = float(g)
    b = float(b)
    high = max(r, g, b)
    low = min(r, g, b)
    h, s, v = high, high, high

    d = high - low
    s = 0 if high == 0 else d/high

    if high == low:
        h = 0.0
    else:
        h = {
            r: (g - b) / d + (6 if g < b else 0),
            g: (b - r) / d + 2,
            b: (r - g) / d + 4,
        }[high]
        h /= 6

return h, s, v

# COLOR YOU WANT TO TEST TESTED
check = "#808000".lstrip('#')
checkRGB = tuple(int(check[i:i+2], 16) for i in (0, 2 ,4))
checkHSV = rgb_to_hsv(checkRGB[0], checkRGB[1], checkRGB[2])


colorsRGB = {}
colorsHSV = {}

for c, v in colors.items():
    h = v.lstrip('#')
    colorsRGB[c] = tuple(int(h[i:i+2], 16) for i in (0, 2 ,4))

for c, v in colorsRGB.items():
    colorsHSV[c] = tuple(rgb_to_hsv(v[0], v[1], v[2]))

def colourdistanceRGB(color1, color2):
    r = float(color2[0] - color1[0])
    g = float(color2[1] - color1[1])
    b = float(color2[2] - color1[2])
    return math.sqrt( ((abs(r))**2) + ((abs(g))**2) + ((abs(b))**2) )

def colourdistanceHSV(color1, color2):
    dh = min(abs(color2[0]-color1[0]), 360-abs(color2[0]-color1[0])) / 180.0
    ds = abs(color2[1]-color1[1])
    dv = abs(color2[2]-color1[2]) / 255.0
    return math.sqrt(dh*dh+ds*ds+dv*dv)

resultRGB = {}
resultHSV = {}

for k, v in colorsRGB.items():
    resultRGB[k]=colourdistanceRGB(v, checkRGB)

for k,v in colorsHSV.items():
    resultHSV[k]=colourdistanceHSV(v, checkHSV)


#THIS WILL NOT WORK FOR GREY
print("RESULT WITH RGB FORMULA")
print(resultRGB)
print(min(resultRGB, key=resultRGB.get))


#THIS WILL WORK FOR EVEN GREY
print(resultHSV)
print(min(resultHSV, key=resultHSV.get))

#OUTPUT FOR RGB
#check = "#808000"  output=GREY
#check = "#4A7DAC"  output=GREY :D

#OUTPUT FOR RGB
#check = "#808000"  output=GREEN
#check = "#4A7DAC"  output=BLUE:D

【讨论】:

  • 如果您没有得到任何代码部分,请告诉我。 :)
  • 这不能回答问题!?!?您刚刚从字典中删除了gray
  • 是的,RGB 中的颜色计算与灰色混淆了。他必须使用 HSV 颜色计算加上一个完全不同的公式,他也会尝试把它放在这里:D 干杯。
  • @JoeIddon 现在它也适用于 Gray。祝你有美好的一天:D
  • 谢谢,但大多数对象返回“黄色”。没用:/
猜你喜欢
  • 2016-08-26
  • 1970-01-01
  • 2019-07-02
  • 2014-10-26
  • 1970-01-01
  • 2011-05-02
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
相关资源
最近更新 更多