matplotlib.animation

动画

在Matplotlib中制作动态动画最简单的方法是使用 Animation 类。

Animation 动画的基类。
FuncAnimation 通过重复调用函数制作动画 func .
ArtistAnimation 使用一组固定的动画 Artist 物体。

在这两种情况下,保持对实例对象的引用至关重要。动画是由计时器(通常来自主机GUI框架)进行的,该计时器 Animation 对象保存对的唯一引用。如果您不持有对 Animation 对象(以及计时器)将被垃圾收集,从而停止动画。

要将动画保存到磁盘,请使用 Animation.saveAnimation.to_html5_video

辅助类 下面是关于支持哪些电影格式的详细信息。

FuncAnimation

内部工作 FuncAnimation 或多或少是:

for d in frames:
   artists = func(d, *fargs)
   fig.canvas.draw_idle()
   fig.canvas.start_event_loop(interval)

通过细节处理“Blitting”(显著提高实时性能)、不阻塞、不重复启动/停止GUI事件循环、处理重复、多个动画轴,并轻松将动画保存到电影文件中。

“BLIT”是一个 standard technique 在计算机图形学中。一般的要点是采取一个现有的位图(在我们的情况下,主要是栅格化的数字),然后'闪电'一个以上的艺术家。因此,通过管理保存的“干净”位图,我们只能重新绘制在每帧上都发生变化的少数艺术家,并可能节省大量时间。当我们使用Blitting(路过 blit=True )的核心循环 FuncAnimation 变得更加复杂:

ax = fig.gca()

def update_blit(artists):
    fig.canvas.restore_region(bg_cache)
    for a in artists:
        a.axes.draw_artist(a)

    ax.figure.canvas.blit(ax.bbox)

artists = init_func()

for a in artists:
   a.set_animated(True)

fig.canvas.draw()
bg_cache = fig.canvas.copy_from_bbox(ax.bbox)

for f in frames:
    artists = func(f, *fargs)
    update_blit(artists)
    fig.canvas.start_event_loop(interval)

当然,这会遗漏许多细节(例如,在调整图形大小或完全重新绘制图形时更新背景)。然而,这个可能是极简主义的例子给出了一个如何 init_funcfunc 在…内部使用 FuncAnimation 以及“闪电”如何工作的理论。

上的预期签名 funcinit_func 很容易保存 FuncAnimation 从你的簿记和绘图逻辑,但这意味着,你传递的可调用对象必须知道他们应该工作的艺术家。有几种方法可以处理这一问题,它们具有不同的复杂性和封装性。对于脚本来说,最简单的方法是在全局范围内定义艺术家,并让Python进行排序,这在脚本的情况下非常有效。例如::

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

fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')

def init():
    ax.set_xlim(0, 2*np.pi)
    ax.set_ylim(-1, 1)
    return ln,

def update(frame):
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    return ln,

ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
                    init_func=init, blit=True)
plt.show()

第二种方法是 functools.partial 将艺术家“绑定”到功能。第三种方法是使用闭包来构建所需的艺术家和函数。第四种方法是创建类。

作家类

提供的作家可分为几个大类。

枕头作者依靠枕头库来编写动画,将所有数据保存在内存中。

PillowWriter

HTML编写器生成基于JavaScript的动画。

HTMLWriter 编写基于JavaScript的HTML电影。

基于管道的编写器通过管道将捕获的帧流式传输到外部进程。基于管道的变体往往更具性能,但可能不适用于所有系统。

FFMpegWriter 基于管道的ffmpeg编写器。
ImageMagickWriter 基于管道的动画GIF。
AVConvWriter 基于管道的AVconv编写器。

基于文件的编写器为每个帧保存临时文件,这些帧在结尾处缝合成单个文件。虽然速度较慢,但这些编写器更容易调试。

FFMpegFileWriter 基于文件的ffmpeg编写器。
ImageMagickFileWriter 基于文件的动画gif书写器。
AVConvFileWriter 基于文件的avconv编写器。

基本上,A MovieWriter 提供从同一底层获取连续帧的方法 Figure 对象。基类 MovieWriter 实现3个方法和一个上下文管理器。基于管道和基于文件的编写器之间的唯一区别在于它们各自的参数 setup 方法。

这个 setup() 方法用于准备编写器(可能打开管道)、对 grab_frame() 一次捕获一帧,然后 finish() 完成电影并将输出文件写入磁盘。例如::

moviewriter = MovieWriter(...)
moviewriter.setup(fig, 'my_movie.ext', dpi=100)
for j in range(n):
    update_figure(j)
    moviewriter.grab_frame()
moviewriter.finish()

如果直接使用writer类(而不是通过 Animation.save )强烈建议使用 saving 上下文管理器:

with moviewriter.saving(fig, 'myfile.mp4', dpi=100):
    for j in range(n):
        update_figure(j)
        moviewriter.grab_frame()

以确保根据需要执行设置和清理。

实例

辅助类

动画基础类

Animation 动画的基类。
TimedAnimation Animation 基于时间的动画的子类。

作者注册

提供了一个模块级注册表,用于在编写器的名称和类之间进行映射,以允许将字符串传递给 Animation.save 而不是编写器实例。

MovieWriterRegistry 按人类可读的名称注册可用的编写器类。

编写器基类

减少代码重复的基类

AbstractMovieWriter 用于编写电影的抽象基类。
MovieWriter 用于编写电影的基类。
FileMovieWriter MovieWriter 用于写入单个文件并在末尾缝合。

和混音

AVConvBase [Deprecated] 用于avconv输出的mixin类。
FFMpegBase 用于ffmpeg输出的mixin类。
ImageMagickBase ImageMagick输出的Mixin类。

提供。

有关如何轻松实现新的 MovieWriter 类。