【问题标题】:Saving an animated Matplotlib graph as a GIF file results in a different looking plot将动画 Matplotlib 图形保存为 GIF 文件会产生不同的绘图
【发布时间】:2021-09-02 02:21:59
【问题描述】:

我使用 Matplotlib 动画类中的 FuncAnimation 创建了一个动画情节,我想将其保存为 .gif 文件。当我运行脚本时,输出看起来很正常,看起来像这样(动画效果很好):

但是,当我尝试使用 ImageMagick 或 PillowWriter 将动画图保存为 .gif 文件时,该图如下图所示:

线条显然要粗得多,总的来说,看起来很糟糕。问题归因于点(紫色和红色圆圈)。因此,似乎情节正在写在每一帧上(我认为是这种情况)。我可以通过一起摆脱它们来避免这种情况。但我不想这样做,因为很难看到线条。

代码如下:

line, = ax.plot([], [], color = 'blue', lw=1)
line2, = ax.plot([], [], color = 'red', lw=1)
line3, = ax.plot([], [], color = 'purple', lw=1)
def animate(i):
    line.set_data(x1[:i], y1[:i])
    line2.set_data(x2[:i], y2[:i])
    line3.set_data(x3[:i], y3[:i])
    point1, = ax.plot(x1[i], y1[i], marker='.', color='blue')
    point2, = ax.plot(x2[i], y2[i], marker='.', color='red')
    point3, = ax.plot(x3[i], y3[i], marker='.', color='purple')
    return line, line2, line3, point1, point2, point3,
        
ani = animation.FuncAnimation(fig, animate, interval=20, blit=True, repeat=False, frames=1000, save_count=1000)    
ani.save("TLI.gif", writer='imagemagick',fps=60)

数组x1, y1, x2, y2, x3, y3 都是包含 x、y 坐标的一维数组。 那么为什么会这样呢?为什么 .gif 文件在我直接运行时不显示绘图显示的内容?还有,我该如何解决这个问题?

我也知道这个 Stack Overflow 问题:matplotlib animation save is not obeying blit=True but it seems to work just fine in plt.show(),这意味着问题肯定是由于 blitting。但是,阅读该问题的答案并没有解决我的问题,因为它仅指ax.text,而不是通过ax.plot 绘制的常规点。

【问题讨论】:

  • 输出图的DPI和题中的gif图一样吗?是否可以提供绘图所需的数据?
  • 您能否提供x1, y1, x2, y2, x3, y3 以使其可重现?
  • @R.Marolahy x1、y1 等分别只是 x 和 y 坐标的列表。我想你可以把它变成一条线,也会出现同样的问题。

标签: python matplotlib animated-gif matplotlib-animation


【解决方案1】:

看看这是否有效。我没有 Imagemagick,所以我使用了 Pillow。

为防止动画显示堆叠帧(即点迹),诀窍是清除轴以刷新每个帧。然后为每一帧设置xlimylim,并使用ax.plot(x1[0:i], y1[0:i]...绘制增量线

要提高图像分辨率,请将输出 dpi 设置为合适的值。我玩弄它并确定了 300 以获得清晰的线条和轴线/数字。

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

x1 = np.arange(0, -0.2, -0.002)
y1 = np.arange(0, -0.2, -0.002)
x2 = np.arange(3.9, 3.7, -0.002)
y2 = np.arange(0, 1, 0.01)
x3 = np.arange(0, 1.8, 0.018)
y3 = np.array(x3**2)

fig,ax = plt.subplots()

def animate(i):
    ax.clear()
    ax.set_xlim(-4,4)
    ax.set_ylim(-4,4)
    line, = ax.plot(x1[0:i], y1[0:i], color = 'blue', lw=1)
    line2, = ax.plot(x2[0:i], y2[0:i], color = 'red', lw=1)
    line3, = ax.plot(x3[0:i], y3[0:i], color = 'purple', lw=1)
    point1, = ax.plot(x1[i], y1[i], marker='.', color='blue')
    point2, = ax.plot(x2[i], y2[i], marker='.', color='red')
    point3, = ax.plot(x3[i], y3[i], marker='.', color='purple')
    return line, line2, line3, point1, point2, point3,
        
ani = FuncAnimation(fig, animate, interval=40, blit=True, repeat=True, frames=100)    
ani.save("TLI.gif", dpi=300, writer=PillowWriter(fps=25))

【讨论】:

  • 谢谢。这行得通。线和点在动画中可见。但是,例如,如果我想保存 1000 帧,则需要很长时间才能保存。但是,这是一个单独的问题。但只是想知道是否有让动画保存更快的提示?
  • 不客气,很高兴它对你有用。我进行了一些降低输出 dpi 和/或 fps 的测试,它们都会影响运行/保存时间。对于我的 4 秒动画,我在 Jupyter Lab 中获得了以下时间:25 fps,300 dpi:12.7 s 25 fps,300 dpi:8.8 s
  • (抱歉,忘记了编辑时间限制)15 fps 300 dpi: 7.5 s; 15 fps 150 dpi:5.4 秒。我确实建议您降低 fps(24 fps 对于体面的卡通动画来说是典型的)。确保将 FuncAnimation fps 与 animation.save fps 同步 - 您的示例以 50 fps(20 ms x 1,000 帧)创建了一个 20 秒的动画,但将其保存为 60 fps(16.7 秒)。
  • 我明白了,谢谢。同步 ani.save() 的 fps 和 FuncAnimation 对性能和速度有什么好处吗?我想以不同的 fps 保存每个,这样输出的 gif 可以更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 2020-07-16
相关资源
最近更新 更多