Максимизация дисперсии цветовой палитры

#python #colors #color-palette

#python #Цвет #цвет-палитра

Вопрос:

У меня много цветовых палитр разной длины (все не менее 3 цветов), и я хочу определить способ, с помощью которого я могу извлечь 3 наиболее представительных цвета или найти цвета, которые максимизировали бы «дисперсию» палитры. Например, одна палитра (в шестнадцатеричном формате) равна

 ['#D2691E', '#8B4513', '#A0522D',  '#0000FF', '#668B8B', '#FFC0CB']

  

это в основном три оттенка коричневого, затем два оттенка синего, затем один оттенок розового. Поэтому я бы хотел, чтобы моя «репрезентативная палитра» была одним из оттенков коричневого, одного синего и одного розового, возможно

 ['#D2691E', '#0000FF', '#FFC0CB']

  

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

Комментарии:

1. «K-означает кластеризацию» может быть … docs.opencv.org/master/d1/d5c/tutorial_py_kmeans_opencv.html

2. О, это прекрасно! Я могу просто преобразовать шестнадцатеричное значение в rgb, а затем сделать rgb полностью числовым и использовать кластеризацию k означает для этих 3D-точек. Отлично!

Ответ №1:

Сначала мы преобразуем шестнадцатеричное представление каждого цвета в палитре в его представление RGB.

 from PIL import ImageColor

palette = ['#D2691E', '#8B4513', '#A0522D',  '#0000FF', '#668B8B', '#FFC0CB']
palette_rgb = list(map(lambda x: ImageColor.getcolor(x, "RGB"), palette))
  

Затем мы хотим найти три точки, которые находятся дальше всего друг от друга.
Поскольку размер вашей палитры невелик, мы можем вычислить попарное расстояние между всеми точками, а затем найти 3 цикла с наибольшей длиной пути с помощью перебора методом перебора.

 from scipy.spatial.distance import pdist, squareform
from itertools import product

d = squareform(pdist(np.array(palette_rgb)))
best = None
best_dist = 0
for i, j, k in product(range(len(palette)), repeat=3):
    dist = d[i, j]   d[j, k]   d[k, i]
    if dist > best_dist:
        best = (i, j, k)
        best_dist = dist
furthest_colors = [palette[i] for i in best]
  

В этом случае цвета ['#8B4513', '#0000FF', '#FFC0CB'] максимально удалены друг от друга.

[Обратите внимание, что это решение может быть оптимизировано, но для этого небольшого приложения, вероятно, оно того не стоит.]