使用ArtistAnimation在matplotlib中对png进行动画处理 [英] Animating pngs in matplotlib using ArtistAnimation
问题描述
我一直在尝试为我使用有限元方法为二维热流问题创建的一系列曲面图制作动画。在每个时间步,我都保存了一个图而不是整个矩阵,以提高效率。
I have been trying to animate a series of surface plots that I created for a 2D heat flow problem using finite element method. At each time step, I saved a plot instead of the whole matrix, in order to be more efficient.
我遇到了 FuncAnimation
在matplotlib.animation库中,因此我决定每次渲染一个表面图,将表面图保存为.png文件,然后使用 pyplot.imread读取该图像
。从那里,我想将每个图像存储到一个列表中,以便可以使用 ArtistAnimation (< a href = http://matplotlib.org/examples/animation/dynamic_image2.html rel = nofollow>示例)。但是,它不是制作动画,而是当我在屏幕上打印 imgplot
时得到两个单独的空白图,然后得到我的表面图.png。
I had trouble with the FuncAnimation
in the matplotlib.animation library, so I decided to render a surface plot at each time, save the surface plot as a .png file, and then read that image using pyplot.imread
. From there, I want to store each image into a list so that I can use the ArtistAnimation ( example). However it is not making the animation, instead I get two separate blank plots and then my surface plot .pngs when I print imgplot
to the screen.
此外,当我尝试保存动画时,出现以下错误消息:
Additionally, when I try to save the animation, I get the following error message:
AttributeError: 'module' object has no attribute 'save'.
从当前目录读取一组.png并将其保存在列表中的任何帮助,然后使用ArtistAnimation对这些.png进行动画处理将不胜感激。我不需要任何花哨的东西。
Any help with reading in a set of .pngs from the current directory, saving them in a list, and then using ArtistAnimation to "animate" those .pngs would be greatly appreciated. I do not need anything fancy.
(注意-我必须使代码自动化,因此很遗憾,我无法使用外部源为iMovie或ffmpeg等图像制作动画。 )
(Note - I have to make the code automated, so unfortunately I cannot use an outside source to animate my images like iMovie or 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:不显示图像
您需要将动画对象存储在变量中:
You need to store your animation object in a variable:
my_anim = animation.ArtistAnimation(fig, myimages, interval=100)
此要求特定于动画
,并且与 matplotlib
中的其他绘图功能不一致,在这里,通常可以不加区别地使用 my_plot = plt.plot()
或 plt.plot()
。
This requirement is specific for animation
and is not consistent with other plotting function in matplotlib
, where you can usually use my_plot=plt.plot()
or plt.plot()
indifferently.
问题2:保存无效
没有任何< codeanimation 实例,也将无法保存数字。这是因为保存
方法
属于 ArtistAnimation
类。您所做的是从动画
模块调用保存
,这是引发错误的原因。
Without any animation
instance, it will not be possible to save a figure either. This is because the save
method
belongs to the ArtistAnimation
class. What you did was calling save
from the animation
module, this is what raised the error.
问题3:两个窗口
最后一个问题是弹出两个数字。原因是,当您调用 plt.imshow()
时,它将在当前图形上显示一个图像,但是由于尚未创建任何图形,因此 pyplot
为您隐式创建一个。
当python稍后解释 fig = plt.figure()
语句时,它将创建一个新图形(另一个窗口)并将其标记为图2。
将此语句移到代码的开头即可解决该问题。
The last issue is that you get two figures popping up. The reason is that when you call plt.imshow()
, it displays an image on the current figure, but since no figure has been created yet, pyplot
implicitly creates one for you.
When python later interprets the fig = plt.figure()
statement, it creates a new figure (another window) and labels it "Figure 2".
Moving this statement to the beginning of your code, solves that problem.
这是修改后的代码:
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。)
(To run the code above, just add 3 images into your working folder with name "heatflow001.png" through "heatflow003.png".)
使用 FuncAnimation $ c的替代方法$ c>
Alternative approach using FuncAnimation
您第一次尝试使用 FuncAnimation
时可能是正确的,因为它收集了图像列表中的内存消耗很大。我通过比较
系统监视器上的内存使用情况,针对上面的代码测试了以下代码。看来 FuncAnimation
方法更有效。我相信随着您使用更多的图像,这种差异会越来越大。
You were probably right when you first tried to use FuncAnimation
, since gathering images in a list is costly in terms of memory. I tested the code below against the one above, by comparing memory usage on the
system monitor. It appears that the FuncAnimation
approach is more efficient. I believe the difference will grow even bigger as you use more images.
这是第二个代码:
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()
这篇关于使用ArtistAnimation在matplotlib中对png进行动画处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!