使图透明与彩色背景

The*_*ude 6 python matplotlib

我有点情况.我需要的是一个黑色背景的情节,在黑色背景上绘制了几个白色圆圈.

我设法使用以下代码执行此操作:

import numpy
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, aspect = "equal", axisbg = "black")
ax.add_artist(plt.Circle((0., 0., .5), color =   "white")) 

plt.xlim(-5, 5)
plt.ylim(-5, 5)

fig.savefig("test.png", dpi = 300)

plt.show()
Run Code Online (Sandbox Code Playgroud)

这会产生以下结果:

在此输入图像描述

现在,我想做的是使这个图像透明.所以这意味着只有白圈应该变得透明.您可能已经能够看到问题,因为我会设置transparent = True.黑色背景自动变得透明,我的身材会失去黑色.

我想另一件事是没有设置transparent = Truesavefig,但实际设置的选项alpha = 0.plt.Circle.这使得白色圆圈实际上是透明的,这是最终目标.但是,因为它是透明的,所以我留下了整个黑色背景.有什么想法可以解决这个问题?

总结一下我的目标:

我想保存图中的透明版本,其中白色圆圈是透明的,而黑色部分则不是.

我知道我可以使用不同的程序,如inkscapegimp创造我想要的东西.但是,由于我需要执行其他操作,我确实需要在python中执行此操作.

谢谢!

GBy*_*GBy 5

编辑3:

已经澄清,基本问题是:

如何在matplotlib图像前面放置一个"黑色和透明"的面具imshow?掩模应来自先前绘制的黑白图形的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]


# fig 1)
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)

# fig 2
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  # difference of Gaussians
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)    

# now saving the composed figure 
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()
Run Code Online (Sandbox Code Playgroud)

赠送: 在此输入图像描述

我测试了你的初始光子测试案例,图片质量似乎没问题

在此输入图像描述

现在,如果你想让图形背景透明:

  • 将fig1背景设置为'白色'即fig1 = plt.figure(facecolor='white'),白色将在传递时变为透明black_white_to_black_transpa
  • 将fig2背景设置为透明fig2.patch.set_alpha(0.0),因为它将被存储而不进行任何修改bitmap_rgba2
  • 最后,在混合bitmap_rgba1bitmap_rgba2内部over功能时注意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
Run Code Online (Sandbox Code Playgroud)

last(?)edit: 似乎返回的数组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)
Run Code Online (Sandbox Code Playgroud)