使用 moviepy 为 matplotlib 图形设置动画的困难 [英] Difficulty animating a matplotlib graph with moviepy

查看:95
本文介绍了使用 moviepy 为 matplotlib 图形设置动画的困难的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须制作大量(〜90,000)个数字的动画.就上下文而言,它是从 1700 年到 1950 年的每一天的地图,并在相关日期标记了感兴趣的事件.我可以使用 matplotlib.animation.FuncAnimation 执行此操作,并且我的代码可以在一个小测试期间成功执行此操作.然而,使用完整的图形集,这花费了不切实际的时间来渲染,并且将导致非常大的电影文件.我已经读过,显然 moviepy 同时提供了速度和文件大小方面的优势.但是,我很难使它起作用–我认为我的问题是我不了解如何正确设置 duration fps 参数.

I have to make an animation of a large number (~90,000) figures. For context, it's a plot of a map for every day from 1700 - 1950, with events of interest marked on relevent days. I can do this using matplotlib.animation.FuncAnimation, and I have code that does this successfully for a small test period. However, with the complete set of figures this is taking an impractical amount of time to render and will result in a very large movie file. I have read that apparently moviepy offers both speed and file size advantages. However, I am having trouble getting this to work – I believe my problem is that I have not understood how to correctly set the duration and fps arguments.

我的代码的简化版本是:

A simplified version of my code is :

import numpy as np
import matplotlib.pyplot as plt
from moviepy.video.io.bindings import mplfig_to_npimage
import moviepy.editor as mpy

fig = plt.figure()
ax = plt.axes()
x = np.random.randn(10,1)
y = np.random.randn(10,1)
p = plt.plot(x,y,'ko')

time = np.arange(2341973,2342373)

def animate(i):
   xn = x+np.sin(2*np.pi*time[i]/10.0)
   yn = y+np.cos(2*np.pi*time[i]/8.0)
   p[0].set_data(xn,yn)
   return mplfig_to_npimage(fig)

fps = 1 
duration = len(time)
animation = mpy.VideoClip(animate, duration=duration)
animation.write_videofile("test.mp4", fps=fps)

但是,这不会产生为 time 的每个元素制作一帧电影并将其保存到.mp4的预期结果.我看不到哪里出了问题,任何帮助或建议都将不胜感激.

However, this does not produce the intended result of producing a movie with one frame for each element of time and saving this to an .mp4. I can’t see where I have gone wrong, any help or pointers would be appreciated.

最好的祝福,卢克

推荐答案

与JuniorCompressor相同的解决方案,在内存中仅保留一帧以避免RAM问题.这个例子在我的机器上运行了 30 秒,并生成了一个高质量的 400 秒剪辑,6000 帧,重 600k.

Same solution as JuniorCompressor, with just one frame kept in memory to avoid RAM issues. This example runs in 30 seconds on my machine and produces a good quality 400-second clip of 6000 frames, weighing 600k.

import numpy as np
import matplotlib.pyplot as plt
from moviepy.video.io.bindings import mplfig_to_npimage
import moviepy.editor as mpy

fig = plt.figure(facecolor="white") # <- ADDED FACECOLOR FOR WHITE BACKGROUND
ax = plt.axes()
x = np.random.randn(10, 1)
y = np.random.randn(10, 1)
p = plt.plot(x, y, 'ko')
time = np.arange(2341973, 2342373)

last_i = None
last_frame = None

def animate(t):
    global last_i, last_frame

    i = int(t)
    if i == last_i:
        return last_frame

    xn = x + np.sin(2 * np.pi * time[i] / 10.0)
    yn = y + np.cos(2 * np.pi * time[i] / 8.0)
    p[0].set_data(xn, yn)

    last_i = i
    last_frame = mplfig_to_npimage(fig)
    return last_frame

duration = len(time)
fps = 15
animation = mpy.VideoClip(animate, duration=duration)
animation.write_videofile("test.mp4", fps=fps)

顺便提一下,有专门的视频剪辑类称为 DataVideoClip 正是为了这个目的,它看起来更像 matplotlib 的 animate.目前,它并不是真正有效的速度(我上面没有包括这个小技巧).运作方式如下:

On a sidenote, there is dedicated class of videoclips called DataVideoClip for precisely this purpose, which looks much more like matplotlib's animate. For the moment it's not really speed-efficient (I didn't include that little memoizing trick above). Here is how it works:

from moviepy.video.VideoClip import DataVideoClip

def data_to_frame(time):
    xn = x + np.sin(2 * np.pi * time / 10.0)
    yn = y + np.cos(2 * np.pi * time / 8.0)
    p[0].set_data(xn, yn)
    return mplfig_to_npimage(fig)

times = np.arange(2341973, 2342373)
clip = DataVideoClip(times, data_to_frame, fps=1) # one plot per second

#final animation is 15 fps, but still displays 1 plot per second
animation.write_videofile("test2.mp4", fps=15) 

这篇关于使用 moviepy 为 matplotlib 图形设置动画的困难的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆