使用ArtistAnimation在matplotlib中制作动画png。

6
我一直在尝试使用有限元方法创建的一系列表面图来实现2D热流问题的动画。每个时间步骤,我保存了一个图而不是整个矩阵,以提高效率。
我在matplotlib.animation库中使用FuncAnimation时遇到了问题,因此我决定在每个时间点上渲染一个表面图,将表面图保存为.png文件,然后使用pyplot.imread读取该图像。从那里开始,我想将每个图像存储到列表中,以便我可以使用ArtistAnimation(示例)进行动画处理。但是它没有制作动画,相反,当我将imgplot打印到屏幕时,我得到两个单独的空白图和我的表面图.png。
此外,当我尝试保存动画时,我会收到以下错误消息:
AttributeError: 'module' object has no attribute 'save'.

任何有关从当前目录读取一组.png文件,将它们保存在列表中,然后使用ArtistAnimation“动画”这些.png文件的帮助将不胜感激。我不需要什么花哨的东西。
(注意-我必须使代码自动化,所以不幸的是我不能使用像iMovie或ffmpeg这样的外部来源来使我的图像动画化。)
以下是我的代码:
from numpy import *
from pylab import *
import matplotlib.pyplot as plt 
import matplotlib.image as mgimg
from matplotlib import animation

## Read in graphs

p = 0
myimages = []

for k in range(1, len(params.t)):

  fname = "heatflow%03d.png" %p 
      # read in pictures
  img = mgimg.imread(fname)
  imgplot = plt.imshow(img)

  myimages.append([imgplot])

  p += 1


## Make animation

fig = plt.figure()
animation.ArtistAnimation(fig, myimages, interval=20, blit=True, repeat_delay=1000)

animation.save("animation.mp4", fps = 30)
plt.show()
2个回答

5
问题1:图片无法显示 需要将动画对象存储在变量中:
my_anim = animation.ArtistAnimation(fig, myimages, interval=100)

这一要求是针对 animation 的,与其他在 matplotlib 中绘图函数不一致。在其他函数中,您通常可以随意使用 my_plot=plt.plot()plt.plot()

进一步讨论此问题请见此处

问题2:保存无效

如果没有任何 animation 实例,则也无法保存图形。这是因为 save 方法属于 ArtistAnimation 类。您所做的是从 animation 模块调用 save,这就是引发错误的原因。

问题3:两个窗口

最后一个问题是您得到了两个弹出的图形窗口。原因是当您调用 plt.imshow() 时,它会在当前图形上显示图像,但由于尚未创建图形,pyplot 会自动为您创建一个。 当 python 后面解释 fig = plt.figure() 语句时,它将创建一个新的图形(另一个窗口)并将其标记为“Figure 2” 。将此语句移到代码开头即可解决此问题。

这是修改后的代码:

import matplotlib.pyplot as plt 
import matplotlib.image as mgimg
from matplotlib import animation

fig = plt.figure()

# initiate an empty  list of "plotted" images 
myimages = []

#loops through available png:s
for p in range(1, 4):

    ## Read in picture
    fname = "heatflow%03d.png" %p 
    img = mgimg.imread(fname)
    imgplot = plt.imshow(img)

    # append AxesImage object to the list
    myimages.append([imgplot])

## create an instance of animation
my_anim = animation.ArtistAnimation(fig, myimages, interval=1000, blit=True, repeat_delay=1000)

## NB: The 'save' method here belongs to the object you created above
#my_anim.save("animation.mp4")

## Showtime!
plt.show()

要运行上述代码,只需将3个图片添加到您的工作文件夹中,并将其命名为“heatflow001.png”到“heatflow003.png”。

使用FuncAnimation的替代方法

当您尝试使用FuncAnimation时,您可能是正确的,因为在列表中收集图像在内存方面成本高昂。我通过比较系统监视器上的内存使用情况,将下面的代码与上面的代码进行了测试。看起来FuncAnimation方法更有效。我相信随着您使用更多图像,差异会变得越来越大。

以下是第二个代码:

from matplotlib import pyplot as plt  
from matplotlib import animation  
import matplotlib.image as mgimg
import numpy as np

#set up the figure
fig = plt.figure()
ax = plt.gca()

#initialization of animation, plot array of zeros 
def init():
    imobj.set_data(np.zeros((100, 100)))

    return  imobj,

def animate(i):
    ## Read in picture
    fname = "heatflow%03d.png" % i 

    ## here I use [-1::-1], to invert the array
    # IOtherwise it plots up-side down
    img = mgimg.imread(fname)[-1::-1]
    imobj.set_data(img)

    return  imobj,


## create an AxesImage object
imobj = ax.imshow( np.zeros((100, 100)), origin='lower', alpha=1.0, zorder=1, aspect=1 )


anim = animation.FuncAnimation(fig, animate, init_func=init, repeat = True,
                               frames=range(1,4), interval=200, blit=True, repeat_delay=1000)

plt.show()

0

@snake_charmer的答案对我有效,除了save()方法(问题2:无法保存)

如果您使用以下编写器,则可以正常工作:

Writer = animation.writers['ffmpeg']
writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800)
my_anim.save("animation.mp4", writer=writer)

请参考:https://matplotlib.org/gallery/animation/basic_example_writer_sgskip.html

在Mac上,您可能需要通过homebrew安装FFmpeg:https://apple.stackexchange.com/questions/238295/installing-ffmpeg-with-homebrew


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