Хочу начать с того, что это НЕ вопрос о том, как определить яркость цвета!
Итак, моя проблема в том, что я ищу способ упорядочить набор цветов по их яркости. У меня есть функция, которая вычисляет яркость всеми методами, упомянутыми здесь и другими. Это отличная статья, которая делает почти то, что мне нужно, но я не уверен в нескольких вещах, поэтому наличие ее в качестве примера очень помогло бы мне объяснить, чего я пытаюсь достичь.
Я хочу построить весь сюжет со всеми цветами, используя matplotlib.pyplot вместо боке. Боке отлично справляется со своей задачей, но мне нужно согласовать его с другими вещами в моем проекте, поэтому мне нужно реконструировать его с помощью matplotlib. Я попробовал несколько методов, но не смог добиться желаемых результатов.
Кроме того, было бы здорово, если бы вместо того, чтобы создавать сюжет, как он создан в статье, я мог бы создать его вертикально, как в ответах здесь, точнее, в ответах Петра Хуртака и Каля, только сделайте это в виде квадрата вместо использования вытянутого вертикального прямоугольника, как это сделали они.
Полезные изображения, взятые из упомянутых статей:

После копания и тестирования в течение пары дней, я думаю, мне удалось добиться того, чего я хотел, поэтому я делюсь своими результатами здесь на случай, если кто-то еще попытается сделать что-то подобное. По сути, я использовал комбинацию кода этой статьи и этой ветки.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.collections as collections
from matplotlib.patches import Rectangle
Сгенерируйте случайные цвета. Сначала выберите желаемое количество цветов, а затем получите степень округленного квадратного корня из этого числа. Сделайте это, чтобы получить число, имеющее целочисленный квадратный корень, чтобы позже получить идеальную сетку WIDTH x HEIGHT.
desired_no_colors = 5000
no_colors = round(np.sqrt(desired_no_colors))**2
# Generate colors
color_list = np.array([(np.random.choice(range(256), size=3)) for _ in np.arange(no_colors)])
color_list = color_list / 255 # Convert values to 0-1 range
Создайте фрейм данных pandas с этим списком
color_df = pd.DataFrame({'color': list(color_list)})
Определите функцию построения графика
def plot_color_grid(df):
width = 1
height = 1
nrows = int(df.color.size ** 0.5)
ncols = int(df.color.size ** 0.5)
gap = 0.2
step = width + gap
x_positions = np.arange(0, ncols*step, step)
y_positions = np.arange(0, nrows*step, step)
fig = plt.figure(figsize=(20, 20))
fig.patch.set_alpha(0)
ax = plt.subplot(111, aspect='equal')
ax.axis([0, ncols*step + 1, 0, nrows*step + 1])
pat = []
color_index = -1
for xi in x_positions:
for yi in y_positions:
color_index += 1
sq = Rectangle((yi, xi), width, height, color=df.color[color_index])
pat.append(sq)
pc = collections.PatchCollection(pat, match_original=True)
ax.add_collection(pc)
plt.axis('off')
plt.show()
и это результат, когда мы передаем функции фрейм данных pandas:
Обратите внимание, что figsize довольно большой. Если он меньше, а количество строк и столбцов такое большое (в данном случае 71), то некоторые пробелы начинают исчезать или становятся несовместимыми по размеру. Это также можно решить, повозившись с размером промежутка, размерами прямоугольного патча, точной настройкой figsize с номерами флота.
Добавьте новый столбец в DataFrame со значениями, например, для вычислений HSP.
color_df["HSP"] = color_df.color.apply(lambda x: ((0.299 * x[0]) + (0.587 * x[1]) + (0.114 * x[2])) ** 0.5)
где «x», по-видимому, является кортежем (R, G, B)
И, наконец, мы сортируем значения по этому новому столбцу «HSP» и передаем их функции
color_df = color_df.sort_values(by=['HSP'], ascending=True, ignore_index=True)
и мы получаем это:
который в справочной статье выглядит так:
Цвет позволит сделать это, также используя более однородное для восприятия цветовое пространство, например. JzAzBz, Оклаб, ICtCp:
import colour
import numpy as np
RGB = np.random.random((256, 256, 3))
colour.plotting.plot_image(RGB);
RGB_f = np.reshape(RGB, (-1, 3))
L = colour.convert(RGB_f, "RGB", "Oklab")[..., 0]
colour.plotting.plot_image(
colour.utilities.orient(RGB_f[L.argsort()].reshape(RGB.shape), "Flop"));
Вы также можете отобразить их в виде сетки следующим образом, хотя это происходит намного медленнее при более высоком разрешении:
RGB = np.random.random((64, 64, 3))
RGB_f = np.reshape(RGB, (-1, 3))
L = colour.convert(RGB_f, "RGB", "Oklab")[..., 0]
colour.plotting.plot_multi_colour_swatches(
RGB_f[L.argsort()], columns=RGB.shape[0], spacing=0.5, background_colour = "k");
Вот блокнот Google Colab, если вы хотите попробовать прямо в браузере: https://colab.research.google.com/drive/1SD-ZU1clsHgHFyC0gpIP2fK9xBvYX-oS?usp=sharing
Я знаю о библиотеке цветов, но, поскольку я делаю свои собственные расчеты, мне нужно построить ее самостоятельно, поэтому я специально попросил способ сделать это с помощью matplotlib. Ваш метод - хорошая альтернатива, и даже если он не работает в моем случае, он может помочь кому-то другому.
Я не указывал это, но две приведенные выше процедуры построения графиков используют Matplotlib.
Попробуйте использовать
ascending=Falseвнутриcolor_df.sort_values...