Какой самый точный способ отличить один из 8 цветов?

Представим себе, как работают некоторые основные цвета:

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")

Я хочу иметь функцию, которая получает 3-кортеж в качестве параметра (например, (206, 17, 38)), и она должна вернуть цвет, который это. Например, (206, 17, 38) - красный, а (2, 2, 0) - черный, а (0, 255, 0) - зеленый. Какой самый точный способ выбрать один из 8 цветов?

7
задан Graf 25 August 2010 в 10:54
поделиться

4 ответа

Краткий ответ: используйте евклидово расстояние в независимом от устройства цветовом пространстве (источник: Статья о разнице цветов в Википедии). Поскольку RGB зависит от устройства, вы должны сначала сопоставить свои цвета с одним из независимых от устройства цветовых пространств.

Я предлагаю преобразовать RGB в L a b * . Еще раз процитируем Википедию:

В отличие от цветовых моделей RGB и CMYK, Цвет лаборатории предназначен для приблизительной человеческое зрение.

Вот рецепт для преобразования. Получив значения L , a , b , вычислите евклидово расстояние между вашим цветом и всеми эталонными цветами и выберите ближайший.


На самом деле, модуль Python python-colormath в Google Code (под GPL v3) способен преобразовывать между множеством различных цветовых пространств, а также вычисляет цветовые различия .

12
ответ дан 6 December 2019 в 07:24
поделиться

Используйте rgb_to_hsv для преобразования. Затем сопоставьте цвет с оттенком туалета

В вашем примере это будет КРАСНЫЙ, потому что оттенок точно соответствует

>>> from colorsys import rgb_to_hsv
>>> rgb_to_hsv(192,2,51)
(0.83333333333333337, 0, 192)
>>> rgb_to_hsv(206, 17, 38)
(0.83333333333333337, 0, 206)
>>> 

Вот пример того, как найти ближайшее совпадение

>>> from colorsys import rgb_to_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"),))
>>> 
>>> color_to_match = (206,17,38)
>>> 
>>> print min((abs(rgb_to_hsv(*k)[0]-rgb_to_hsv(*color_to_match)[0]),v) for k,v in colors.items())
(0.0, 'RED')
3
ответ дан 6 December 2019 в 07:24
поделиться

Я надеюсь, что так оно и должно работать: оно преобразует цвета в hsv, затем вычисляет (возведенное в квадрат) евклидово расстояние до всех доступных цветов и возвращает наиболее близкое соответствие.

В основном это исправленная версия кода грызунов.

from colorsys import rgb_to_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 to_hsv( color ): 
    """ converts color tuples to floats and then to hsv """
    return rgb_to_hsv(*[x/255.0 for x in color]) #rgb_to_hsv wants floats!

def color_dist( c1, c2):
    """ returns the squared euklidian distance between two color vectors in hsv space """
    return sum( (a-b)**2 for a,b in zip(to_hsv(c1),to_hsv(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)

color_to_match = (127, 255, 255)
print min_color_diff( color_to_match, colors)

Всё причудливое понимание списков выглядело бы намного лучше с простым классом Color, который поддерживает сортировку и расстояние (но вы можете сделать это для практики ;-).

1
ответ дан 6 December 2019 в 07:24
поделиться

Рассмотрите цвета как векторы и посчитайте расстояние между данным и каждым из них и выберите тот, который наименьший. Простейшее расстояние может быть: |a1 - a2| + |b1 - b2| + |c1 - c2|.

Прочтите это также: http://answers.yahoo.com/question/index?qid=20071202234050AAaDGLf, там описана более подходящая функция расстояния.

3
ответ дан 6 December 2019 в 07:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: