在 matplotlib 中提取叠加 AxesImage 的独特颜色
Extracting unique colors of an overlay AxesImage in matplotlib
这是一个关于 matplotlib 图像中颜色信息的问题。
我用以下代码绘制了两个数组:
import numpy as np
import matplotlib.pyplot as plt
M1 = ([1, 2, 3, np.nan],
[4, 5, np.nan, np.nan],
[6, 7, 8, 9])
M2 = ([np.nan, np.nan, np.nan, np.nan],
[np.nan, 1, 2, 3],
[np.nan, 4, 5, 6])
M1arr = ~np.isnan(M1)
M2arr = ~np.isnan(M2)
fig, ax = plt.subplots()
im1 = ax.imshow(M1arr, cmap="Reds", alpha=0.5)
im2 = ax.imshow(M2arr, cmap="Blues", alpha=0.5)
#color_array = mystery_function(im1, im2, ax, fig)
plt.show()
输出:
有没有办法从我们最终看到的绘制的复合图像中提取颜色(例如,创建一个颜色条)?我已经看到 如何对 im1
或 im2
中的颜色进行逆向工程。 BUT im2
并不是我们最终会看到的复合叠加图像,im1
和 im2
貌似只是由 plt.show()
组合而成。我还试图强制 matplotlib 使用 plt.draw()
预先生成最终图像并使用 ax.get_images()
提取图像,唉,两张图像仍然分开。
我对如何以不同的方式解决这个问题不感兴趣 - 经过无用的尝试,我改变了我的策略和 。我的问题是,如果我们可以在 AxesImage
显示之前不久从中提取四种颜色。
同样有用的是有关 matplotlib 如何组合叠加层中的颜色的信息。我尝试了 im1
和 im2
中的颜色总和(显然是错误的,因为它可以超过 1)和每个颜色通道的平均值(也是错误的)。
经过一番挖掘,我找到了如何获取渲染数组的答案。它基于绘制图形,正如我之前尝试的那样,并使用 fig.canvas.buffer_rgba()
:
检索渲染器缓冲区的内存视图
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
M1 = ([1, 2, 3, np.nan],
[4, 5, np.nan, np.nan],
[6, 7, 8, 9])
M2 = ([np.nan, np.nan, np.nan, np.nan],
[np.nan, 1, 2, 3],
[np.nan, 4, 5, 6])
M1arr = ~np.isnan(M1)
M2arr = ~np.isnan(M2)
fig, ax = plt.subplots()
ax.imshow(M1arr, cmap="Reds", alpha=0.5)
ax.imshow(M2arr, cmap="Blues", alpha=0.5)
#get image without axis, so only the colors plotted in the overlay image are considered
ax.axis("off")
#get rgba values from image predrawn by the renderer
fig.canvas.draw()
im = fig.canvas.buffer_rgba()
#identify unique colors, containing white background
all_colors = np.unique(np.asarray(im).reshape(-1, 4), axis=0)
#remove white background color
colors_image = all_colors[:-1].reshape(4, -1)
#turn axes back on
ax.axis("on")
#determine cmap and norm for colorbar
cmapM1M2 = colors.ListedColormap(colors_image[::-1]/255)
normM1M2 = colors.BoundaryNorm(np.arange(-0.5,4), 4)
#temporarily draw image of zeroes to get scalar mappable for colorbar
temp_im = ax.imshow(np.zeros(M1arr.shape), cmap=cmapM1M2, norm=normM1M2)
cbt = plt.colorbar(temp_im, ticks=np.arange(4), fraction=0.035)
#and remove this temporary image
temp_im.remove()
#label colorbar
cbt.ax.set_yticklabels(["M1 & M2 NaN", "only M1 values", "only M2 values", "M1 & M2 values"])
#and overlay image
ax.set_xticks(np.arange(M1arr.shape[1]))
ax.set_yticks(np.arange(M1arr.shape[0]))
plt.tight_layout()
plt.show()
输出:
为了在颜色栏中使用已识别的唯一颜色,我绘制了一个临时图像,稍后将其删除。人们也可以从头开始绘制颜色条,但结果证明手动控制所有参数相当烦人。
更新
我只是注意到不需要颜色条,它在 中很方便。因此,我们也可以只创建一个带有补丁的图形图例:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
M1 = ([1, 2, 3, np.nan],
[4, 5, np.nan, np.nan],
[6, 7, 8, 9])
M2 = ([np.nan, np.nan, np.nan, np.nan],
[np.nan, 1, 2, 3],
[np.nan, 4, 5, 6])
M1arr = ~np.isnan(M1)
M2arr = ~np.isnan(M2)
fig, ax = plt.subplots()
ax.imshow(M1arr, cmap="Reds", alpha=0.5)
ax.imshow(M2arr, cmap="Blues", alpha=0.5)
#after this, I want to extract the colors of the overlay image
#get image without axis, so only the colors plotted in the overlay image are considered
ax.axis("off")
#get rgba values from image predrawn by the renderer
fig.canvas.draw()
im = fig.canvas.buffer_rgba()
#identify unique colors, containing white background
all_colors = np.unique(np.asarray(im).reshape(-1, 4), axis=0)
#remove white background color
colors_image = all_colors[:-1].reshape(4, -1)
#turn axes back on
ax.axis("on")
#and overlay image
ax.set_xticks(np.arange(M1arr.shape[1]))
ax.set_yticks(np.arange(M1arr.shape[0]))
#create legend with patches of the four colors
categories = ["M1 & M2 NaN", "only M1 values", "only M2 values", "M1 & M2 values"]
fig.legend(handles=[mpatches.Patch(facecolor=col, edgecolor="k", label=categories[3-i]) for i, col in enumerate(colors_image/255)],
loc="upper center", ncol = 2)
plt.show()
输出:
带回家消息: 比从后端内存中追溯提取信息更容易。
这是一个关于 matplotlib 图像中颜色信息的问题。
我用以下代码绘制了两个数组:
import numpy as np
import matplotlib.pyplot as plt
M1 = ([1, 2, 3, np.nan],
[4, 5, np.nan, np.nan],
[6, 7, 8, 9])
M2 = ([np.nan, np.nan, np.nan, np.nan],
[np.nan, 1, 2, 3],
[np.nan, 4, 5, 6])
M1arr = ~np.isnan(M1)
M2arr = ~np.isnan(M2)
fig, ax = plt.subplots()
im1 = ax.imshow(M1arr, cmap="Reds", alpha=0.5)
im2 = ax.imshow(M2arr, cmap="Blues", alpha=0.5)
#color_array = mystery_function(im1, im2, ax, fig)
plt.show()
输出:
有没有办法从我们最终看到的绘制的复合图像中提取颜色(例如,创建一个颜色条)?我已经看到 im1
或 im2
中的颜色进行逆向工程。 BUT im2
并不是我们最终会看到的复合叠加图像,im1
和 im2
貌似只是由 plt.show()
组合而成。我还试图强制 matplotlib 使用 plt.draw()
预先生成最终图像并使用 ax.get_images()
提取图像,唉,两张图像仍然分开。
我对如何以不同的方式解决这个问题不感兴趣 - 经过无用的尝试,我改变了我的策略和 AxesImage
显示之前不久从中提取四种颜色。
同样有用的是有关 matplotlib 如何组合叠加层中的颜色的信息。我尝试了 im1
和 im2
中的颜色总和(显然是错误的,因为它可以超过 1)和每个颜色通道的平均值(也是错误的)。
经过一番挖掘,我找到了如何获取渲染数组的答案。它基于绘制图形,正如我之前尝试的那样,并使用 fig.canvas.buffer_rgba()
:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors
M1 = ([1, 2, 3, np.nan],
[4, 5, np.nan, np.nan],
[6, 7, 8, 9])
M2 = ([np.nan, np.nan, np.nan, np.nan],
[np.nan, 1, 2, 3],
[np.nan, 4, 5, 6])
M1arr = ~np.isnan(M1)
M2arr = ~np.isnan(M2)
fig, ax = plt.subplots()
ax.imshow(M1arr, cmap="Reds", alpha=0.5)
ax.imshow(M2arr, cmap="Blues", alpha=0.5)
#get image without axis, so only the colors plotted in the overlay image are considered
ax.axis("off")
#get rgba values from image predrawn by the renderer
fig.canvas.draw()
im = fig.canvas.buffer_rgba()
#identify unique colors, containing white background
all_colors = np.unique(np.asarray(im).reshape(-1, 4), axis=0)
#remove white background color
colors_image = all_colors[:-1].reshape(4, -1)
#turn axes back on
ax.axis("on")
#determine cmap and norm for colorbar
cmapM1M2 = colors.ListedColormap(colors_image[::-1]/255)
normM1M2 = colors.BoundaryNorm(np.arange(-0.5,4), 4)
#temporarily draw image of zeroes to get scalar mappable for colorbar
temp_im = ax.imshow(np.zeros(M1arr.shape), cmap=cmapM1M2, norm=normM1M2)
cbt = plt.colorbar(temp_im, ticks=np.arange(4), fraction=0.035)
#and remove this temporary image
temp_im.remove()
#label colorbar
cbt.ax.set_yticklabels(["M1 & M2 NaN", "only M1 values", "only M2 values", "M1 & M2 values"])
#and overlay image
ax.set_xticks(np.arange(M1arr.shape[1]))
ax.set_yticks(np.arange(M1arr.shape[0]))
plt.tight_layout()
plt.show()
输出:
为了在颜色栏中使用已识别的唯一颜色,我绘制了一个临时图像,稍后将其删除。人们也可以从头开始绘制颜色条,但结果证明手动控制所有参数相当烦人。
更新
我只是注意到不需要颜色条,它在
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
M1 = ([1, 2, 3, np.nan],
[4, 5, np.nan, np.nan],
[6, 7, 8, 9])
M2 = ([np.nan, np.nan, np.nan, np.nan],
[np.nan, 1, 2, 3],
[np.nan, 4, 5, 6])
M1arr = ~np.isnan(M1)
M2arr = ~np.isnan(M2)
fig, ax = plt.subplots()
ax.imshow(M1arr, cmap="Reds", alpha=0.5)
ax.imshow(M2arr, cmap="Blues", alpha=0.5)
#after this, I want to extract the colors of the overlay image
#get image without axis, so only the colors plotted in the overlay image are considered
ax.axis("off")
#get rgba values from image predrawn by the renderer
fig.canvas.draw()
im = fig.canvas.buffer_rgba()
#identify unique colors, containing white background
all_colors = np.unique(np.asarray(im).reshape(-1, 4), axis=0)
#remove white background color
colors_image = all_colors[:-1].reshape(4, -1)
#turn axes back on
ax.axis("on")
#and overlay image
ax.set_xticks(np.arange(M1arr.shape[1]))
ax.set_yticks(np.arange(M1arr.shape[0]))
#create legend with patches of the four colors
categories = ["M1 & M2 NaN", "only M1 values", "only M2 values", "M1 & M2 values"]
fig.legend(handles=[mpatches.Patch(facecolor=col, edgecolor="k", label=categories[3-i]) for i, col in enumerate(colors_image/255)],
loc="upper center", ncol = 2)
plt.show()
输出:
带回家消息: