【问题标题】:Matplotlib animation repeating even whit repeat set to FalseMatplotlib 动画重复甚至重复设置为 False
【发布时间】:2021-06-13 14:32:50
【问题描述】:

我正在尝试使用matplotlib 创建动画。 我有以下代码:

import math
import numpy as np
import matplotlib as mpl
from matplotlib import pyplot as plt
from matplotlib import animation as ani
import ffmpeg

xValues = np.empty((4, 100))              # Initialize the vectors
yValues = np.empty((4, 100))

for i in np.arange(100):                    # Populate the vectors
    xValues[:,i] = np.random.random(4)
    yValues[:,i] = np.random.random(4)

k = 0                                      # Initialisation of k
myFig, ax = plt.subplots(figsize=(8,5))
p, = ax.plot([],[])

def animFunc(j):                           # Animation function
    global k, p
    j = int(j)
    p.remove()
    p, = ax.plot(xValues[:,k],yValues[:,k])
    p.set_data(xValues[:,k],yValues[:,k])
    k += 1
    return p,

animator = ani.FuncAnimation(myFig, animFunc, interval=1, blit=True, repeat=False, frames=100)
animator.save('my_video.mp4', writer='ffmpeg', fps=50, bitrate=1000)

我基本上是在绘制两个向量 xValues,yValues,它们沿轴 1 的大小为 100。

当我运行代码时,视频已创建,但出现以下错误:

Traceback (most recent call last):
  File "C:\...\...\my_code.py", line 30, in <module>
    animator.save('my_video.mp4', writer='ffmpeg', fps=50, bitrate=1000)
  File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\animation.py", line 1152, in save
    anim._draw_next_frame(d, blit=False)
  File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\animation.py", line 1192, in _draw_next_frame
    self._draw_frame(framedata)
  File "C:\Users\User\AppData\Local\Programs\Python\Python37\lib\site-packages\matplotlib\animation.py", line 1755, in _draw_frame
    self._drawn_artists = self._func(framedata, *self._args)
  File "C:\...\...\my_code.py", line 24, in animFunc
    p, = ax.plot(xValues[:,k],yValues[:,k])
IndexError: index 100 is out of bounds for axis 1 with size 100

看起来,该函数试图在最后一帧之后重复动画(然后重复从索引k = 100 开始,这对于xValues, yValues 来说太大了)。但它为什么会这样做呢?我在声明中设置了repeat=False

另外,您将如何调整bitrate 参数? 1000 值不值?


编辑 1: JohanC 的解决方案工作正常,我尝试实现一个虚拟 InitFunction(ax 对象在任何函数中初始化一次)并将k 替换为j现在没有对动画的额外调用了!

【问题讨论】:

  • 如果您不提供初始化函数,则会调用animFunc。这使得它将被调用 101 次,导致最后一次调用崩溃。一个解决方案可能是提供一个不会增加k 的虚拟初始化函数。请注意,一般来说,出于速度和内存使用的考虑,p.remove()p, = ax.plot(..) 不应在动画函数内部调用(仅需要 p.set_data(...))。对于bitrate,您需要进行实验。它应该足够高以获得足够的质量,并且足够低以避免文件变得太大。
  • 另请注意,建议仅使用动画参数(在本例中为j)而不是全局变量k。这样你就可以完全避免这个问题。总的来说,建议尽量减少global的使用。
  • 感谢您提供有用的见解,删除全局 k 变量是关键!+
  • @JohanC 只是另一个问题,如果我删除了动画和 init 函数中的 global 声明,那么我会收到类似“赋值前引用的局部变量 xyz”之类的错误,其中 xyz 是全局变量...为什么没有正确识别?

标签: python matplotlib animation


【解决方案1】:

当只在函数内部读取全局变量时,不需要global 声明。但是,如果您在函数内部使用全局声明调用 p, = ax.plot(...),则会创建一个同名的局部变量。这会导致“赋值前引用”错误。

不建议在更新函数中调用p, = ax.plot(...),因为这会减慢执行速度。

在您的情况下,您似乎想同时绘制 4 条曲线,而大多数 funcAnimation 示例仅绘制 1 条曲线。有 4 条曲线,ax.plot 返回,嗯,4 条曲线。在简单的情况下,ax.plot 返回一个带有一条曲线的 list,并且通常使用不直观的逗号符号来提取该列表的第一个(也是唯一一个)元素。对于 4 条曲线,您确实希望收到完整列表(因此,不使用逗号)。

设置将需要 4 条虚拟曲线,您可以通过 nan 值的 1×4 数组创建它们。为了避免动画不断移动限制,通常从一开始就设置一些固定限制。

下面是一些示例代码:

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation as ani

xValues = np.empty((4, 100))  # Initialize the vectors
yValues = np.empty((4, 100))

for i in np.arange(100):  # Populate the vectors
    xValues[:, i] = np.random.random(4)
    yValues[:, i] = np.random.random(4)

myFig, ax = plt.subplots(figsize=(8, 5))
empty_values = np.empty((1, 4))
empty_values[:] = np.nan
lines = ax.plot(empty_values, empty_values)
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)

def initFunc():
    return lines

def animFunc(j):  # Animation function
    for i, line in enumerate(lines):
        line.set_data(xValues[i, :j], yValues[i, :j])
    return lines

animator = ani.FuncAnimation(myFig, animFunc, init_func=initFunc, interval=1, blit=True, repeat=False, frames=100)
plt.show()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-22
    • 2014-01-01
    • 1970-01-01
    • 2017-08-09
    相关资源
    最近更新 更多