Matplotlib视频创作

时间:2017-03-20 21:42:45

标签: matplotlib

编辑:ImportanceOfBeingErnest提供了答案,但我仍然邀请大家解释一下,为什么savefig逻辑与animation逻辑不同。

我想在matplotlib制作视频。我阅读了手册和示例,但我还是没有得到它。 (关于matplotlib,我总是复制示例,因为经过五年的python和两年的mathplotlib,我仍然理解0.0%的matplotlib语法)

这里经过了六个小时后才是我的目标。好吧,我得到空视频。不知道为什么。

import os
import math
import matplotlib
matplotlib.use("Agg")
from matplotlib import pyplot as plt
import matplotlib.animation as animation

# Set up formatting for the movie files
Writer = animation.writers['ffmpeg']
writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800)

numb=100
temp=[0.0]*numb
cont=[0.0]*numb
for i in range(int(4*numb/10),int(6*numb/10)):
    temp[i]=2
    cont[i]=2

fig = plt.figure()
plts=fig.add_subplot(1,1,1)

plts.set_ylim([0,2.1])
plts.get_xaxis().set_visible(False)
plts.get_yaxis().set_visible(False)
ims = []

for i in range(1,10):
    line1, = plts.plot(range(0,numb),temp, linewidth=1, color='black')
    line2, = plts.plot(range(0,numb),cont, linewidth=1, color='red')
#    savefig is here for testing, works perfectly!
#    fig.savefig('test'+str(i)+'.png', bbox_inches='tight', dpi=300)
    ims.append([line1,line2])
    plts.lines.remove(line1)
    plts.lines.remove(line2)
    for j in range(1,10):
        tempa=0
        for k in range (1,numb-1):
            tempb=temp[k]+0.51*(temp[k-1]-2*temp[k]+temp[k+1])
            temp[k-1]=tempa
            tempa=tempb
        temp[numb-1]=0
    for j in range(1,20):
        conta=0
        for k in range (1,numb-1):
            contb=cont[k]+0.255*(cont[k-1]-2*cont[k]+cont[k+1])
            cont[k-1]=conta
            conta=contb
        cont[numb-1]=0

im_ani = animation.ArtistAnimation(fig, ims, interval=50, repeat_delay=3000,blit=True)
im_ani.save('im.mp4', writer=writer)

有人可以帮我这个吗?

1 个答案:

答案 0 :(得分:1)

如果你想要一个非空的情节,主要的想法就是不要删除情节中的线条。

即删除两行

plts.lines.remove(line1)
plts.lines.remove(line2)

如果删除这两行,输出将如下所示

enter image description here [Link to orginial size animation]

现在有人可能会问,为什么我不需要在每个迭代步骤中删除艺术家,否则所有的行都会立即填充画布?

答案是ArtistAnimation会处理这个问题。它仅显示提供列表中与给定时间步长相对应的那些艺术家。因此,在for循环结束时,您最终将所有线条绘制到画布上,一旦动画开始,它们将全部被移除,并且一次只显示一组艺术家。

在这种情况下,使用循环保存单个图像当然不是一个好主意,因为最终图像会同时包含所有绘制的行,

enter image description here

然后解决方案要么进行两次脚本运行,一次用于动画,另一次用于在每个时间步长中删除行。或者,也许更好,使用动画自己来创建图像。

im_ani.save('im.png', writer="imagemagick") 

会在当前文件夹中将图片创建为im-<nr>.png。它需要安装imagemagick。

<小时/> 我正在尝试回答评论中的两个问题:

1。 我在删除之前附加了line1和line2。他们仍然在最终结果中消失了。怎么样?

您已将这些行添加到列表中。之后,您从轴上删除了线条。现在这些行在列表中但不是轴的一部分。在进行动画制作时,matplotlib会在列表中找到这些行并使其可见。但它们不在轴中(因为它们已被移除),因此某些Line2D对象的可见性会发生变化,这些对象不在任何轴上,而只在内存中的某个位置。但这并没有反映在情节中,因为情节不再知道这条线。

2。 如果我理解正确,当您发出line1,= plts.plot ...命令时,则将line1绘图对象添加到plts图形对象。但是,如果通过再次发出line1,= plts.plot ...命令来更改line1绘图对象,则matplotlib会更改line1对象,但在此之前将旧的line1永久保存到plts图形对象。这是什么导致了我的问题?

没有。第一步是正确的,line1, = plts.plot(..)将一个Line2D对象添加到轴。但是,在稍后的循环步骤line1, = plts.plot()中创建另一个 Line2D对象并将其放入画布。最初的Line2D对象未更改,并且它不知道图中旁边现在还有其他一行。因此,如果不删除这些线,它们将在最后的静态图中显示。