使用 matplotlib 按亮度绘制颜色

问题描述 投票:0回答:3

我想从这个不是关于如何确定颜色亮度的问题开始!

所以,我的问题是我正在寻找一种根据亮度排列颜色集合的方法。我有一个函数可以使用here等提到的所有方法来计算亮度。这是一篇很棒的文章,它几乎完全满足了我的需要,但我不确定有几件事,所以以它为例将对我解释我想要实现的目标有很大帮助。

我想使用 matplotlib.pyplot 而不是使用散景来构建具有所有颜色的整个图。 Bokeh 做得很好,但我需要与我项目中的其他东西保持一致,所以我需要用 matplotlib 重建它。我尝试了几种方法,但无法达到我想要的结果。

此外,如果不是按照文章中创建的方式创建情节,我可以创建vertically,类似于答案here中的那些,更具体地说,的答案Petr HurtakKal,只在 square 中做,而不是像他们那样使用 细长的垂直矩形

从上述文章中获取的有用图片: Colors arranged by brightness

numpy matplotlib math colors rgb
3个回答
0
投票

经过几天的挖掘和测试,我认为我设法实现了我想要的,所以我在这里分享我的结果,以防其他人尝试做类似的事情。基本上我使用的是代码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
  1. 生成随机颜色。首先,选择所需的颜色数量,然后计算该数量的四舍五入平方根的幂。这样做以获得一个具有整数平方根的数字,以便稍后获得完美的 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
    
  2. 使用该列表创建一个 pandas 数据框

    color_df = pd.DataFrame({'color': list(color_list)})

  3. 定义绘图函数

    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 和浮点数来解决。

  1. 向 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)

  1. 最后我们通过这个新的“HSP”列对值进行排序并将它们传递给函数

    color_df = color_df.sort_values(by=['HSP'], ascending=True, ignore_index=True)
    

我们得到这个:

在参考文章中,它看起来像这样:


0
投票

我不确定你是否理解...但这是我的建议...

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


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.