【问题标题】:Animate a rotating 3D graph in matplotlib在 matplotlib 中为旋转的 3D 图形制作动画
【发布时间】:2013-08-23 02:06:11
【问题描述】:

我设置了散点图并按照我想要的方式绘制,我想创建一个在空间中旋转的图形的 .mp4 视频,就好像我使用了plt.show() 并拖动视点一样。

This answer 几乎正是我想要的,除了保存电影,我必须手动调用带有图像文件夹的 FFMpeg。我宁愿使用 Matplotlib 内置的动画支持,而不是保存单个帧。代码转载如下:

from mpl_toolkits.mplot3d import Axes3D
ax = Axes3D(fig)
ax.scatter(xx,yy,zz, marker='o', s=20, c="goldenrod", alpha=0.6)
for ii in xrange(0,360,1):
    ax.view_init(elev=10., azim=ii)
    savefig("movie"%ii+".png")

【问题讨论】:

标签: python animation matplotlib


【解决方案1】:

如果你想了解更多关于 matplotlib 动画的信息,你真的应该关注 this tutorial。它详细解释了如何创建动画情节。

注意:创建动画情节需要安装ffmpegmencoder

这是他的第一个示例的一个版本,已更改为与您的散点图一起使用。

# First import everthing you need
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
from mpl_toolkits.mplot3d import Axes3D

# Create some random data, I took this piece from here:
# http://matplotlib.org/mpl_examples/mplot3d/scatter3d_demo.py
def randrange(n, vmin, vmax):
    return (vmax - vmin) * np.random.rand(n) + vmin
n = 100
xx = randrange(n, 23, 32)
yy = randrange(n, 0, 100)
zz = randrange(n, -50, -25)

# Create a figure and a 3D Axes
fig = plt.figure()
ax = Axes3D(fig)

# Create an init function and the animate functions.
# Both are explained in the tutorial. Since we are changing
# the the elevation and azimuth and no objects are really
# changed on the plot we don't have to return anything from
# the init and animate function. (return value is explained
# in the tutorial.
def init():
    ax.scatter(xx, yy, zz, marker='o', s=20, c="goldenrod", alpha=0.6)
    return fig,

def animate(i):
    ax.view_init(elev=10., azim=i)
    return fig,

# Animate
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=360, interval=20, blit=True)
# Save
anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])

【讨论】:

  • 对不起,我希望你真的没有被冒犯。不确定我是否同意您对缺少返回值的看法。我认为blit 需要它们正常工作,但图书馆的那部分对我来说仍然是一个黑盒子。 (我确实对答案投了赞成票)。
  • 你当然没有! :D 实际上,我非常尊重您的 cmets,因为他们来自经验丰富的 matplotlib 开发人员!我尝试向他们学习并按照您的建议行事(昨天关于问题标记)。因此,每当您认为我做错了什么时,请DO纠正我:)。这既符合 SO 社区的利益,也符合我自己的学习过程。碰巧我们在上一个问题上存在轻微的方法分歧,所以我把它作为一个笑话添加,因为我知道你会阅读所有matplotlib 问题:)
  • 关于返回值。在博客文章中,Jake 说:“这个函数返回线对象很重要,因为这告诉动画师在每一帧之后要更新绘图上的哪些对象”。但由于情节上的任何对象都没有改变,我认为不应该返回任何东西。如果这是一个不正确的假设,我会编辑帖子。
  • 这需要return ()initanimate 中才能不崩溃
  • 当我将此代码复制并粘贴到我的 IDLE 中时,我收到以下错误,有人知道吗?文件“/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/matplotlib/animation.py”,第 1260 行,在 轴 = {a.axes for a in Artist} TypeError: unhashable type: 'list'
【解决方案2】:

当我偶然发现这个时,我正在研究用 matplotlib 为我的情节制作动画: http://zulko.wordpress.com/2012/09/29/animate-your-3d-plots-with-pythons-matplotlib/

它提供了简单的功能来围绕绘图制作动画并以多种格式输出。

【讨论】:

【解决方案3】:

这有点小技巧,但如果您使用的是 Jupyter 笔记本,您可以使用单元魔法直接从笔记本本身运行命令行版本的 ffmpeg。在一个单元格中运行您的脚本以生成原始帧

from mpl_toolkits.mplot3d import Axes3D
ax = Axes3D(fig)
ax.scatter(xx,yy,zz, marker='o', s=20, c="goldenrod", alpha=0.6)
for ii in xrange(0,360,1):
    ax.view_init(elev=10., azim=ii)
    savefig("movie%d.png" % ii)

现在,在一个新的笔记本单元格中,输入以下内容,然后运行该单元格

%%bash 
ffmpeg -r 30 -i movie%d.png -c:v libx264 -vf fps=25 -pix_fmt yuv420p out.mp4

【讨论】:

    【解决方案4】:

    Viktor Kerkez 提供的解决方案对我不起作用(matplotlib 版本 3.4.2)。我收到与user3015729 报告的相同错误。下面是一个修改后的版本,它产生相同的结果,但适用于 matplotlib 3.4.2。

    # First import everthing you need
    import numpy as np
    from matplotlib import pyplot as plt
    from matplotlib import animation
    from mpl_toolkits.mplot3d import Axes3D
    
    # Create some random data, I took this piece from here:
    # http://matplotlib.org/mpl_examples/mplot3d/scatter3d_demo.py
    
    
    def randrange(n, vmin, vmax):
        return (vmax - vmin) * np.random.rand(n) + vmin
    
    
    n = 100
    xx = randrange(n, 23, 32)
    yy = randrange(n, 0, 100)
    zz = randrange(n, -50, -25)
    
    # Create a figure and a 3D Axes
    fig = plt.figure()
    ax = Axes3D(fig)
    scat = ax.scatter(xx, yy, zz, marker='o', s=20, c="goldenrod", alpha=0.6)
    
    # Create an init function and the animate functions.
    # Both are explained in the tutorial. Since we are changing
    # the the elevation and azimuth and no objects are really
    # changed on the plot we don't have to return anything from
    # the init and animate function. (return value is explained
    # in the tutorial.
    
    
    def init():
        ax.view_init(elev=10., azim=0)
        return [scat]
    
    
    def animate(i):
        ax.view_init(elev=10., azim=i)
        return [scat]
    
    
    # Animate
    anim = animation.FuncAnimation(fig, animate, init_func=init,
                                   frames=360, interval=20, blit=True)
    # Save
    anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-02
      • 2012-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      相关资源
      最近更新 更多