使用Matplotlib导出动态gif

9
我是一名有用的助手,可以为您翻译文本。
我已经尝试了几天在我的Windows计算机上导出动画gif。
以下是基本代码:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro', animated=True)

def init():
    ax.set_xlim(0, 2*np.pi)
    ax.set_ylim(-1, 1)
    return ln,

def update(frame):
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    return ln,

ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
                    init_func=init, blit=True)
ani.save("test.gif")
plt.show()

和错误:

>>> python .\anim_test.py
Traceback (most recent call last):
  File ".\anim_test.py", line 22, in <module>
    ani.save("test.gif")
  File "C:\Users\ishma\Anaconda2\lib\site-packages\matplotlib\animation.py", line 1063, in save
    writer.grab_frame(**savefig_kwargs)
  File "C:\Users\ishma\Anaconda2\lib\site-packages\matplotlib\animation.py", line 336, in grab_frame
    'with --verbose-debug.'.format(e, out, err))
IOError: Error saving animation to file (cause: [Errno 22] Invalid argument) Stdout:  StdError: . It may help to re-run
with --verbose-debug.
PS C:\Users\ishma\Dropbox (SteinLab)\spectra\MassSpecPlot> python .\anim_test.py --verbose-debug
$HOME=C:\Users\ishma
matplotlib data path C:\Users\ishma\Anaconda2\lib\site-packages\matplotlib\mpl-data

*****************************************************************
You have the following UNSUPPORTED LaTeX preamble customizations:

Please do not ask for support with these customizations active.
*****************************************************************

loaded rc file C:\Users\ishma\Anaconda2\lib\site-packages\matplotlib\mpl-data\matplotlibrc
matplotlib version 2.0.2
verbose.level debug
interactive is False
platform is win32
loaded modules: <dictionary-keyiterator object at 0x0000000003EA0048>
CACHEDIR=C:\Users\ishma\.matplotlib
Using fontManager instance from C:\Users\ishma\.matplotlib\fontList.cache
backend Qt5Agg version 5.6
Animation.save using <class 'matplotlib.animation.FFMpegWriter'>
frame size in pixels is 640 x 480
MovieWriter.run: running command: ffmpeg -f rawvideo -vcodec rawvideo -s 640x480 -pix_fmt rgba -r 5.0 -i pipe: -vcodec h
264 -pix_fmt yuv420p -y test.gif
MovieWriter.grab_frame: Grabbing frame.
findfont: Matching :family=sans-serif:style=normal:variant=normal:weight=400:stretch=normal:size=10.0 to DejaVu Sans (u'
C:\\Users\\ishma\\Anaconda2\\lib\\site-packages\\matplotlib\\mpl-data\\fonts\\ttf\\DejaVuSans.ttf') with score of 0.0000
00
MovieWriter.grab_frame: Grabbing frame.
MovieWriter -- Error running proc:
None
None
MovieWriter -- Command stdout:
None
MovieWriter -- Command stderr:
None
Traceback (most recent call last):
  File ".\anim_test.py", line 22, in <module>
    ani.save("test.gif")
  File "C:\Users\ishma\Anaconda2\lib\site-packages\matplotlib\animation.py", line 1063, in save
    writer.grab_frame(**savefig_kwargs)
  File "C:\Users\ishma\Anaconda2\lib\site-packages\matplotlib\animation.py", line 336, in grab_frame
    'with --verbose-debug.'.format(e, out, err))
IOError: Error saving animation to file (cause: [Errno 22] Invalid argument) Stdout: None StdError: None. It may help to
 re-run with --verbose-debug.

如果我将输出文件类型切换为mp4,代码就可以正常工作。在阅读了许多人出现视频文件错误的帖子后,我感觉自己已经尝试过每种不同的编写器组合(包括FFMpegWriter、ImageMagickWriter、AVConvWriter以及FileWriters),确保相关程序位于我的PATH中,在matplotlibrc中更改设置,并尝试使用多台计算机。我被卡住了。
我只找到一个引用此确切错误的线程: https://stackoverflow.com/questions/46562938/oserror-errno-22-invalid-argument-error-saving-animation-to-file 但是遵循那里的评论中的建议并没有解决我的问题。
有什么想法吗?感谢任何帮助。
1个回答

7

使用问题中的代码,您基本上要求使用MPEG编写器生成动画gif。然而,MPEG编写器只能制作视频。

通过matplotlib动画模块产生动画gif的标准方法是使用ImageMagick。

因此,首先将您的行更改为

ani.save("test.gif",writer="imagemagick")

现在,为了使它工作起来,rcParam animation.convert_path 必须指向 ImageMagick 的 convert 程序。
看起来你正在使用Windows系统,所以最好包括完整路径。因此,在保存之前,请设置

plt.rcParams["animation.convert_path"] = "C:\ProgramFiles\ImageMagick\convert.exe" 

无论你的路径是什么,都需要转换为convert.exe

现在看起来convert.exe可能不再是新版本imageMagick的一部分了。文档说:

如果这些工具不可用,可以简单地将它们添加到magick工具后面,如下所示:
magick convert

对于matplotlib动画来说,这意味着您需要设置一个额外的参数。将路径设置为

plt.rcParams["animation.convert_path"] = "C:\ProgramFiles\ImageMagick\magick.exe"

然后调用。
ani.save("test.gif",writer="imagemagick", extra_args="convert")

我的ImageMagick安装似乎没有convert.exe。它应该有吗?不过,我在我的ImageMagick目录中看到了一个ffmpeg.exe。 - ishmandoo
如果你正在使用ImageMagick 7,那么convert已经更名为magick。所以你是否有magick.exe? - fmw42
@fmw42 我有 ImageMagick-7.0.3-Q16,也有 convert.exe。我还有一个 magick.exe,但在这种情况下没有用处。你有关于重命名的任何来源吗?否则我不会相信那个说法。 - ImportanceOfBeingErnest
但是你到目前为止是正确的,因为显然有一些版本没有所有命令工具。文档说:“如果这些工具不可用,您可以像这样简单地将它们附加到magick工具上:magick convert”。我会更新答案。 - ImportanceOfBeingErnest
1
Magick是convert的新版本,属于IM 7。在IM 7中,如果您有convert,则它是Windows安装时勾选遗留复选框的IM 6版本。使用magick convert与magick不同,但可能与遗留的convert相同。我对此并不确定。因此,如果您有convert并想使用旧代码,则仍应使用convert.exe。也许您正在使用的工具无法正确识别IM 7,您可能需要回退并删除它,然后安装较旧的IM 6版本。 - fmw42
我不确定你在说什么,但无论如何,就像我所说的,我已经更新了解决方案以适用于magick.exe。 - ImportanceOfBeingErnest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接