Exporting animated gif using matplotlib

2019-02-14 15:59发布

I've been trying to export an animated gif on my windows computer for several days.

Here is the basic code:

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()

And the error:

>>> 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.

If I switch the output file type to mp4, the code works. After reading many threads from people with errors producing video files, I feel like I have tried every combination of different writers (including FFMpegWriter, ImageMagickWriter, AVConvWriter, and the FileWriters as well), made sure the relevant programs are in my PATH, changed settings in matplotlibrc, and tried multiple computers. I'm stumped.

I've found only one thread referencing this exact error: https://stackoverflow.com/questions/46562938/oserror-errno-22-invalid-argument-error-saving-animation-to-file

But following the advice in the comments there haven't solved my problem.

Any ideas? Thanks for any help.

1条回答
贪生不怕死
2楼-- · 2019-02-14 16:33

With the code from the question you are basically asking to produce an animated gif using the MPEG writer. The MPEG writer however is only able to produce videos.

The standard way to produce an animated gif through the matplotlib animation module is to use ImageMagick.

So first change your line to

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

Now for this to work the rcParam animation.convert_path must point to the ImageMagick's convert program.
It seems you are on windows here, so it's best to include the complete path to it. Hence, before the saving, set

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

or whatever your path to the convert.exe may be.

Now it may apparently happen that convert.exe is not part of newer versions of imageMagick anymore. The documentation says

If these tools are not available, you can simply append them to the magick tool like this:
magick convert.

For the matplotlib animation this means that you would need to set an extra argument. Set the path to

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

then call

ani.save("test.gif",writer="imagemagick", extra_args="convert")
查看更多
登录 后发表回答