【发布时间】: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