如何同时保存和展示matplotlib动画且避免重复运行每一帧?
解决方案
你遇到的重复运行问题,本质是FuncAnimation的save方法和plt.show()会各自独立触发一次完整的帧渲染流程,初始化函数、每帧渲染函数都会各跑两次。我们可以通过预渲染帧的方案避免重复计算,全程只渲染一次,不需要写大量额外代码。
方案1:预生成帧用ArtistAnimation实现(最稳妥)
这个方案提前一次性生成所有帧的渲染结果,后续保存、展示都直接调用预生成的内容,不会重复执行渲染逻辑:
""" 修改后只渲染一次的动画示例 """ import numpy as np from matplotlib import pyplot as plt from matplotlib import animation # 基础画布设置不变 fig = plt.figure() ax = plt.axes(xlim=(0, 2), ylim=(-2, 2)) # 预生成所有帧的内容 frames_count = 5 artists = [] print("init") for i in range(frames_count): print(i) x = np.linspace(0, 2, 1000) y = np.sin(2 * np.pi * (x - 0.01 * i)) line, = ax.plot([], [], lw=2) line.set_data(x, y) artists.append([line]) # 直接用预生成的帧创建动画 anim = animation.ArtistAnimation(fig, artists, interval=20, blit=True, repeat=False) # 保存和展示都不会再触发帧渲染 anim.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264']) plt.show()
运行后可以看到init只打印1次,每个帧序号也只打印1次,耗时直接减半。
方案2:给渲染函数加缓存(改动最小)
如果你不想改动原有FuncAnimation的逻辑,可以直接给初始化和渲染函数加缓存装饰器,第二次调用时直接返回之前的计算结果,不需要重新执行:
from functools import lru_cache # 原有代码其他部分不变,仅给两个函数加装饰器 @lru_cache(maxsize=None) def init(): print("init") line.set_data([], []) return line, @lru_cache(maxsize=None) def animate(i): print(i) x = np.linspace(0, 2, 1000) y = np.sin(2 * np.pi * (x - 0.01 * i)) line.set_data(x, y) return line,
这个方案只需要加2行导入和2行装饰器代码,原有逻辑完全不用改,就能实现只渲染一次的效果。
内容的提问来源于stack exchange,提问作者Yulia V
相关产品推荐
相关产品推荐

