如何在 matplotlib 中插入颜色以使其数量加倍
How to interpolate colours to double its number in matplotlib
我有一个包含 9 种颜色的列表:
colors = [
[0, 82, 246, 255],
[0, 196, 196, 255],
[0, 137, 83, 255],
[1, 233, 11, 255],
[234, 255, 31, 255],
[255, 176, 0, 255],
[247, 19, 0, 255],
[193, 0, 76, 255],
[255, 0, 255, 255]]
我想使用 matplotlib 将插值颜色的数量加倍。我用过 LinearSegmentedColormap.from_list
没有成功:
cm = LinearSegmentedColormap.from_list('test', np.array(colors) / 255,
N=len(colors))
colors = cm(np.linspace(0, 1, 2 * len(colors)))
colors = (colors * 255).astype('uint8')
但是我得到了相同的颜色但重复了:
array([[ 0, 82, 246, 255],
[ 0, 82, 246, 255],
[ 0, 196, 196, 255],
[ 0, 196, 196, 255],
[ 0, 137, 83, 255],
[ 0, 137, 83, 255],
[ 1, 233, 11, 255],
[ 1, 233, 11, 255],
[234, 255, 31, 255],
[234, 255, 31, 255],
[255, 176, 0, 255],
[255, 176, 0, 255],
[247, 18, 0, 255],
[247, 18, 0, 255],
[193, 0, 76, 255],
[193, 0, 76, 255],
[255, 0, 255, 255],
[255, 0, 255, 255]], dtype=uint8)
我怎样才能得到预期的行为,使用我原来的颜色,加上中间的其他颜色?
您的“预期”行为是不可能的:如果您有 9 种颜色,并且您采用 18 个等距内插值,则只有第一个和最后一个值来自您的初始集。要将您的初始集作为列表的一部分,您需要一个倍数减一。
LinearSegmentedColormap.from_list()
的输入不能是 0-255 范围内的 rgb 值:它们必须是 0-1 范围内的浮点值。此外,N=
参数将是内部存储值的数量。如果您将 N
设置为等于原始颜色数,则不会计算任何插值颜色。为了获得最大的灵活性,您可以将 N 设置为 256。
之后,您可以再次将这些值乘以 255 以获得 0-255 范围内的 rgb 值。
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
colors = [[0, 82, 246, 255],
[0, 196, 196, 255],
[0, 137, 83, 255],
[1, 233, 11, 255],
[234, 255, 31, 255],
[255, 176, 0, 255],
[247, 19, 0, 255],
[193, 0, 76, 255],
[255, 0, 255, 255]]
cm = LinearSegmentedColormap.from_list('', np.array(colors) / 255, 256)
colors_18 = (cm(np.linspace(0, 1, len(colors) * 2)) * 255).astype(np.uint8)
colors_17 = (cm(np.linspace(0, 1, len(colors) * 2 - 1)) * 255).astype(np.uint8)
colors_18:
array([[ 0, 82, 246, 255],
[ 0, 135, 222, 255],
[ 0, 189, 198, 255],
[ 0, 171, 149, 255],
[ 0, 143, 96, 255],
[ 0, 170, 57, 255],
[ 0, 216, 23, 255],
[ 69, 239, 16, 255],
[179, 249, 26, 255],
[238, 236, 23, 255],
[248, 199, 9, 255],
[253, 148, 0, 255],
[249, 74, 0, 255],
[240, 16, 8, 255],
[215, 7, 44, 255],
[196, 0, 86, 255],
[225, 0, 170, 255],
[255, 0, 255, 255]], dtype=uint8)
colors_17:
array([[ 0, 82, 246, 255],
[ 0, 139, 220, 255],
[ 0, 195, 195, 255],
[ 0, 166, 138, 255],
[ 0, 137, 82, 255],
[ 0, 185, 46, 255],
[ 3, 233, 11, 255],
[120, 244, 21, 255],
[234, 253, 30, 255],
[244, 214, 14, 255],
[254, 172, 0, 255],
[250, 94, 0, 255],
[245, 18, 1, 255],
[218, 9, 39, 255],
[194, 0, 80, 255],
[225, 0, 170, 255],
[255, 0, 255, 255]], dtype=uint8)
为了在其他应用程序中使用颜色,matplotlib 还提供了一个 to_hex
函数(不适用于数组,仅适用于单个颜色):
from matplotlib.colors import to_hex
colors_18_hex = [to_hex(cm(v)) for v in np.linspace(0, 1, len(colors) * 2)]
# ['#0052f6', '#0088de', '#00bdc7', '#00ac95', '#009060', '#00ab3a', '#01d818', '#46ef11', '#b3fa1a', '#efec18', '#f9c709', '#fe9400', '#fa4a00', '#f11109', '#d7082d', '#c50057', '#e200ab', '#ff00ff']"
这是一个图表,展示了插值是如何进行的:
from matplotlib import pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
colors = np.array([[0, 82, 246, 255], [0, 196, 196, 255], [0, 137, 83, 255], [1, 233, 11, 255], [234, 255, 31, 255], [255, 176, 0, 255], [247, 19, 0, 255], [193, 0, 76, 255], [255, 0, 255, 255]])
fig, axs = plt.subplots(nrows=3, figsize=(15, 5))
plt.colorbar(ScalarMappable(cmap=LinearSegmentedColormap.from_list('', colors / 255, len(colors))),
ticks=np.linspace(0, 1, len(colors)), orientation='horizontal', cax=axs[0])
axs[0].set_title("9 colors, no interpolation")
plt.colorbar(ScalarMappable(cmap=LinearSegmentedColormap.from_list('', colors / 255, 256)),
ticks=np.linspace(0, 1, len(colors) * 2 - 1), orientation='horizontal', cax=axs[1])
axs[1].set_title("positions of 17 colors")
axs[1].xaxis.grid(True, ls='--')
plt.colorbar(ScalarMappable(cmap=LinearSegmentedColormap.from_list('', colors / 255, 256)),
ticks=np.linspace(0, 1, len(colors) * 2), orientation='horizontal', cax=axs[2])
axs[2].set_title("positions of 18 colors")
axs[2].xaxis.grid(True, ls='--')
plt.tight_layout()
plt.show()
我的解决方案类似,但可能更简单。
我有这个 numpy 数组 colvals
:
array([[0.90588235, 0.96078431, 1. , 1. ],
[0.81568627, 0.92156863, 1. , 1. ],
[0.64705882, 0.84705882, 1. , 1. ],
[0.45490196, 0.75294118, 0.98823529, 1. ],
[0.30196078, 0.67058824, 0.96862745, 1. ],
[0.2 , 0.60392157, 0.94117647, 1. ],
[0.13333333, 0.54509804, 0.90196078, 1. ],
[0.10980392, 0.49411765, 0.83921569, 1. ],
[0.09803922, 0.44313725, 0.76078431, 1. ],
[0.09411765, 0.39215686, 0.67058824, 1. ]])
它是 rgba 格式。
转换为颜色图如下所示:
cmp_blue = ListedColormap(colvals)
cmp_blue
现在我让它更细化
inbetween_color_amount = 10
# the 10 is from the original 10 colors, the 4 is for R, G, B, A
newcolvals = np.zeros(shape=(10 * (inbetween_color_amount) - (inbetween_color_amount - 1), 4))
# add first one already
newcolvals[0] = colvals[0]
for i, (rgba1, rgba2) in enumerate(zip(colvals[:-1], np.roll(colvals, -1, axis=0)[:-1])):
for j, (p1, p2) in enumerate(zip(rgba1, rgba2)):
flow = np.linspace(p1, p2, (inbetween_color_amount + 1))
# discard first 1 since we already have it from previous iteration
flow = flow[1:]
newcolvals[ i * (inbetween_color_amount) + 1 : (i + 1) * (inbetween_color_amount) + 1, j] = flow
newcolvals
这次:
cmp_blue = ListedColormap(newcolvals)
cmp_blue
我得到:
我有一个包含 9 种颜色的列表:
colors = [
[0, 82, 246, 255],
[0, 196, 196, 255],
[0, 137, 83, 255],
[1, 233, 11, 255],
[234, 255, 31, 255],
[255, 176, 0, 255],
[247, 19, 0, 255],
[193, 0, 76, 255],
[255, 0, 255, 255]]
我想使用 matplotlib 将插值颜色的数量加倍。我用过 LinearSegmentedColormap.from_list
没有成功:
cm = LinearSegmentedColormap.from_list('test', np.array(colors) / 255,
N=len(colors))
colors = cm(np.linspace(0, 1, 2 * len(colors)))
colors = (colors * 255).astype('uint8')
但是我得到了相同的颜色但重复了:
array([[ 0, 82, 246, 255],
[ 0, 82, 246, 255],
[ 0, 196, 196, 255],
[ 0, 196, 196, 255],
[ 0, 137, 83, 255],
[ 0, 137, 83, 255],
[ 1, 233, 11, 255],
[ 1, 233, 11, 255],
[234, 255, 31, 255],
[234, 255, 31, 255],
[255, 176, 0, 255],
[255, 176, 0, 255],
[247, 18, 0, 255],
[247, 18, 0, 255],
[193, 0, 76, 255],
[193, 0, 76, 255],
[255, 0, 255, 255],
[255, 0, 255, 255]], dtype=uint8)
我怎样才能得到预期的行为,使用我原来的颜色,加上中间的其他颜色?
您的“预期”行为是不可能的:如果您有 9 种颜色,并且您采用 18 个等距内插值,则只有第一个和最后一个值来自您的初始集。要将您的初始集作为列表的一部分,您需要一个倍数减一。
LinearSegmentedColormap.from_list()
的输入不能是 0-255 范围内的 rgb 值:它们必须是 0-1 范围内的浮点值。此外,N=
参数将是内部存储值的数量。如果您将 N
设置为等于原始颜色数,则不会计算任何插值颜色。为了获得最大的灵活性,您可以将 N 设置为 256。
之后,您可以再次将这些值乘以 255 以获得 0-255 范围内的 rgb 值。
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
colors = [[0, 82, 246, 255],
[0, 196, 196, 255],
[0, 137, 83, 255],
[1, 233, 11, 255],
[234, 255, 31, 255],
[255, 176, 0, 255],
[247, 19, 0, 255],
[193, 0, 76, 255],
[255, 0, 255, 255]]
cm = LinearSegmentedColormap.from_list('', np.array(colors) / 255, 256)
colors_18 = (cm(np.linspace(0, 1, len(colors) * 2)) * 255).astype(np.uint8)
colors_17 = (cm(np.linspace(0, 1, len(colors) * 2 - 1)) * 255).astype(np.uint8)
colors_18:
array([[ 0, 82, 246, 255],
[ 0, 135, 222, 255],
[ 0, 189, 198, 255],
[ 0, 171, 149, 255],
[ 0, 143, 96, 255],
[ 0, 170, 57, 255],
[ 0, 216, 23, 255],
[ 69, 239, 16, 255],
[179, 249, 26, 255],
[238, 236, 23, 255],
[248, 199, 9, 255],
[253, 148, 0, 255],
[249, 74, 0, 255],
[240, 16, 8, 255],
[215, 7, 44, 255],
[196, 0, 86, 255],
[225, 0, 170, 255],
[255, 0, 255, 255]], dtype=uint8)
colors_17:
array([[ 0, 82, 246, 255],
[ 0, 139, 220, 255],
[ 0, 195, 195, 255],
[ 0, 166, 138, 255],
[ 0, 137, 82, 255],
[ 0, 185, 46, 255],
[ 3, 233, 11, 255],
[120, 244, 21, 255],
[234, 253, 30, 255],
[244, 214, 14, 255],
[254, 172, 0, 255],
[250, 94, 0, 255],
[245, 18, 1, 255],
[218, 9, 39, 255],
[194, 0, 80, 255],
[225, 0, 170, 255],
[255, 0, 255, 255]], dtype=uint8)
为了在其他应用程序中使用颜色,matplotlib 还提供了一个 to_hex
函数(不适用于数组,仅适用于单个颜色):
from matplotlib.colors import to_hex
colors_18_hex = [to_hex(cm(v)) for v in np.linspace(0, 1, len(colors) * 2)]
# ['#0052f6', '#0088de', '#00bdc7', '#00ac95', '#009060', '#00ab3a', '#01d818', '#46ef11', '#b3fa1a', '#efec18', '#f9c709', '#fe9400', '#fa4a00', '#f11109', '#d7082d', '#c50057', '#e200ab', '#ff00ff']"
这是一个图表,展示了插值是如何进行的:
from matplotlib import pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
colors = np.array([[0, 82, 246, 255], [0, 196, 196, 255], [0, 137, 83, 255], [1, 233, 11, 255], [234, 255, 31, 255], [255, 176, 0, 255], [247, 19, 0, 255], [193, 0, 76, 255], [255, 0, 255, 255]])
fig, axs = plt.subplots(nrows=3, figsize=(15, 5))
plt.colorbar(ScalarMappable(cmap=LinearSegmentedColormap.from_list('', colors / 255, len(colors))),
ticks=np.linspace(0, 1, len(colors)), orientation='horizontal', cax=axs[0])
axs[0].set_title("9 colors, no interpolation")
plt.colorbar(ScalarMappable(cmap=LinearSegmentedColormap.from_list('', colors / 255, 256)),
ticks=np.linspace(0, 1, len(colors) * 2 - 1), orientation='horizontal', cax=axs[1])
axs[1].set_title("positions of 17 colors")
axs[1].xaxis.grid(True, ls='--')
plt.colorbar(ScalarMappable(cmap=LinearSegmentedColormap.from_list('', colors / 255, 256)),
ticks=np.linspace(0, 1, len(colors) * 2), orientation='horizontal', cax=axs[2])
axs[2].set_title("positions of 18 colors")
axs[2].xaxis.grid(True, ls='--')
plt.tight_layout()
plt.show()
我的解决方案类似,但可能更简单。
我有这个 numpy 数组 colvals
:
array([[0.90588235, 0.96078431, 1. , 1. ],
[0.81568627, 0.92156863, 1. , 1. ],
[0.64705882, 0.84705882, 1. , 1. ],
[0.45490196, 0.75294118, 0.98823529, 1. ],
[0.30196078, 0.67058824, 0.96862745, 1. ],
[0.2 , 0.60392157, 0.94117647, 1. ],
[0.13333333, 0.54509804, 0.90196078, 1. ],
[0.10980392, 0.49411765, 0.83921569, 1. ],
[0.09803922, 0.44313725, 0.76078431, 1. ],
[0.09411765, 0.39215686, 0.67058824, 1. ]])
它是 rgba 格式。
转换为颜色图如下所示:
cmp_blue = ListedColormap(colvals)
cmp_blue
现在我让它更细化
inbetween_color_amount = 10
# the 10 is from the original 10 colors, the 4 is for R, G, B, A
newcolvals = np.zeros(shape=(10 * (inbetween_color_amount) - (inbetween_color_amount - 1), 4))
# add first one already
newcolvals[0] = colvals[0]
for i, (rgba1, rgba2) in enumerate(zip(colvals[:-1], np.roll(colvals, -1, axis=0)[:-1])):
for j, (p1, p2) in enumerate(zip(rgba1, rgba2)):
flow = np.linspace(p1, p2, (inbetween_color_amount + 1))
# discard first 1 since we already have it from previous iteration
flow = flow[1:]
newcolvals[ i * (inbetween_color_amount) + 1 : (i + 1) * (inbetween_color_amount) + 1, j] = flow
newcolvals
这次:
cmp_blue = ListedColormap(newcolvals)
cmp_blue
我得到: