【问题标题】:mplot3d animation with transparent background具有透明背景的 mplot3d 动画
【发布时间】:2016-09-28 03:46:26
【问题描述】:

我想使用 matplotlib 生成一些具有透明背景的 gif。我尝试了不同的选项,但我无法获得具有透明背景的文件。使用当前的设置,我得到了第一帧,但不是其余的。以下是我的代码

from __future__ import division
from numpy import pi, sin, cos, mgrid
from scipy.special import jn, jn_zeros
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import rcParams


# In Windows the next line should provide the full path to convert.exe
# since convert is a Windows command
rcParams['animation.convert_path'] = "C:\Program Files\ImageMagick-6.9.3\convert.exe"
rcParams['savefig.transparent'] = True
rcParams['savefig.dpi'] = 130
rcParams['savefig.pad_inches'] = 0
plot_args = {'rstride': 1, 'cstride': 1, 'cmap':"RdYlBu",
             'linewidth': 0.5, 'antialiased': True, 'color': '#1e1e1e',
             'shade': True, 'alpha': 1.0, 'vmin': -1, 'vmax':1}


def data_gen(num):
    ax.cla()
    m, n = 1, 2
    lam = jn_zeros(m, n)[-1]
    dt = 2*pi/(30*lam)
    z = cos(m*t)*jn(m, lam*r)*sin(lam*num*dt)
    surf = ax.plot_surface(x, y, z, **plot_args)
    ax.view_init(elev=30, azim=45)
    ax.set_xlim(-0.6, 0.6)
    ax.set_ylim(-0.6, 0.6)
    ax.set_zlim(-1, 1)
    plt.axis("off")
    return surf


r, t = mgrid[0:1:20j, 0:2*pi:40j]
x, y = r*cos(t), r*sin(t)
fig = plt.figure(facecolor=None)
ax = fig.add_subplot(111, projection='3d')
ani = animation.FuncAnimation(fig, data_gen, range(30), blit=False)
ani.save("Drum vibration mode.gif", writer='imagemagick')

结果是(如果你点击它,你可以看到只有一帧是透明的)

问题:有没有办法使用 mplot3d 获得具有透明背景的动画?

【问题讨论】:

  • 你看到这个blog.adrian.pw/posts/2016/06/matplotlib-transparent-animation了吗?您正在寻找的似乎是fig.patch.set_alpha(0.) 和ani.save('circle_anim.mov', codec="png", dpi=100, bitrate=-1, savefig_kwargs={'transparent': True, 'facecolor': 'none'}) 之类的东西。我现在不能尝试,但稍后会试一试。
  • @JacquesGaudin,我刚刚检查过了。这很酷,但它不会将图像导出为 GIF。事实上,savefig_kwargs 在使用 GIF 编写器时会被忽略。
  • @JacquesGaudin,刚试过:不行。
  • 您可能想阅读此github.com/matplotlib/matplotlib/issues/5335。似乎gif动画的透明度被一起删除了。
  • "我相信 matplotlib 将每一帧保存为 png,然后通过 convert (imagemagick) 或 ffmpeg 将这些 png 保存为动画。我相信这里的问题是,虽然 gif 正确支持透明度,它们只支持完整的 alpha 或不支持 alpha,这会迫使 imagemagick 为每个提供像素化外观的中间 alpha 决定是 alpha 还是无 alpha。”和“也许我们可以一起禁用 gif 文件的透明度(我认为 matplotlib 不能正确处理布尔 alpha 级别),然后将默认帧格式设置为 gif 文件用于动画”

标签: python matplotlib animated-gif mplot3d


【解决方案1】:

我认为这确实是一个错误。 但是,如果您更关心结果而不是到达那里的方式,那么以下内容就可以完成。不用调用动画,您可以单独保存每个图像,然后调用 imageMagick 将它们转换为动画 gif。 请参阅下面的代码并注意 convert.exe 的参数。

from __future__ import division
from numpy import pi, sin, cos, mgrid
from scipy.special import jn, jn_zeros
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

from matplotlib import rcParams
import subprocess


# In Windows the next line should provide the full path to convert.exe
# since convert is a Windows command
path_to_convert =  "C:\Program Files\ImageMagick-6.9.3\convert.exe"
#rcParams['animation.convert_path'] = path_to_convert
rcParams['savefig.transparent'] = True
rcParams['savefig.dpi'] = 130
rcParams['savefig.pad_inches'] = 0
plot_args = {'rstride': 1, 'cstride': 1, 'cmap':"RdYlBu",
             'linewidth': 0.5, 'antialiased': True, 'color': '#1e1e1e',
             'shade': True, 'alpha': 1.0, 'vmin': -1, 'vmax':1}


def data_gen(num):
    ax.cla()
    ax.clear()
    m, n = 1, 2
    lam = jn_zeros(m, n)[-1]
    dt = 2*pi/(30*lam)
    z = cos(m*t)*jn(m, lam*r)*sin(lam*num*dt)
    surf = ax.plot_surface(x, y, z, **plot_args)
    ax.view_init(elev=30, azim=45)
    ax.set_xlim(-0.6, 0.6)
    ax.set_ylim(-0.6, 0.6)
    ax.set_zlim(-1, 1)
    ax.axis("off")
    fig.patch.set_visible(False)
    ax.patch.set_visible(False)
    ax.set_axis_off()
    ax._axis3don = False
    return surf


r, t = mgrid[0:1:20j, 0:2*pi:40j]
x, y = r*cos(t), r*sin(t)
fig = plt.figure(facecolor=None, frameon=False)
ax = fig.add_subplot(111, projection='3d')
for i in range(30):
    data_gen(i)
    plt.savefig("drum_{n:02d}.png".format(n=i), transparent=True,  frameon=False)
    print i, 

args = [path_to_convert, "-delay", "10", "-loop" , "0", "-dispose", "Background", "drum_*.png", "output.gif"]
subprocess.call(args, shell=True)
subprocess.call(["del", "/Q", "drum_*.png"], shell=True)
print "\ndone"

请注意,对 imageMagick 和删除命令的调用可能是系统依赖的。此脚本已在 Windows 8 下使用 imageMagick 7.0.3 (Q16) 进行测试。

【讨论】:

  • 我在考虑这个选项,但希望有人能以另一种方式做到这一点。为了让你的答案发挥作用,我将args 行更改为args = [path_to_convert, "drum_*.png", "-delay", "10", "-loop" , "0", "-dispose", "Background", "output.gif"]。
  • 如果我们可以添加类似 subprocess.call(["rm", "drum_*.png"], shell=False) 的内容来删除 PNG 文件并保留 GIF,那就太好了。
  • 我添加了一行来删除 png 文件。关于 convert.exe 参数顺序的变化,我不知道。它确实可以按照上面写的方式在我的机器上运行。
猜你喜欢
  • 1970-01-01
  • 2012-07-06
  • 2016-09-24
  • 1970-01-01
  • 2021-03-19
  • 1970-01-01
  • 2017-09-28
  • 2021-04-04
相关资源
最近更新 更多