Matplotlib 简明教程

Matplotlib - Animations

Animation 是一种视觉技术,它涉及通过一系列单帧创建动态图像。每帧表示时间中的特定时刻,当以高速连续播放时,会创建移动的幻觉。例如,动画对象的常见示例是 GIF。示例如下 −

animations intro

动画的流行文件格式有 GIF、APNG(动画可移植网络图形)、mkv、mp4 等。

Animations in Matplotlib

Matplotlib 提供了一个专门用于创建动画的模块。在此上下文中,动画是一系列帧,每个帧都与图形上的一幅图相关联。

要将动画能力集成到我们的工作环境中,我们可以使用以下命令导入专用模块 −

import matplotlib.animation as animation

Creating Animations

在 Matplotlib 中创建动画可以通过两种不同的方法来完成。matplotlib.animation 模块为此提供了两个主要类 −

  1. FuncAnimation

  2. ArtistAnimation

The FuncAnimation class

使用 FuncAnimation 类的做法是一种高效的方式,可以通过修改每帧的绘图数据来创建动画。它允许我们通过传递一个用户定义的函数来创建动画,该函数迭代修改绘图数据。该类涉及生成初始帧的数据,随后修改此数据以用于每个后续帧。

此示例演示了使用 FuncAnimation 类对正弦波绘图进行动画,演示对象的运动。它还使用 Matplotlib 动画更新 X 轴值。

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

# Creating a figure and axis
fig, ax = plt.subplots(figsize=(7, 4))

# Generating x values
x = np.arange(0, 2*np.pi, 0.01)

# Plotting the initial sine curve
line, = ax.plot(x, np.sin(x))
ax.legend([r'$\sin(x)$'])

# Function to update the plot for each frame of the animation
def update(frame):
   line.set_ydata(np.sin(x + frame / 50))
   ax.set_xlim(left=0, right=frame)
   return line

# Creating a FuncAnimation object
ani = animation.FuncAnimation(fig=fig, func=update, frames=40, interval=30)

# Displaying the output
plt.show()

以上示例生成以下输出 −

animations ex1

这里有另一个示例,它使用 FuncAnimation 类创建了一个动画的 3D 曲面图。

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

# Generate data
N = 50
fps = 250
frn = 75
x = np.linspace(-2, 2, N + 1)
x, y = np.meshgrid(x, x)
zarray = np.zeros((N + 1, N + 1, frn))
f = lambda x, y, sig: 1 / np.sqrt(sig) * np.exp(-(x ** 2 + y ** 2) / sig ** 2)

# Create data array
for i in range(frn):
   zarray[:, :, i] = f(x, y, 1.5 + np.sin(i * 2 * np.pi / frn))

# Update plot function
def change_plot(frame_number, zarray, plot):
   plot[0].remove()
   plot[0] = ax.plot_surface(x, y, zarray[:, :, frame_number], cmap="afmhot_r")

# Create figure and subplot
fig = plt.figure(figsize=(7, 4))
ax = fig.add_subplot(111, projection='3d')

# Initial plot
plot = [ax.plot_surface(x, y, zarray[:, :, 0], color='0.75', rstride=1, cstride=1)]

# Set axis limits
ax.set_zlim(0, 1.1)

# Animation
ani = animation.FuncAnimation(fig, change_plot, frn, fargs=(zarray, plot), interval=1000 / fps)

# Turn off axis and grid
ax.axis('off')
ax.grid(False)

# Show plot
plt.show()

以上示例生成以下输出 −

animations ex5

ArtistAnimation

ArtistAnimation 是一种灵活的方法,适用于需要按顺序对不同的艺术家进行动画的场景。此方法涉及生成一个艺术家列表(可迭代),将它们绘制到动画的每帧中。

此示例演示了使用 ArtistAnimation 类创建动画。

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

# Create a figure and axis
fig, ax = plt.subplots(figsize=(7,4))

# Define the function
def f(x, y):
   return np.sin(x) + np.cos(y)

# Generate x and y values for the function
x = np.linspace(0, 2 * np.pi, 180)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)

# ims is a list of lists, each row is a list of artists to draw in the current frame
ims = []

# Generate frames for the animation
for i in range(60):
   x += np.pi / 10
   y += np.pi / 30
   im = ax.imshow(f(x, y), animated=True)
   if i == 0:
      ax.imshow(f(x, y))  # show an initial one first
   ims.append([im])

# Create an ArtistAnimation with the specified interval, blit, and repeat_delay
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True, repeat_delay=1000)
# Display the animation
plt.show()

上面的代码生成了以下结果 −

animations ex2

Saving animations

可以使用不同的多媒体编写器(如 Pillow、ffmpeg 和 imagemagick)将动画对象保存到磁盘。但是,需要注意的是,并非所有视频格式都受每个编写器支持。编写器主要有四种类型:

  1. PillowWriter

  2. HTMLWriter

  3. Pipe-based writers

  4. File-based writers

PillowWriter

它使用 Pillow 库以 GIF、APNG 和 WebP 等各种格式保存动画。

一个示例演示了对散点图进行动画并使用 PillowWriter 将其保存为 GIF。

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

# Generate data
steps = 50
nodes = 100
positions = []
solutions = []

for i in range(steps):
   positions.append(np.random.rand(2, nodes))
   solutions.append(np.random.random(nodes))

# Create a figure and axes
fig, ax = plt.subplots(figsize=(7, 4))
marker_size = 50

# Function to update the plot for each frame of the animation
def animate(i):
   fig.clear()
   ax = fig.add_subplot(111, aspect='equal', autoscale_on=False, xlim=(0, 1), ylim=(0, 1))
   ax.set_xlim(0, 1)
   ax.set_ylim(0, 1)
   s = ax.scatter(positions[i][0], positions[i][1], s=marker_size, c=solutions[i], cmap="RdBu_r", marker="o", edgecolor='black')

plt.grid(None)

# Creating a FuncAnimation object
ani = animation.FuncAnimation(fig, animate, interval=100, frames=range(steps))

# Save the animation as a GIF using the PillowWriter
ani.save('animation.gif', writer='pillow')

如果您访问保存输出的文件夹,可以看到以下 gif 文件 −

animations ex3

HTMLWriter

HTMLWriter 用于创建基于 JavaScript 的动画,支持 HTML 和 PNG 格式。此编写器可用于将动画嵌入到网页中。

Pipe-based writers

这些编写人员使用诸如 FFMpegWriter 和 ImageMagickWriter 之类的外部实用程序来创建动画。它们支持各种视频格式,并将帧传输到该实用程序,该实用程序将它们拼接在一起以创建动画。

File-based writers

基于文件的编写器(FFMpegFileWriter 和 ImageMagickFileWriter)稍慢,但提供在创建最终动画之前保存每个帧的优点。

以下示例展示了如何正确为 matplotlib.animation 启用 ffmpeg 。在此,使用动画图像矩阵和动画彩色条创建绘图。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.axes_grid1 import make_axes_locatable

plt.rcParams["figure.figsize"] = [7.50, 3.50]
plt.rcParams["figure.autolayout"] = True
plt.rcParams['animation.ffmpeg_path'] = 'ffmpeg'

fig = plt.figure()
ax = fig.add_subplot(111)
div = make_axes_locatable(ax)
cax = div.append_axes('right', '5%', '5%')
data = np.random.rand(5, 5)
im = ax.imshow(data)
cb = fig.colorbar(im, cax=cax)
tx = ax.set_title('Frame 0')

cmap = ["copper", 'RdBu_r', 'Oranges', 'cividis', 'hot', 'plasma']

def animate(i):
   cax.cla()
   data = np.random.rand(5, 5)
   im = ax.imshow(data, cmap=cmap[i%len(cmap)])
   fig.colorbar(im, cax=cax)
   tx.set_text('Frame {0}'.format(i))

ani = animation.FuncAnimation(fig, animate, frames=10)
FFwriter = animation.FFMpegWriter()
ani.save('plot.mp4', writer=FFwriter)

执行上述代码时,您将获得以下输出 -

animations ex4