加速 matplotlib 动画到视频文件 [英] Speedup matplotlib animation to video file
问题描述
在 Raspbian (Raspberry Pi 2) 上,从我的脚本中删除的以下最小示例正确生成了一个 mp4 文件:
On Raspbian (Raspberry Pi 2), the following minimal example stripped from my script correctly produces an mp4 file:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
def anim_lift(x, y):
#set up the figure
fig = plt.figure(figsize=(15, 9))
def animate(i):
# update plot
pointplot.set_data(x[i], y[i])
return pointplot
# First frame
ax0 = plt.plot(x,y)
pointplot, = ax0.plot(x[0], y[0], 'or')
anim = animation.FuncAnimation(fig, animate, repeat = False,
frames=range(1,len(x)),
interval=200,
blit=True, repeat_delay=1000)
anim.save('out.mp4')
plt.close(fig)
# Number of frames
nframes = 200
# Generate data
x = np.linspace(0, 100, num=nframes)
y = np.random.random_sample(np.size(x))
anim_lift(x, y)
现在,制作的文件质量很好,文件很小,但是制作一部 170 帧的电影需要 15 分钟,这对我的应用程序来说是不可接受的.我正在寻找显着的加速,视频文件大小增加不是问题.
Now, the file is produced with good quality and pretty small file size, but it takes 15 minutes to produce a 170 frames movie, which is not acceptable for my application. i'm looking for a significant speedup, video file size increase is not a problem.
我认为视频制作的瓶颈在于以 png 格式临时保存帧.在处理过程中,我可以看到 png 文件出现在我的工作目录中,CPU 负载仅为 25%.
I believe the bottleneck in the video production is in the temporary saving of the frames in png format. During processing I can see the png files apprearing in my working directory, with the CPU load at 25% only.
请提出一个解决方案,该解决方案也可能基于不同的包,而不是简单的 matplotlib.animation
,例如 OpenCV
(无论如何已经导入到我的项目中)或 moviepy
.
Please suggest a solution, that might also be based on a different package rather than simply matplotlib.animation
, like OpenCV
(which is anyway already imported in my project) or moviepy
.
正在使用的版本:
- python 2.7.3
- matplotlib 1.1.1rc2
- ffmpeg 0.8.17-6:0.8.17-1+rpi1
推荐答案
将动画保存到文件的瓶颈在于figure.savefig()
的使用.这是 matplotlib 的一个自制子类 FFMpegWriter
,灵感来自 gaggio 的回答.它不使用 savefig
(因此忽略了 savefig_kwargs
),但只需要对您的动画脚本进行最少的更改.
The bottleneck of saving an animation to file lies in the use of figure.savefig()
. Here is a homemade subclass of matplotlib's FFMpegWriter
, inspired by gaggio's answer. It doesn't use savefig
(and thus ignores savefig_kwargs
) but requires minimal changes to whatever your animation script are.
from matplotlib.animation import FFMpegWriter
class FasterFFMpegWriter(FFMpegWriter):
'''FFMpeg-pipe writer bypassing figure.savefig.'''
def __init__(self, **kwargs):
'''Initialize the Writer object and sets the default frame_format.'''
super().__init__(**kwargs)
self.frame_format = 'argb'
def grab_frame(self, **savefig_kwargs):
'''Grab the image information from the figure and save as a movie frame.
Doesn't use savefig to be faster: savefig_kwargs will be ignored.
'''
try:
# re-adjust the figure size and dpi in case it has been changed by the
# user. We must ensure that every frame is the same size or
# the movie will not save correctly.
self.fig.set_size_inches(self._w, self._h)
self.fig.set_dpi(self.dpi)
# Draw and save the frame as an argb string to the pipe sink
self.fig.canvas.draw()
self._frame_sink().write(self.fig.canvas.tostring_argb())
except (RuntimeError, IOError) as e:
out, err = self._proc.communicate()
raise IOError('Error saving animation to file (cause: {0}) '
'Stdout: {1} StdError: {2}. It may help to re-run '
'with --verbose-debug.'.format(e, out, err))
与使用默认的 FFMpegWriter
相比,我能够用一半或更短的时间创建动画.
I was able to create animation in half the time or less than with the default FFMpegWriter
.
您可以按照本示例中的说明使用.
You can use is as explained in this example.
这篇关于加速 matplotlib 动画到视频文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!