matplotlib动画:不使用第三方modu写入png文件

2024-09-25 08:25:04 发布

您现在位置:Python中文网/ 问答频道 /正文

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

甚至matplotlib中的MovieWriter类似乎都是以第三方模块的方式构建的(启动和关闭进程,通过管道进行通信):http://matplotlib.org/api/animation_api.html#matplotlib.animation.MovieWriter。在

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

因此,我的问题是:

  • 如何将matplotlib.animation.FuncAnimation对象直接保存到.png文件而不需要使用第三方模块?在
  • 有没有为这个用例实现的writer类?在
  • 如何从FuncAnimation对象逐帧获取体形对象(以便我自己保存它们)?在

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


Tags: 模块文件对象方法httpscomapipng
3条回答

你想看一下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的类)

尽管这看起来有点复杂,但保存动画的帧在动画本身中可能很容易完成。在

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保存PNG

^{pr2}$

这将保存文件anim-1.png、anim-2.png等

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

我无法得到塔卡斯威尔的答复,不加修改。所以,这是我的看法。在

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()

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

^{pr2}$

它将以“filename{number}.format”的形式保存文件。在

相关问题 更多 >