【问题标题】:How to create high-res animations with Matplotlib without memory problems?如何使用 Matplotlib 创建高分辨率动画而不会出现内存问题?
【发布时间】:2018-08-08 23:07:53
【问题描述】:

我想创建至少 200*300 分辨率和 500 帧的 Matplotlib 热图动画。问题是我拍摄的动画的标准方法存在巨大的内存泄漏(如this question* 中所述)。当动画开始绘制或写出时,RAM 开始被填满,直到系统冻结,直到脚本被终止。太糟糕了,即使我的 4gb RAM 和 4gb 交换在一起也不够。除了创建更小的块并在那里一起编辑之外,还有什么方法可以制作该动画?

这是我的代码,稍加简化。 (注意:运行需要几分钟,可能会完全填满你的内存,导致死机。)

import numpy as np
from matplotlib import pyplot as plt
import matplotlib.animation as animation

def waveanim(frames, trange, xbounds, ybounds, xnum, ynum, fps):

    xpoints = np.linspace(*xbounds, xnum)
    ypoints = np.linspace(*ybounds, ynum)
    tmin, tmax = trange

    # this part is a complicated calculation in my actual code; point is I have all the 
    # values for all the time points in an array that I calculate like this ready before 
    # I even start animating. (Since the calculation involves an inverse FFT, I can't just use NumPy's cool array managing abilities as ImportanceOfBeingErnest's answer suggests.)
    result = np.empty((xnum, ynum, frames), dtype="float64")
    for i, x in enumerate(xpoints):
        print("calculating: {} out of {}".format(i, len(xpoints)), end='\r')
        for j, y in enumerate(ypoints):
            arr = np.array([np.sin(x+t) + np.cos(x-y-2*t) for t in np.linspace(tmin, tmax, frames)])
            result[i,j] = arr
    print('\n')
    def animate(i):
        print("animating: {} out of {}".format(i, frames), end='\r')
        val = result[:,:,i].transpose()
        pc = plt.pcolor(xpoints, ypoints, val, cmap='jet')
        return pc,

    fig, ax = plt.subplots()
    im_ani = animation.FuncAnimation(fig, animate, frames=frames, interval=1000/fps, repeat_delay=0, blit=True)
    plt.show()


def main():

    trange = (-10.0, 10.0)
    xbounds = (-20.0, 20.0)
    ybounds = (-20.0, 20.0)
    frames = 100
    xnum = 300
    ynum = 300
    fps = 25
    waveanim(frames, trange, xbounds, ybounds, xnum, ynum, fps)

if __name__ == '__main__':
     main()

我还尝试单独生成图,将它们放入一个数组中,然后将该数组放入ArtistAnimation,就像在this example 中一样,但结果是一样的。

*我的不是骗子,因为 a) 我在 Kubuntu 上工作,而不是在 iOS 上工作,并且修复是特定于操作系统的,b) 因为我不限制解决泄漏错误的解决方案。

【问题讨论】:

    标签: python-3.x animation matplotlib


    【解决方案1】:

    您正在同一图中创建 100 个plt.pcolor 图。这肯定很多。为了有效地使用内存,您只能使用单个 plt.pcolor 绘图。然后,您可以在每个动画步骤中更新此图。 (这个概念实际上也用在了链接的问题中,只是针对不同的情节类型。)

    为了节省计算时间,您还可以摆脱嵌套的 python 循环来填充数组,而是使用 numpy.这将减少动画开始的时间,从大约 1 分钟到几秒钟。

    import numpy as np
    from matplotlib import pyplot as plt
    import matplotlib.animation as animation
    
    def waveanim(frames, trange, xbounds, ybounds, xnum, ynum, fps):
    
        xpoints = np.linspace(*xbounds, xnum)
        ypoints = np.linspace(*ybounds, ynum)
        tmin, tmax = trange
    
        # Evaluating a function on a grid is more efficient than using a python loop
        X, Y, T = np.meshgrid(xpoints, ypoints, np.linspace(tmin, tmax, frames))
        # Because pcolor(mesh) defines the values at the edges of the pixels,
        # we need one less row and column in the result
        result = (np.sin(X+T) + np.cos(X-Y-2*T))[:-1,:-1,:]
    
    
        def animate(i):
            print("animating: {} out of {}".format(i, frames), end='\r')
            val = result[:,:,i]
            # update the values of the pcolormesh plot
            pc.set_array(val.flatten())
            return pc,
    
        fig, ax = plt.subplots()
        norm = plt.Normalize(result.min(), result.max())
        pc = plt.pcolormesh(xpoints, ypoints, result[:,:,0], cmap='jet', norm=norm)
        im_ani = animation.FuncAnimation(fig, animate, frames=frames, interval=1000/fps, 
                                         repeat_delay=0, blit=True)
        plt.show()
    
    
    def main():
    
        trange = (-10.0, 10.0)
        xbounds = (-20.0, 20.0)
        ybounds = (-20.0, 20.0)
        frames = 100
        xnum = 300
        ynum = 300
        fps = 25
        waveanim(frames, trange, xbounds, ybounds, xnum, ynum, fps)
    
    if __name__ == '__main__':
         main()
    

    【讨论】:

      猜你喜欢
      • 2014-07-08
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      • 1970-01-01
      • 2010-12-04
      • 1970-01-01
      • 2017-02-13
      • 1970-01-01
      相关资源
      最近更新 更多