我一直在尝试将我用有限元法为一个二维热流问题创建的一系列曲面图制作成动画。在每个时间步骤中,我保存了一个图,而不是整个矩阵,以提高工作效率。
我在以下方面遇到了问题 FuncAnimation
中的matplotlib.animation库,所以我决定每次都渲染一个曲面图,将曲面图保存为一个.png文件,然后使用 pyplot.imread
. 从那里,我想把每个图像存储到一个列表中,这样我就可以使用 艺术家动画 ( 例子). 然而,它并没有制作动画,相反,当我打印出 imgplot
到屏幕上。
此外,当我尝试保存动画时,我得到了以下错误信息。
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
方法属于 ArtistAnimation
类。你所做的是调用 save
来自 animation
模块,这就是引发错误的原因。
问题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 "到 "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()
@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.orggalleryanimationbasic_example_writer_sgskip.html。
在Mac上,你可能需要在homebrew上安装FFmpeg。https:/apple.stackexchange.comquestions238295安装ffmpeg-with-homebrew。