使用比率绘制 RGB 颜色

Plotting RGB colors using ratios

我目前正在从事一个需要将 RGB 颜色绘制为图形的项目。颜色存储在 nx3 数组中,其中 n 是颜色数,3 是 RGB 值。

例如:

colors = [[0.70248465, 0.10704011, 0.00900125], [0.0067905 , 0.27228963, 0.6428365 ], [0.00859376, 0.36948201, 0.18334154], [0.85125032, 0.65469019, 0.04035713]

假设我有一个数组,用于存储第一种颜色的大小比率。

例如:

ratios = [1,1/2,1/3,1/5]

我想做的是绘制这些颜色但保持大小比例。我当前的功能是:

def plot(colors):

    plt.imshow([colors])
    plt.axis('off')

    plt.show()

绘制颜色如下:

而我想要这样的东西:

这应该可以解决问题:

EXPAND_BY = 30

expanded_colors = []
for c, r in zip(colors, ratios):
    expanded_colors += [c] * int(EXPAND_BY * r)    
colors = expanded_colors

在选择 EXPAND_BY 的值时要小心。比率的最大公分母是正确的,但任何 large-ish 值都应该给出视觉上令人信服的结果。

它是如何工作的?

Imshow 假设它得到的每个 RGB 三元组是一个“像素”。该解决方案只是根据其大小比例重复每个条目(像素)。

对于较大的数据,内存效率可能不是很高,但代码效率很高 - 只有少数额外的行:)

下面的方法使用了ListedColormap。这些比率乘以某个足够大的因子,四舍五入并用作重复因子。

import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import numpy as np

colors = [[0.70248465, 0.10704011, 0.00900125], [0.0067905, 0.27228963, 0.6428365], [0.00859376, 0.36948201, 0.18334154], [0.85125032, 0.65469019, 0.04035713]]

ratios = [1, 1/2, 1/3, 1/5]
ratios_int = (np.array(ratios) * 60).round().astype(int)

plt.imshow(np.repeat(np.arange(len(colors)), ratios_int).reshape(1, -1),
           cmap=ListedColormap(colors), # the given list of colors
           aspect=ratios_int.sum()/10)  # 1:10 aspect ratio for the image
plt.axis('off')
plt.show()

ratio_int 是一个仅包含整数的数组,但其比率与给定的小数比率相似。如果所有的分母都是整数,可以乘以分母的最小公倍数。在示例中,60 用作乘数。一般来说,对于不能表示为小整数之间的比率的分数,足够大的乘数就可以完成这项工作。即使这会在精确比率之间产生微小的差异,这种微小的差异在生成的图像中也不会很明显。

np.arange(len(colors))给出数组0,1,2,3,...。 Matplotlib 的颜色映射会将这些映射到 ListedColormap 中的相应颜色。 np.repeat([0,1,2,3], [60,30,20,12]) 将重复 0 60 次,1 重复 30 次,等等。因此,这将创建一个数组,其中每个数字重复对应于给定的比率. .reshape(1,-1) 将此一维数组转换为适合 imshow 的二维数组。第一个维度是 1,第二个维度等于一维数组的长度(-1 表示“根据需要获取尽可能多的内容,使初始数组和重塑后的数组具有相同数量的元素” ).