Python Matplotlib.animation:如何删除白边

Python Matplotlib.animation:如何删除白边,python,animation,video,matplotlib,Python,Animation,Video,Matplotlib,我尝试使用matplotlib电影编写器生成电影。如果我这样做,我总是会在视频周围留一个空白。有没有人知道如何消除这种差距 调整的示例来自 在最近的示例中,您似乎可以将参数传递给编写器: def grab_frame(self, **savefig_kwargs): ''' Grab the image information from the figure and save as a movie frame. All keyword argume

我尝试使用matplotlib电影编写器生成电影。如果我这样做,我总是会在视频周围留一个空白。有没有人知道如何消除这种差距

调整的示例来自

在最近的示例中,您似乎可以将参数传递给编写器:

def grab_frame(self, **savefig_kwargs):
        '''
        Grab the image information from the figure and save as a movie frame.
        All keyword arguments in savefig_kwargs are passed on to the 'savefig'
        command that saves the figure.
        '''
        verbose.report('MovieWriter.grab_frame: Grabbing frame.',
                       level='debug')
        try:
            # Tell the figure to save its data to the sink, using the
            # frame format and dpi.
            self.fig.savefig(self._frame_sink(), format=self.frame_format,
                dpi=self.dpi, **savefig_kwargs)
        except RuntimeError:
            out, err = self._proc.communicate()
            verbose.report('MovieWriter -- Error running proc:\n%s\n%s' % (out,
                err), level='helpful')
            raise
如果是这种情况,您可以通过
bbox\u inches=“tight”
pad\u inches=0
来抓取帧->保存图,这将删除大部分边框。然而,Ubuntu上最新的版本仍然有以下代码:

def grab_frame(self):
    '''
    Grab the image information from the figure and save as a movie frame.
    '''
    verbose.report('MovieWriter.grab_frame: Grabbing frame.',
                   level='debug')
    try:
        # Tell the figure to save its data to the sink, using the
        # frame format and dpi.
        self.fig.savefig(self._frame_sink(), format=self.frame_format,
            dpi=self.dpi)
    except RuntimeError:
        out, err = self._proc.communicate()
        verbose.report('MovieWriter -- Error running proc:\n%s\n%s' % (out,
            err), level='helpful')
        raise

因此,看起来功能正在投入使用。抓住这个版本,给它一个机会

传递
None
作为
子批次调整的论据,不会做您认为它会做的事情。它的意思是“使用deault值”。要执行所需操作,请使用以下命令:

fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=None, hspace=None)
如果重复使用
ImageAxes
对象,还可以使代码更加高效

mat = np.random.random((100,100))
im = ax.imshow(mat,interpolation='nearest')
with writer.saving(fig, "writer_test.mp4", 100):
    for i in range(100):
        mat = np.random.random((100,100))
        im.set_data(mat)
        writer.grab_frame()
默认情况下,
imshow
将纵横比固定为相等,即像素为正方形。您需要重新调整体形的大小,使其与图像的纵横比相同:

fig.set_size_inches(w, h, forward=True)
或者告诉
imshow
使用任意纵横比

im = ax.imshow(..., aspect='auto')
如果您“只是”想保存矩阵的matshow/imshow渲染,而不使用axis注释,那么scikit视频(skvideo)的最新开发版本也可能与此相关,-如果您安装了avconv。分布中的一个示例显示了由numpy函数构造的动态图像:

下面是我对示例的修改:

# Based on https://github.com/aizvorski/scikit-video/blob/master/skvideo/examples/test_writer.py
from __future__ import print_function

from skvideo.io import VideoWriter
import numpy as np

w, h = 640, 480

checkerboard = np.tile(np.kron(np.array([[0, 1], [1, 0]]), np.ones((30, 30))), (30, 30))
checkerboard = checkerboard[:h, :w]

filename = 'checkerboard.mp4'
wr = VideoWriter(filename, frameSize=(w, h), fps=8)

wr.open()
for frame_num in range(300):
    checkerboard = 1 - checkerboard
    image = np.tile(checkerboard[:, :, np.newaxis] * 255, (1, 1, 3))
    wr.write(image)
    print("frame %d" % (frame_num))

wr.release()
print("done")

我搜索了一整天,最终在创建每张图像时使用了@matehat的解决方案

import matplotlib.pyplot as plt
import matplotlib.animation as animation
要制作不带边框的图形,请执行以下操作:

fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)
使内容充满整个图形

ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
绘制第一帧,假设您的电影存储在“imageStack”中:

movieImage = ax.imshow(imageStack[0], aspect='auto')
然后我编写了一个动画函数:

def animate(i):
    movieImage.set_array(imageStack[i])
    return movieImage

anim = animation.FuncAnimation(fig,animate,frames=len(imageStack),interval=100)
anim.save('myMovie.mp4',fps=20,extra_args=['-vcodec','libx264']
它工作得很好

以下是删除空白解决方案的链接:


我对
bbox\u inches='tight'
的体验非常糟糕,因为抓取的帧的像素大小和写入器的像素大小配置为“不匹配”并获取垃圾电影。如果您想测试这个,请通过rcparam设置
bbox_inches
值。@tcaswell有趣的是,这听起来像是一个bug,应该报告。我无法在这台计算机上测试该版本,因此我试图从源代码中猜出答案。这不是一个bug,只是MP4需要固定的像素帧大小,而mpl使用紧边界框时生成不同大小的图像,两者之间的交互不好。更好地控制这一点(我认为)需要打破mpl在用户和渲染细节之间的一些很好的抽象障碍。它还没有包括在那里。我有点急于更新到git HEAD,因为我需要稳定的绘图。我将等待并尝试下一个版本。@P.R.替代方法是放弃matplotlib动画编写器,自己制作电影。这其实并不难(尤其是在使用Unix发行版时),只需按顺序生成电影图像,并在其上运行类似于
ffmpeg
的操作即可。在这个级别上,您将拥有完全的控制权。使用
子批次\u adjust
仅删除顶部和底部的边距。我在视频的左右两侧仍然有一个空白。而且不知何故,我无法执行
im.set\u cdata(mat)
。我收到错误:
AttributeError:'AxesImage'对象没有属性'set\u cdata'
awesome,这解决了我的问题。没有剩余的页边距,使用
set\u data
确实使整个过程更快!你的补充评论“如果你重新使用ImageAxis对象,你也可以使你的代码更加高效”真的帮助了我。由于此更改程序在动画期间使用的内存较少。我建议您准确指出帮助您和/或回答用户问题的部分,然后参考链接:)
def animate(i):
    movieImage.set_array(imageStack[i])
    return movieImage

anim = animation.FuncAnimation(fig,animate,frames=len(imageStack),interval=100)
anim.save('myMovie.mp4',fps=20,extra_args=['-vcodec','libx264']