You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Celluloid中camera.snap()保存GIF与程序实时输出不符问题

问题原因与解决方案

核心问题

你遇到的问题是因为celluloid的Camera默认设计用于“替换式”动画:每次调用camera.snap()时,它只会记录当前步骤绘制的元素,之前添加的线条会被隐藏。而你实时运行时看到的累计效果,是plt.pause(0.1)强制窗口刷新后显示了所有已绘制的线条,但Camera并未记录这些累计状态,最终生成的GIF每一帧仅保留当前绘制的单条线条,和预期的累计效果不符。

此外,代码中X0 = np.linspace(0, 10)包含x0=2、4等偶数点,此时har_1函数计算出的线条会超出你设置的ylim(0,5)范围,导致部分线条在图中不可见,进一步加剧了“仅看到最后一条线”的错觉。


解决方案

方案一:修改celluloid代码实现累计效果

通过每次循环重新绘制所有已生成的线条,让camera.snap()记录累计状态:

import numpy as np
import matplotlib.pyplot as plt
from celluloid import Camera

def har_1(x, x0):
    return (x - x0)*(1 + np.cos(np.pi*x0/2)**2)/(2*np.cos(np.pi*x0/2))

fig1, ax1 = plt.subplots()
camera = Camera(fig1)

ax1.set_xlim(0,1)
# 调整y轴范围,确保所有线条可见
ax1.set_ylim(0, 10)
X0 = np.linspace(0, 10)
X = np.linspace(0, 1)

drawn_x0 = []
for x0 in X0:
    drawn_x0.append(x0)
    # 清空轴后重新绘制所有已保存的线条
    ax1.clear()
    ax1.set_xlim(0,1)
    ax1.set_ylim(0,10)
    for xd in drawn_x0:
        ax1.plot(X, har_1(X, xd))
    plt.pause(0.1)
    camera.snap()

animation = camera.animate()
animation.save('my_animation.gif')

方案二:改用matplotlib原生FuncAnimation(更推荐)

原生FuncAnimation更适合实现累计式动画,无需重复绘制所有元素:

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

def har_1(x, x0):
    return (x - x0)*(1 + np.cos(np.pi*x0/2)**2)/(2*np.cos(np.pi*x0/2))

fig1, ax1 = plt.subplots()
ax1.set_xlim(0,1)
ax1.set_ylim(0,10)
X0 = np.linspace(0, 10)
X = np.linspace(0, 1)

lines = []

def update(frame):
    x0 = X0[frame]
    line, = ax1.plot(X, har_1(X, x0))
    lines.append(line)
    return lines

# interval设置每帧间隔(毫秒),blit=True提升动画流畅度
ani = FuncAnimation(fig1, update, frames=len(X0), interval=100, blit=True)
ani.save('my_animation.gif', writer='pillow')

内容的提问来源于stack exchange,提问作者Александр Евстратенко

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 21:23:24