在matplotlib中提取覆盖AxeImage的唯一颜色

2024-09-30 10:30:51 发布

您现在位置:Python中文网/ 问答频道 /正文

这是一个关于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()

输出:
![![enter image description here

有没有一种方法可以从我们最终看到的打印复合图像中提取颜色(例如,创建一个色条)?我已经看到了如何从{}或{}对颜色进行反向工程。但是im2并不是我们最终将看到的复合叠加图像,im1im2似乎只是由plt.show()组合而成。我还试图强制matplotlib使用plt.draw()预先生成最终图像,并使用ax.get_images()提取图像,可惜这两个图像仍然是分开的

我对如何以不同的方式解决这个问题不感兴趣——在无用的尝试之后,我改变了策略并plotted the combined matrix instead。我的问题是,如果我们能在AxesImage显示前不久从中提取出四种颜色。
关于matplotlib如何组合覆盖中的颜色的信息也同样有用。我尝试了im1im2中的颜色总和(显然是错误的,因为它可以超过1)和每个颜色通道的平均值(也错误)


Tags: 图像import信息matplotlib颜色asnpplt
1条回答
网友
1楼 · 发布于 2024-09-30 10:30:51

经过一些挖掘,我找到了如何获得渲染数组的答案。正如我之前尝试的那样,它基于绘制图形,并使用^{}检索渲染器缓冲区的memoryview:

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

输出:
enter image description here

为了在颜色栏中使用识别出的唯一颜色,我绘制了一个临时图像,稍后将其删除。人们也可以从头开始画一个颜色条,但手工控制所有参数却很烦人

更新
我只是注意到颜色条不是必需的,它只是在previous question中很方便。因此,我们也可以创建一个带有补丁的人物图例:

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

输出:
enter image description here

带回家的消息:从后端内存中回溯提取信息要比从后端内存中提取信息容易得多

相关问题 更多 >

    热门问题