使用ArtistAnimation在matplotlib中设置png的动画



我一直在尝试使用有限元方法为2D热流问题创建一系列曲面图。在每个时间步长,我都保存了一个图,而不是整个矩阵,以提高效率。

我在matplotlib.animation库中的FuncAnimation遇到了问题,所以我决定每次渲染一个曲面图,将曲面图保存为.png文件,然后使用pyplot.imread读取该图像。从那里,我想将每个图像存储到一个列表中,这样我就可以使用ArtistAnimation(示例)。然而,它并没有制作动画,相反,当我将imgplot打印到屏幕上时,我得到了两个单独的空白图,然后是我的曲面图.pngs。

此外,当我试图保存动画时,我会收到以下错误消息:

AttributeError: 'module' object has no attribute 'save'.

如果您能从当前目录中读取一组.pngs,将其保存在列表中,然后使用ArtistAnimation对这些.pngs进行"动画化",我们将不胜感激。我不需要任何花哨的东西。

(注意-我必须使代码自动化,所以不幸的是,我不能使用外部源来动画我的图像,如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()

问题1:不显示图像

您需要将动画对象存储在一个变量中:

my_anim = animation.ArtistAnimation(fig, myimages, interval=100)

这一要求是针对animation的,与matplotlib中的其他绘图功能不一致,通常可以使用my_plot=plt.plot()plt.plot()

这个问题将在这里进一步讨论。

问题2:保存不起作用

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

问题3:两个窗口

最后一个问题是,你会弹出两个数字。原因是,当您调用plt.imshow()时,它会在当前地物上显示一个图像,但由于尚未创建地物,pyplot会隐式为您创建一个。当python稍后解释fig = plt.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"到"heatfflow003.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()

@swake_charmer答案对我有效,除了save()(问题2:save不起作用)

如果你使用这样的编写器,它就会起作用:

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上,您可能需要在自制软件上安装FFmpeg:https://apple.stackexchange.com/questions/238295/installing-ffmpeg-with-homebrew

最新更新