我想从这个不是关于如何确定颜色亮度的问题开始!
所以,我的问题是我正在寻找一种根据亮度排列颜色集合的方法。我有一个函数可以使用here等提到的所有方法来计算亮度。这是一篇很棒的文章,它几乎完全满足了我的需要,但我不确定有几件事,所以以它为例将对我解释我想要实现的目标有很大帮助。
我想使用 matplotlib.pyplot 而不是使用散景来构建具有所有颜色的整个图。 Bokeh 做得很好,但我需要与我项目中的其他东西保持一致,所以我需要用 matplotlib 重建它。我尝试了几种方法,但无法达到我想要的结果。
此外,如果不是按照文章中创建的方式创建情节,我可以创建vertically,类似于答案here中的那些,更具体地说,的答案Petr Hurtak 和 Kal,只在 square 中做,而不是像他们那样使用 细长的垂直矩形。
经过几天的挖掘和测试,我认为我设法实现了我想要的,所以我在这里分享我的结果,以防其他人尝试做类似的事情。基本上我使用的是代码this文章和this线程的组合。
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()
注意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)
我不确定你是否理解...但这是我的建议...
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def diag_color(color_df, side):
colors = np.zeros((side, side, 3))
first = side - 1
last = - first
cols, lines = np.meshgrid(range(-side, 0), range(side))
end = 0
for offset in range(first, last-1, -1):
n = side - abs(offset)
start = end
end += n
i = np.diagonal(lines, offset=offset)
j = np.diagonal(cols, offset=offset)
colors[i, j] = color_df.iloc[start:end, :3]
return colors
def vertic_color(color_df, side, order='C'):
colors = np.zeros((side, side, 3))
shape = (side, side)
colors[:,:,0] = color_df['R'].to_numpy().reshape(shape, order=order)
colors[:,:,1] = color_df['G'].to_numpy().reshape(shape, order=order)
colors[:,:,2] = color_df['B'].to_numpy().reshape(shape, order=order)
return colors
您可以使用功能
np.flipud
、np.fliplr
和np.rot90
获取其他图像
desired_no_colors = 5000
side = round(np.sqrt(desired_no_colors))
no_colors = side**2
# Generate colors
color_list = np.random.rand(no_colors, 3)
color_df = pd.DataFrame(color_list, columns=['R', 'G', 'B'])
color_df["HSP"] = (0.299*color_df['R'] +
0.587*color_df['G'] +
0.114*color_df['B'])**0.5
color_df.sort_values('HSP', ascending=False, kind='stable', inplace=True)
c1 = diag_color(color_df, side)
c2 = np.fliplr(c1)
c3 = vertic_color(color_df, side, order='C')
c4 = np.flipud(c3)
c5 = vertic_color(color_df, side, order='F')
c6 = np.fliplr(c5)
fig, ax = plt.subplots(3, 2)
[[ax1, ax2], [ax3, ax4], [ax5, ax6]] = ax
ax1.imshow(c1)
ax2.imshow(c2)
ax3.imshow(c3)
ax4.imshow(c4)
ax5.imshow(c5)
ax6.imshow(c6)
for [a, b] in ax:
a.set_axis_off()
b.set_axis_off()
Colour 也可以通过使用更好的感知均匀色彩空间来做到这一点,例如JzAzBz、Oklab、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");