【问题标题】:Error saving matplotlib animation in Gif在 Gif 中保存 matplotlib 动画时出错
【发布时间】:2018-12-31 19:27:20
【问题描述】:

我在将一组二维数组保存到 Gif 时遇到问题。我搜索了类似的标题,但没有发现相同的问题。

我有 600 个包含数据的文件,它们是 93*226 浮点数组。我只需要将它们绘制成 gif 文件。

import numpy as np
import os
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib
from  matplotlib.animation import FuncAnimation

# reading files
path = '/home/Anton/Heat'
files = os.listdir(path)
files.sort()
print('Number of files:', len(files))
arr = []

for i in range(len(files[0:150])):  # read files
    file = files[i]
    df = pd.read_csv(path + '/'+ file, sep = ' ', skiprows = 2, header = None) # skip 2 lines
    arr.append(df.values[:,1:]) # skip 1st col
arr = np.array(arr)

fig = plt.figure(figsize=(14,25))
zmin, zmax = 50, 1150  # scale for Z values
norm = matplotlib.colors.Normalize(vmin=zmin, vmax=zmax, clip=False)
im = plt.imshow(np.transpose(arr[0,:,:]), animated = True, cmap = plt.cm.gist_heat, norm=norm)
plt.grid(False)
nst = arr.shape[0] # number of frames in Gif == number of files read

def update(i):
    im.set_array(np.transpose(arr[i,:,:]))
    return im

# create and save animation
anim = FuncAnimation(fig, update, frames=range(nst), interval=50, repeat = False)
anim.save('/home/Anton/Heat_1/Heating_1.gif', writer='imagemagick')

所以如果我在循环中设置要读取的文件数 = 50

for i in range(len(files[0:50]))

,正常工作。或者,或者,如果我阅读了所有 600 个文件,但以小分辨率保存它们

fig = plt.figure(figsize=(10,7))
...
anim.save('/home/Anton/Heat_1/Heating_1.gif', dpi = 50, writer='imagemagick')

它也有效。

但是当我将文件数设置为大于 ~50(例如,如上所示的 150)和/或更大的 figsize 时,我收到一个错误:

ValueError                                Traceback (most recent call last)
<ipython-input-171-7897cf1b47b2> in <module>()
     91 anim = FuncAnimation(fig, update, interval=50, repeat = False)
---> 92 anim.save('/home/zizin/Heat_1/Heating_1.gif', writer='imagemagick')

~/anaconda3/lib/python3.6/site-packages/matplotlib/animation.py in save(self, filename, writer, fps, dpi, codec, bitrate, extra_args, metadata, extra_anim, savefig_kwargs)
   1258                         # TODO: See if turning off blit is really necessary
   1259                         anim._draw_next_frame(d, blit=False)
-> 1260                     writer.grab_frame(**savefig_kwargs)
~/anaconda3/lib/python3.6/contextlib.py in __exit__(self, type, value, traceback)
     97                 value = type()
     98             try:
---> 99                 self.gen.throw(type, value, traceback)
~/anaconda3/lib/python3.6/site-packages/matplotlib/animation.py in saving(self, fig, outfile, dpi, *args, **kwargs)
    235             yield self
    236         finally:
--> 237             self.finish()
~/anaconda3/lib/python3.6/site-packages/matplotlib/animation.py in finish(self)
    367     def finish(self):
    368         '''Finish any processing for writing the movie.'''
--> 369         self.cleanup()
~/anaconda3/lib/python3.6/site-packages/matplotlib/animation.py in cleanup(self)
    406     def cleanup(self):
    407         '''Clean-up and collect the process used to write the movie file.'''
--> 408         out, err = self._proc.communicate()
~/anaconda3/lib/python3.6/subprocess.py in communicate(self, input, timeout)
    841 
    842             try:
--> 843                 stdout, stderr = self._communicate(input, endtime, timeout)
~/anaconda3/lib/python3.6/subprocess.py in _communicate(self, input, endtime, orig_timeout)
   1503                     selector.register(self.stdin, selectors.EVENT_WRITE)
   1504                 if self.stdout:
-> 1505                     selector.register(self.stdout, selectors.EVENT_READ)
~/anaconda3/lib/python3.6/selectors.py in register(self, fileobj, events, data)
    349 
    350         def register(self, fileobj, events, data=None):
--> 351             key = super().register(fileobj, events, data)
~/anaconda3/lib/python3.6/selectors.py in register(self, fileobj, events, data)
    235             raise ValueError("Invalid events: {!r}".format(events))
    236 
--> 237         key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
~/anaconda3/lib/python3.6/selectors.py in _fileobj_lookup(self, fileobj)
    222         """
    223         try:
--> 224             return _fileobj_to_fd(fileobj)
~/anaconda3/lib/python3.6/selectors.py in _fileobj_to_fd(fileobj)
     37         except (AttributeError, TypeError, ValueError):
     38             raise ValueError("Invalid file object: "
---> 39                              "{!r}".format(fileobj)) from None
ValueError: Invalid file object: <_io.BufferedReader name=54>

【问题讨论】:

  • 我无法重现该问题。使用您的代码和随机生成的数据,我成功地生成了 600 或 1000 帧的 gif。你应该尝试做同样的事情(即绕过图片的阅读),看看是否能解决问题,也许看看你是否可以查明是否有特定的图片文件导致错误?
  • 会不会是Linux限制的进程内存不足? (虽然我有 64 GB RAM,和 8 核 i9)
  • 我对系统之间的差异了解不多,但我对此表示怀疑,因为您似乎拥有高端 CPU 和大量 RAM。如果您想测试它,这是我使用的代码clippr.co/H1c1sWSNX41589
  • 我记得在通过 ffmpeg 保存许多 (>1000) 帧时,以前版本的 matplotlib 中存在类似(不一样)的错误。您使用的是 matplotlib 2.2.2 吗?
  • 我有 matplotlib.__version__ 2.1.2

标签: python matplotlib gif animated-gif


【解决方案1】:

我已删除 writer='imagemagick' 来自

anim.save('/home/Anton/Heat_1/Heating.gif', writer='imagemagick')

现在它可以工作了。 ¯\_(ツ)_/¯

【讨论】:

  • 我遇到了同样的问题,但是当我删除 imagemagick 时,gif 只运行一次并且没有循环。
猜你喜欢
  • 2014-09-28
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 2014-09-01
  • 2018-03-24
  • 2015-01-12
  • 2013-08-03
相关资源
最近更新 更多