Matplotlib FuncAnimation 分步动画函数

Matplotlib FuncAnimation Step-by-Step Animation Function

我正在尝试使用 matplotlibFuncAnimation 制作动画视频。每个帧只是一个布尔 n x n 数组,可视化为 white/black 方块。我可以通过预先定义所有数组然后一个一个地遍历它们来成功地做到这一点。这使用类似于 matplotlib's example.

的代码

我的东西比较大,想运行模拟很久。因此,我不想创建整个数组列表,然后一个一个地检查它们。相反,我想定义 animate 函数来执行每个步骤。让我用一个最小的非工作示例来解释。我的实际示例包括更大的数组!

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

def create_video(n):
    global X
    X = np.random.binomial(1, 0.3, size = (n,n))
    
    fig = plt.figure()
    im = plt.imshow(X, cmap = plt.cm.gray)
    
    def animate(t):
        global X
        X = np.roll(X, +1, axis = 0)
        im.set_array(X)
    
    anim = FuncAnimation(
        fig,
        animate,
        frames = 100,
        interval = 1000 / 30,
        blit = True
    )
    
    return anim

anim = create_video(10)

这会初始化一些随机的 10 x 100/1s 然后在每一步只 'rolls' 它。我收到一个错误。

RuntimeError: The animation function must return a sequence of Artist objects.

如果我删除 return anim,将其替换为 pass,并将 anim = create_video(10) 替换为 create_video(10),则会收到警告。

UserWarning: Animation was deleted without rendering anything. This is most likely unintended. To prevent deletion, assign the Animation to a variable that exists for as long as you need the Animation.

显然,我还不够了解FuncAnimation。我想要发生的是函数 animate 更新数组 X,通过 'rolling' 它一步,以及做 im.set_array(X).

中所述:

As the error suggests, and as can be seen e.g. in the simple_animation example, but also from the FuncAnimation documentation, the init_func as well as the updating func are supposed to return an iterable of artists to animate.

The documentation does not say that this is actually only needed when using blit=True, but since you are using blitting here, it is definitely needed.

所以你有两种方法:

  • 添加

    return im,
    

    animate函数

  • FuncAnimation

    中设置blit = False

完整代码

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


def create_video(n):
    global X
    X = np.random.binomial(1, 0.3, size = (n, n))

    fig = plt.figure()
    im = plt.imshow(X, cmap = plt.cm.gray)

    def animate(t):
        global X
        X = np.roll(X, +1, axis = 0)
        im.set_array(X)
        return im, 

    anim = FuncAnimation(
        fig,
        animate,
        frames = 100,
        interval = 1000/30,
        blit = True
    )

    plt.show()

    return anim

anim = create_video(10)