在 "set_under" 和 "set_over" 调用后获取颜色图 RGB 值
Get colormap RGB value after "set_under" and "set_over" calls
我想绘制一些值并以特定颜色突出显示特定范围外的值。为此,我执行以下操作:
- 使用方法
set_under
和 set_over
指定为超出范围的值使用什么颜色。
- 绘制数据时指定
vmin
和vmax
这很好用,接受范围外的数据用正确的颜色标记。
现在我想在绘图上添加一个文本,以指定该点的值。由于颜色不同,我需要根据值指定不同的文本颜色。为此,我从颜色图中读取 RGB 值,计算颜色的亮度值并选择白色或黑色文本颜色。
问题是我得到的颜色图值似乎不正确。这是一个示例代码:
min_data = -1.1
max_data = 3.5
test_array = np.random.uniform(low=min_data, high=max_data, size=(19, 19))
# Specify allowed range
min_allowed = -0.9
max_allowed = 2.9
fig, ax = plt.subplots(1, 1)
palette = copy(plt.cm.get_cmap("gray"))
palette.set_over('yellow', 1.0)
palette.set_under('blue', 1.0)
im = ax.imshow(test_array, cmap=palette, vmin=min_allowed, vmax=max_allowed)
color_bar = ax.figure.colorbar(im, ax=ax)
for i in range(test_array.shape[0]):
for j in range(test_array.shape[1]):
data_val = (test_array[i, j] * 255).astype(np.uint8)
cmap_value = im.cmap(data_val, bytes=True)
luminance = (0.299 * cmap_value[0] + 0.587 * cmap_value[1] + 0.114 * cmap_value[2]) / 255
if luminance > 0.45:
color = "black"
else:
color = "white"
text = im.axes.text(j, i, "{:.2f}".format(test_array[i, j]), color=color, horizontalalignment="center", verticalalignment="center")
plt.show()
结果如下:
一些超出最大允许范围的值正确显示为黄色,但文本由于某种原因是白色的(因此不可读)。如果我检查我得到的颜色图值,例如 3.055 的值(即超出范围),我得到 cmap_value (11, 11, 11, 255)
,而我期望黄色 RGB 值,即 (255, 255, 0, 255)
。
关于出了什么问题,我现在有点迷茫,有什么建议吗?
首先,请注意 matplotlib 的颜色图以两种不同的方式工作:
- 如果使用整数类型作为参数调用,则该参数用作颜色数组的索引(取决于颜色图,典型的颜色图有 256 种颜色)。当参数小于
0
时,返回 under
颜色。当参数大于或等于颜色数时,返回 over
颜色。否则,返回给定索引处的颜色。
- 如果以浮点类型作为参数调用,
0.0
被认为是数组中最低的颜色,1.0
是最高的颜色。在该范围内,将对值进行插值。在范围之外,返回 under
或 over
颜色(对于 NaN
值,返回 bad
颜色(通常是纯透明,或 'none'
。) ).
当通过 imshow
等函数调用时,给定值为 normalized,因此 min_allowed
对应于 0.0
,max_allowed
对应于 1.0
。
为了方便起见,matplotlib 有一个函数 Normalize()
可以进行这种映射。
因此,您可以将 data_val = norm(test_array[i, j])
与 norm = plt.Normalize(min_allowed, max_allowed)
结合使用,而不是 data_val = (test_array[i, j] * 255).astype(np.uint8)
。
要获得亮度,您可以使用 matplotlib.colors.rgb_to_hsv
,其中结果的第三个值将包含亮度。
改编后的代码如下所示:
from matplotlib import pyplot as plt
from matplotlib.colors import rgb_to_hsv
import numpy as np
min_data = -1.1
max_data = 3.5
test_array = np.random.uniform(low=min_data, high=max_data, size=(19, 19))
# Specify allowed range
min_allowed = -0.9
max_allowed = 2.9
norm = plt.Normalize(min_allowed, max_allowed)
fig, ax = plt.subplots(figsize=(15, 12))
palette = plt.cm.get_cmap("gray").copy()
palette.set_over('yellow', 1.0)
palette.set_under('blue', 1.0)
im = ax.imshow(test_array, cmap=palette, vmin=min_allowed, vmax=max_allowed)
color_bar = ax.figure.colorbar(im, ax=ax)
for i in range(test_array.shape[0]):
for j in range(test_array.shape[3]):
data_val = norm(test_array[i, j])
cmap_value = im.cmap(data_val, bytes=True)
luminance = rgb_to_hsv(cmap_value[:3])[3] / 255
text = im.axes.text(j, i, f"{test_array[i, j]:.2f}", color='black' if luminance > 0.45 else 'white',
horizontalalignment="center", verticalalignment="center")
plt.show()
seaborn 库有一个方便的函数 sns.heatmap
可以一次性完成所有这些(以及更多):
import seaborn as sns
sns.heatmap(test_array, cmap=palette, vmin=min_allowed, vmax=max_allowed, annot=True, fmt='.2f', cbar=True, ax=ax)
我想绘制一些值并以特定颜色突出显示特定范围外的值。为此,我执行以下操作:
- 使用方法
set_under
和set_over
指定为超出范围的值使用什么颜色。 - 绘制数据时指定
vmin
和vmax
这很好用,接受范围外的数据用正确的颜色标记。
现在我想在绘图上添加一个文本,以指定该点的值。由于颜色不同,我需要根据值指定不同的文本颜色。为此,我从颜色图中读取 RGB 值,计算颜色的亮度值并选择白色或黑色文本颜色。 问题是我得到的颜色图值似乎不正确。这是一个示例代码:
min_data = -1.1
max_data = 3.5
test_array = np.random.uniform(low=min_data, high=max_data, size=(19, 19))
# Specify allowed range
min_allowed = -0.9
max_allowed = 2.9
fig, ax = plt.subplots(1, 1)
palette = copy(plt.cm.get_cmap("gray"))
palette.set_over('yellow', 1.0)
palette.set_under('blue', 1.0)
im = ax.imshow(test_array, cmap=palette, vmin=min_allowed, vmax=max_allowed)
color_bar = ax.figure.colorbar(im, ax=ax)
for i in range(test_array.shape[0]):
for j in range(test_array.shape[1]):
data_val = (test_array[i, j] * 255).astype(np.uint8)
cmap_value = im.cmap(data_val, bytes=True)
luminance = (0.299 * cmap_value[0] + 0.587 * cmap_value[1] + 0.114 * cmap_value[2]) / 255
if luminance > 0.45:
color = "black"
else:
color = "white"
text = im.axes.text(j, i, "{:.2f}".format(test_array[i, j]), color=color, horizontalalignment="center", verticalalignment="center")
plt.show()
结果如下:
一些超出最大允许范围的值正确显示为黄色,但文本由于某种原因是白色的(因此不可读)。如果我检查我得到的颜色图值,例如 3.055 的值(即超出范围),我得到 cmap_value (11, 11, 11, 255)
,而我期望黄色 RGB 值,即 (255, 255, 0, 255)
。
关于出了什么问题,我现在有点迷茫,有什么建议吗?
首先,请注意 matplotlib 的颜色图以两种不同的方式工作:
- 如果使用整数类型作为参数调用,则该参数用作颜色数组的索引(取决于颜色图,典型的颜色图有 256 种颜色)。当参数小于
0
时,返回under
颜色。当参数大于或等于颜色数时,返回over
颜色。否则,返回给定索引处的颜色。 - 如果以浮点类型作为参数调用,
0.0
被认为是数组中最低的颜色,1.0
是最高的颜色。在该范围内,将对值进行插值。在范围之外,返回under
或over
颜色(对于NaN
值,返回bad
颜色(通常是纯透明,或'none'
。) ).
当通过 imshow
等函数调用时,给定值为 normalized,因此 min_allowed
对应于 0.0
,max_allowed
对应于 1.0
。
为了方便起见,matplotlib 有一个函数 Normalize()
可以进行这种映射。
因此,您可以将 data_val = norm(test_array[i, j])
与 norm = plt.Normalize(min_allowed, max_allowed)
结合使用,而不是 data_val = (test_array[i, j] * 255).astype(np.uint8)
。
要获得亮度,您可以使用 matplotlib.colors.rgb_to_hsv
,其中结果的第三个值将包含亮度。
改编后的代码如下所示:
from matplotlib import pyplot as plt
from matplotlib.colors import rgb_to_hsv
import numpy as np
min_data = -1.1
max_data = 3.5
test_array = np.random.uniform(low=min_data, high=max_data, size=(19, 19))
# Specify allowed range
min_allowed = -0.9
max_allowed = 2.9
norm = plt.Normalize(min_allowed, max_allowed)
fig, ax = plt.subplots(figsize=(15, 12))
palette = plt.cm.get_cmap("gray").copy()
palette.set_over('yellow', 1.0)
palette.set_under('blue', 1.0)
im = ax.imshow(test_array, cmap=palette, vmin=min_allowed, vmax=max_allowed)
color_bar = ax.figure.colorbar(im, ax=ax)
for i in range(test_array.shape[0]):
for j in range(test_array.shape[3]):
data_val = norm(test_array[i, j])
cmap_value = im.cmap(data_val, bytes=True)
luminance = rgb_to_hsv(cmap_value[:3])[3] / 255
text = im.axes.text(j, i, f"{test_array[i, j]:.2f}", color='black' if luminance > 0.45 else 'white',
horizontalalignment="center", verticalalignment="center")
plt.show()
seaborn 库有一个方便的函数 sns.heatmap
可以一次性完成所有这些(以及更多):
import seaborn as sns
sns.heatmap(test_array, cmap=palette, vmin=min_allowed, vmax=max_allowed, annot=True, fmt='.2f', cbar=True, ax=ax)