matplotlib.animation
#
动画#
在 Matplotlib 中制作实时动画的最简单方法是使用其中一个
Animation
类。
动画的基类。 |
|
通过重复调用函数func来制作动画。 |
|
使用一组固定 |
在这两种情况下,保持对实例对象的引用至关重要。动画由Animation
对象唯一引用的计时器(通常来自主机 GUI 框架)推进。如果您没有对该Animation
对象的引用,它(以及因此的计时器)将被垃圾收集,这将停止动画。
要保存动画,请使用Animation.save
、Animation.to_html5_video
或Animation.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”如何工作的理论。func
FuncAnimation
预期的签名非常简单,可以很容易地func
避开您的簿记和绘图逻辑,但这意味着您传入的可调用对象必须知道他们应该处理哪些艺术家。有几种方法可以处理这个问题,它们具有不同的复杂性和封装性。最简单的方法(在脚本的情况下效果很好)是在全局范围内定义艺术家,然后让 Python 解决问题。例如init_func
FuncAnimation
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
#
例子#
作家课程#
提供的作家分为几大类。
Pillow writer 依赖 Pillow 库来编写动画,将所有数据保存在内存中。
HTML 编写器生成基于 JavaScript 的动画。
基于 JavaScript 的 HTML 电影的作家。 |
基于管道的编写器通过管道将捕获的帧流式传输到外部进程。基于管道的变体往往性能更高,但可能不适用于所有系统。
基于管道的 ffmpeg 编写器。 |
|
基于管道的动画 gif。 |
基于文件的编写器为每个帧保存临时文件,这些文件在最后拼接成一个文件。虽然速度较慢,但这些编写器更容易调试。
基于文件的 ffmpeg 编写器。 |
|
基于文件的动画 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.save
而不是编写器实例。
按人类可读名称注册的可用编写器类。 |
编写器基类#
减少代码重复基类
用于编写电影的抽象基类,提供一种通过调用 |
|
编写电影的基类。 |
|
|
和混合
FFMpeg 输出的 Mixin 类。 |
|
ImageMagick 输出的 Mixin 类。 |
提供。
请参阅源代码以了解如何轻松实现新MovieWriter
类。