как выбрать пространство HSV с единообразием восприятия - PullRequest
1 голос
/ 17 июня 2020

Я могу выбрать пространство HSV (фиксированное s и v) так:

hue_gradient = np.linspace(0, 360,16)#sample 16 different equally spread hues
hsv = np.ones(shape=(1, len(hue_gradient), 3), dtype=float)*0.75#set sat and brightness to 0.75
hsv[:, :, 0] = hue_gradient#make one array
hsv


array([[[  0.  ,   0.75,   0.75],
        [ 24.  ,   0.75,   0.75],
        [ 48.  ,   0.75,   0.75],
        [ 72.  ,   0.75,   0.75],
        [ 96.  ,   0.75,   0.75],
        [120.  ,   0.75,   0.75],
        [144.  ,   0.75,   0.75],
        [168.  ,   0.75,   0.75],
        [192.  ,   0.75,   0.75],
        [216.  ,   0.75,   0.75],
        [240.  ,   0.75,   0.75],
        [264.  ,   0.75,   0.75],
        [288.  ,   0.75,   0.75],
        [312.  ,   0.75,   0.75],
        [336.  ,   0.75,   0.75],
        [360.  ,   0.75,   0.75]]])

Однако все эти цвета не воспринимаются одинаково *

Я могу подтвердить это, запустив уравнение deltaE2000 (delta_e_cie2000) из пакета colormath. Результат выглядит так:

enter image description here

Значения представляют собой значения deltaE, цвета 0-15 соответствуют положениям углов оттенка. Как видите, некоторые цвета ниже порога восприятия.

enter image description here

Итак, вопрос : могу ли я равномерно выбрать hsv-пространство с фиксированными s и v? Если нет, как я могу пробовать пространство таким образом, чтобы цвета располагались по соседству со сходным оттенком, при этом s и v менялись настолько мало, насколько это необходимо?

1 Ответ

0 голосов
/ 18 июня 2020

Я пробовал несколько вещей, но в конце концов это сработало. Он равномерно разделяет значения оттенков, а затем подталкивает их до тех пор, пока они не станут однородными по восприятию.

from colormath import color_objects, color_diff, color_conversions

SAT = 1.0
VAL = 1.0
COLOR_COUNT = 16
NUDGE_SIZE = 0.2


def hue_to_lab(hue):
    return color_conversions.convert_color(
        color_objects.HSVColor(hue, SAT, VAL), color_objects.LabColor
    )


def get_equally_spaced(number, iters=100):
    # Create hues with evenly spaced values in hue space
    hues = [360 * x / number for x in range(number)]
    for _ in range(iters):
        # Convert hues to CIELAB colours
        cols = [hue_to_lab(h) for h in hues]
        # Work out the perceptual differences between pairs of adjacent
        # colours
        deltas = [
            color_diff.delta_e_cie2000(cols[i], cols[i - 1]) for i in range(len(cols))
        ]
        # Nudge each hue towards whichever adjacent colour is furthest
        # away perceptually
        nudges = [
            (deltas[(i + 1) % len(deltas)] - deltas[i]) * NUDGE_SIZE
            for i in range(len(deltas))
        ]
        hues = [(h + d) % 360 for (h, d) in zip(hues, nudges)]
    return hues


print(get_equally_spaced(COLOR_COUNT, iters=1000))

NUDGE_SIZE может испортить его, если он установлен неправильно (изменение его на 2 здесь не приводит к ничему, напоминающему радугу) и я думаю, что лучшее значение зависит от того, сколько итераций вы делаете и сколько цветов вы генерируете. Значения delta_e_cie2000 для соседних цветов (с заданными настройками) равны [16.290288769191324, 16.290288766871242, 16.290288753399196, 16.290288726186013, 16.290288645469946, 16.290288040904777, 16.290288035037598, 16.290288051426675, 16.290288079361915, 16.290288122430887, 16.290288180738187, 16.290288265350803, 16.290288469198916, 16.29028866254433, 16.2902887136652], которые довольно однородны: я думаю, что iters=1000 является излишним для этих нескольких цветов. Я использую здесь обычные списки, но он должен преобразовываться в NumPy массивы - и, вероятно, работать немного быстрее.

Алгоритм работает следующим образом:

  1. Начните с наивного равномерно распределенный набор оттенков.
  2. Рассчитайте перцепционные различия между соседними парами цветов.
  3. Слегка сдвиньте каждый оттенок к тому из его соседей, который больше всего отличается от него в восприятии. Размер этого движения пропорционален NUDGE_SIZE.
  4. Повторите 2–3, пока оттенки не изменятся iters раз.
...