Matplotlib - 动画



动画是一种视觉技术,它通过一系列单独的帧创建动态图像。每个帧代表一个特定的时间点,当以高速连续播放时,它们会产生运动的错觉。例如,GIF 就是一个常见的动画对象示例。以下是一个示例:

Animations Intro

动画的流行文件格式包括 GIF、APNG(动画便携式网络图形)、mkv、mp4 等。

Matplotlib 中的动画

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

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

import matplotlib.animation as animation

创建动画

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

  • FuncAnimation
  • ArtistAnimation

FuncAnimation 类

使用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

保存动画

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

  • PillowWriter
  • HTMLWriter
  • 基于管道的写入器
  • 基于文件的写入器

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 文件:

输出
Animation Ex3

HTMLWriter

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

基于管道的写入器

这些写入器使用 FFMpegWriter 和 ImageMagickWriter 等外部实用程序来创建动画。它们支持各种视频格式,并且帧被管道传输到实用程序,该实用程序将它们拼接在一起以创建动画。

基于文件的写入器

基于文件的写入器(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
广告