matplotlib动画:写入没有第三方模块的png文件

时间:2016-12-19 20:13:17

标签: python animation matplotlib

matplotlib中的动画模块通常需要第三方模块,如FFmpeg,mencoder或imagemagik才能将动画保存到文件中(例如:https://stackoverflow.com/a/25143651/5082048)。

即使是matplotlib中的MovieWriter类似乎也是以第三方模块的合并方式构建的(开始和结束过程,通过管道进行通信):http://matplotlib.org/api/animation_api.html#matplotlib.animation.MovieWriter

我正在寻找一种方法,如何在python中直接将matplotlib.animation.FuncAnimation对象框架保存到框架到png。之后,我想使用这种方法在iPython笔记本中将.png文件显示为动画:https://github.com/PBrockmann/ipython_animation_javascript_tool/

因此我的问题是:

  • 如何将matplotlib.animation.FuncAnimation对象直接保存到.png文件而无需使用第三方模块?
  • 是否为此用例实现了一个编写器类?
  • 如何从FuncAnimation对象中逐帧获取图形对象(以便我可以自己保存)?

编辑:给出matplotlib.animation.FuncAnimation对象,任务是使用纯Python保存它的帧。不幸的是,我无法像ImportanceOfBeingErnest建议的那样更改底层动画功能。

3 个答案:

答案 0 :(得分:3)

虽然这看起来有点复杂,但在动画中可以很容易地保存动画帧。

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np

def animate(i):
    line.set_ydata(np.sin(2*np.pi*i / 50)*np.sin(x))
    #fig.canvas.draw() not needed see comment by @tacaswell
    plt.savefig(str(i)+".png")
    return line,

fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1,1)
x = np.linspace(0, 2*np.pi, 200)
line, = ax.plot(x, np.zeros_like(x))
plt.draw()

ani = matplotlib.animation.FuncAnimation(fig, animate, frames=5, repeat=False)
plt.show()

注意repeat = False参数,这将阻止动画连续运行并重复将相同的文件写入磁盘。

请注意,如果您愿意放宽"没有外部包裹的限制"你可以使用imagemagick来保存pngs

ani.save("anim.png", writer="imagemagick")

将保存文件anim-1.png,anim-2.png等。

最后请注意,当然有easier methods to show an animation in a jupyter notebook

答案 1 :(得分:2)

您想查看FileMovieWriter子类(请参阅http://matplotlib.org/2.0.0rc2/api/animation_api.html#writer-classes)您可能希望子类FileMoveWriter,例如

import matplotlib.animation as ma


class BunchOFiles(ma.FileMovieWriter):
    def setup(self, fig, dpi, frame_prefix):
        super().setup(fig, dpi, frame_prefix, clear_temp=False)

    def _run(self):
        # Uses subprocess to call the program for assembling frames into a
        # movie file.  *args* returns the sequence of command line arguments
        # from a few configuration options.
        pass

    def grab_frame(self, **savefig_kwargs):
        '''
        Grab the image information from the figure and save as a movie frame.
        All keyword arguments in savefig_kwargs are passed on to the 'savefig'
        command that saves the figure.
        '''

        # Tell the figure to save its data to the sink, using the
        # frame format and dpi.
        with self._frame_sink() as myframesink:
            self.fig.savefig(myframesink, format=self.frame_format,
                             dpi=self.dpi, **savefig_kwargs)

    def cleanup(self):
        # explictily skip a step in the mro
        ma.MovieWriter.cleanup(self)

(未经过测试,最好只实现一个实现savinggrab_framefinishedsetup)的类

答案 2 :(得分:2)

未经修改,我无法获得塔卡斯韦尔的答案。所以,这就是我的看法。

from matplotlib.animation import FileMovieWriter


class BunchOFiles(FileMovieWriter):
    supported_formats = ['png', 'jpeg', 'bmp', 'svg', 'pdf']

    def __init__(self, *args, extra_args=None, **kwargs):
        # extra_args aren't used but we need to stop None from being passed
        super().__init__(*args, extra_args=(), **kwargs)

    def setup(self, fig, dpi, frame_prefix):
        super().setup(fig, dpi, frame_prefix, clear_temp=False)
        self.fname_format_str = '%s%%d.%s'
        self.temp_prefix, self.frame_format = self.outfile.split('.')

    def grab_frame(self, **savefig_kwargs):
        '''
        Grab the image information from the figure and save as a movie frame.
        All keyword arguments in savefig_kwargs are passed on to the 'savefig'
        command that saves the figure.
        '''

        # Tell the figure to save its data to the sink, using the
        # frame format and dpi.
        with self._frame_sink() as myframesink:
            self.fig.savefig(myframesink, format=self.frame_format,
                             dpi=self.dpi, **savefig_kwargs)

    def finish(self):
        self._frame_sink().close()

我们可以使用以下方法保存一组文件:

anim.save('filename.format', writer=BunchOFiles())

,它将以'filename {number} .format'的形式保存文件。