matplotlib.animation#

动画#

在 Matplotlib 中制作实时动画的最简单方法是使用其中一个 Animation类。

matplotlib.animation.FuncAnimation、matplotlib.animation.ArtistAnimation的继承图

Animation

动画的基类。

FuncAnimation

通过重复调用函数func来制作动画。

ArtistAnimation

使用一组固定Artist对象的动画。

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

要保存动画,请使用Animation.saveAnimation.to_html5_videoAnimation.to_jshtml

有关支持的电影格式的详细信息,请参阅下面的帮助程序类。

FuncAnimation#

的内部运作FuncAnimation或多或少是:

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

带有处理“blitting”的细节(以显着提高现场性能),非阻塞,不重复启动/停止 GUI 事件循环,处理重复,多个动画轴,并轻松地将动画保存到电影文件。

“Blitting”是计算机图形学中的标准技术。一般的要点是获取一个现有的位图(在我们的例子中是一个主要是光栅化的图形),然后在顶部再“blit”一位艺术家。因此,通过管理保存的“干净”位图,我们只能重新绘制在每一帧都在变化的少数艺术家,并可能节省大量时间。当我们使用 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_func 以及“blitting”如何工作的理论。funcFuncAnimation

预期的签名非常简单,可以很容易地func避开您的簿记和绘图逻辑,但这意味着您传入的可调用对象必须知道他们应该处理哪些艺术家。有几种方法可以处理这个问题,它们具有不同的复杂性和封装性。最简单的方法(在脚本的情况下效果很好)是在全局范围内定义艺术家,然后让 Python 解决问题。例如init_funcFuncAnimation

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

fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = ax.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“绑定”艺术家来发挥作用。第三种方法是使用闭包来构建所需的艺术家和功能。第四种方法是创建一个类。

例子#

ArtistAnimation#

例子#

作家课程#

matplotlib.animation.FFMpegFileWriter、matplotlib.animation.FFMpegWriter、matplotlib.animation.ImageMagickFileWriter、matplotlib.animation.ImageMagickWriter、matplotlib.animation.PillowWriter、matplotlib.animation.HTMLWriter的继承图

提供的作家分为几大类。

Pillow writer 依赖 Pillow 库来编写动画,将所有数据保存在内存中。

PillowWriter

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

HTMLWriter

基于 JavaScript 的 HTML 电影的作家。

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

FFMpegWriter

基于管道的 ffmpeg 编写器。

ImageMagickWriter

基于管道的动画 gif。

基于文件的编写器为每个帧保存临时文件,这些文件在最后拼接成一个文件。虽然速度较慢,但​​这些编写器更容易调试。

FFMpegFileWriter

基于文件的 ffmpeg 编写器。

ImageMagickFileWriter

基于文件的动画 gif 作家。

编写器类提供了一种从同一底层获取顺序帧的方法Figure。它们都提供了三个必须按顺序调用的方法:

  • 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

用于编写电影的抽象基类,提供一种通过调用grab_frame.

MovieWriter

编写电影的基类。

FileMovieWriter

MovieWriter用于写入单个文件并在最后缝合。

和混合

FFMpegBase

FFMpeg 输出的 Mixin 类。

ImageMagickBase

ImageMagick 输出的 Mixin 类。

提供。

请参阅源代码以了解如何轻松实现新MovieWriter类。