如何为matplotlib图的时间序列序列设置动画

ely*_*ely 15 python animation image image-processing matplotlib

我想在matplotlib中绘制一系列.png图像.目标是快速绘制它们以模拟电影的效果,但我有其他理由想要避免实际创建.avi文件或保存matplotlib图形,然后在Python之外按顺序查看它们.

我特意尝试在Python中的for循环中按顺序查看图像文件.假设我已正确导入matplotlib,并且我有自己的函数'new_image()'和'new_rect()',这里有一些示例代码无法工作,因为show()函数调用GUI mainloop的阻塞效果:

 for index in index_list:
     img = new_image(index)
     rect = new_rect(index)

     plt.imshow(img)
     plt.gca().add_patch(rect)
     plt.show()

     #I also tried pausing briefly and then closing, but this doesn't
     #get executed due to the GUI mainloop from show()
     time.sleep(0.25)
     plt.close()
Run Code Online (Sandbox Code Playgroud)

上面的代码只能显示第一个图像,但程序只是挂起并等待我手动关闭结果图窗口.一旦我关闭它,程序就会挂起并且不会重新绘制新的图像数据.我该怎么办?另请注意,我已尝试使用plt.draw()命令替换plt.show()命令,然后在for循环外添加plt.show().这不会显示任何内容而只是挂起.

unu*_*tbu 8

基于http://matplotlib.sourceforge.net/examples/animation/simple_anim_tkagg.html:

import time
import numpy as np
import matplotlib
matplotlib.use('TkAgg') # do this before importing pylab

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)

def animate():
    tstart = time.time()                   # for profiling
    data=np.random.randn(10,10)
    im=plt.imshow(data)

    for i in np.arange(1,200):
        data=np.random.randn(10,10)
        im.set_data(data)
        fig.canvas.draw()                         # redraw the canvas
    print 'FPS:' , 200/(time.time()-tstart)

win = fig.canvas.manager.window
fig.canvas.manager.window.after(100, animate)
plt.show()
Run Code Online (Sandbox Code Playgroud)

plt.imshow可以接受float数组,uint8数组或PIL图像.因此,如果你有一个PNG文件目录,你可以打开它们作为PIL图像并像这样动画它们:

import matplotlib
matplotlib.use('TkAgg') # do this before importing pylab
import matplotlib.pyplot as plt
import Image
import glob

fig = plt.figure()
ax = fig.add_subplot(111)

def animate():
    filenames=sorted(glob.glob('*.png'))
    im=plt.imshow(Image.open(filenames[0]))
    for filename in filenames[1:]:
        image=Image.open(filename)
        im.set_data(image)
        fig.canvas.draw() 

win = fig.canvas.manager.window
fig.canvas.manager.window.after(100, animate)
plt.show()
Run Code Online (Sandbox Code Playgroud)


ely*_*ely 6

我找到的最好方法是pylab.ion()在导入pylab后使用命令.

这是一个确实使用的脚本show(),但每次pylab.draw()调用时都会显示不同的绘图,并使绘图窗口无限期显示.它使用简单的输入逻辑来决定何时关闭数字(因为使用show()pylab不会处理windows x按钮上的点击),但这应该很容易添加到你的gui作为另一个按钮或文本字段.

import numpy as np
import pylab
pylab.ion()

def get_fig(fig_num, some_data, some_labels):

    fig = pylab.figure(fig_num,figsize=(8,8),frameon=False)
    ax = fig.add_subplot(111)
    ax.set_ylim([0.1,0.8]); ax.set_xlim([0.1, 0.8]);
    ax.set_title("Quarterly Stapler Thefts")
    ax.pie(some_data, labels=some_labels, autopct='%1.1f%%', shadow=True);
    return fig

my_labels = ("You", "Me", "Some guy", "Bob")

# To ensure first plot is always made.
do_plot = 1; num_plots = 0;

while do_plot:
    num_plots = num_plots + 1;
    data = np.random.rand(1,4).tolist()[0]

    fig = get_fig(num_plots,data,my_labels)
    fig.canvas.draw()
    pylab.draw()

    print "Close any of the previous plots? If yes, enter its number, otherwise enter 0..."
    close_plot = raw_input()

    if int(close_plot) > 0:
        pylab.close(int(close_plot))

    print "Create another random plot? 1 for yes; 0 for no."
    do_plot = raw_input();

    # Don't allow plots to go over 10.
    if num_plots > 10:
        do_plot = 0

pylab.show()
Run Code Online (Sandbox Code Playgroud)

通过在这里修改基本逻辑,我可以让它关闭窗口并连续绘制图像以模拟播放电影,或者我可以保持键盘控制它如何逐步完成电影.

注意:这对我来说跨平台有用,并且看起来严格优于上面的窗口画布管理器方法,并且不需要'TkAgg'选项.