编辑3:
已经澄清了根本问题是:
如何在由imshow
生成的matplotlib图像前面放置一个“黑色和透明”的遮罩层?该遮罩层应该来源于以前绘制的matplotlib黑白图像。
以下代码通过访问和混合图形rgba位图来演示此功能:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.mlab as mlab
def get_rgba_bitmap(fig):
fig.canvas.draw()
tab = fig.canvas.copy_from_bbox(fig.bbox).to_string_argb()
ncols, nrows = fig.canvas.get_width_height()
return np.fromstring(tab, dtype=np.uint8).reshape(nrows, ncols, 4)
def black_white_to_black_transpa(rgba):
rgba[:, :, 3] = 255 - rgba[:, :, 0]
rgba[:, :, 0:3] = 0
def over(rgba1, rgba2):
if rgba1.shape != rgba2.shape:
raise ValueError("rgba1 and rgba2 shall have same size")
alpha = np.expand_dims(rgba1[:, :, 3] / 255., 3)
rgba = np.array(rgba1 * alpha + rgba2 * (1.-alpha), dtype = np.uint8)
return rgba[:, :, 0:3]
fig1 = plt.figure(facecolor = "white")
fig1.set_dpi(300)
ax1 = fig1.add_subplot(1, 1, 1, aspect = "equal", axisbg = "black")
ax1.add_artist(plt.Circle((0., 0., .5), color = "white"))
ax1.set_xlim(-5, 5)
ax1.set_ylim(-5, 5)
bitmap_rgba1 = get_rgba_bitmap(fig1)
black_white_to_black_transpa(bitmap_rgba1)
fig2 = plt.figure(facecolor = "white")
fig2.set_dpi(300)
delta = 0.025
ax2 = fig2.add_subplot(1, 1, 1, aspect = "equal", axisbg = "black")
ax2.set_xlim(-5, 5)
ax2.set_ylim(-5, 5)
x = y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = Z2-Z1
im = ax2.imshow(Z, interpolation='bilinear', cmap=cm.jet,
origin='lower', extent=[-5, 5, -5, 5],
vmax=abs(Z).max(), vmin=-abs(Z).max())
bitmap_rgba2 = get_rgba_bitmap(fig2)
fig = plt.figure()
fig.patch.set_alpha(0.0)
ax = fig.add_axes([0., 0., 1., 1.])
ax.patch.set_alpha(0.0)
ax.imshow(over(bitmap_rgba1, bitmap_rgba2))
plt.axis('off')
fig.savefig("test_transpa.png", dpi=300)
plt.show()
给定:
![enter image description here](https://istack.dev59.com/7wcS6.webp)
我使用了您最初的光子测试样例,照片质量似乎还可以。
现在,如果您也想让图片背景透明,请按照以下步骤操作:
1. 将fig1的背景设置为“白色”,即
fig1 = plt.figure(facecolor='white')
。因为当它传递给
black_white_to_black_transpa
时,白色将变成透明。
2. 将fig2的背景设置为透明
fig2.patch.set_alpha(0.0)
,因为它将不被修改地存储到
bitmap_rgba2
中。
3. 最后,在
over
函数内混合
bitmap_rgba1
和
bitmap_rgba2
时,需要注意alpha通道(请参见下面的可能修改)。
def over(rgba1, rgba2):
if rgba1.shape != rgba2.shape:
raise ValueError("rgba1 and rgba2 shall have same size")
alpha1 = np.expand_dims(rgba1[:, :, 3] / 255., axis=3)
alpha2 = np.expand_dims(rgba2[:, :, 3] / 255., axis=3)
alpha = 1. - (1.-alpha1) * (1.-alpha2)
C1 = rgba1[:, :, 0:3]
C2 = rgba2[:, :, 0:3]
C = (alpha1 * C1 + (1-alpha1) * alpha2 * C2) / alpha
rgba = np.empty_like(rgba1, dtype = np.uint8)
rgba[:, :, 0:3] = C
rgba[:, :, 3] = 255 * alpha[:, :, 0]
return rgba
上次修改:
看起来to_string_argb
返回的数组与imshow
期望的数组存在不一致(RGB通道的顺序)。一个可能的解决方案是将ax.imshow(over(bitmap_rgba1, bitmap_rgba2))
更改为:
over_tab = over(bitmap_rgba1, bitmap_rgba2)
over_tab[:, :, 0:3] = over_tab[:, :, ::-1][:, :, 1:4]
ax.imshow(over_tab)