Search code examples
pythonanimationvideomatplotlib

Matplotlib.animation: how to remove white margin


I try to generate a movie using the matplotlib movie writer. If I do that, I always get a white margin around the video. Has anyone an idea how to remove that margin?

Adjusted example from http://matplotlib.org/examples/animation/moviewriter.html

# This example uses a MovieWriter directly to grab individual frames and
# write them to a file. This avoids any event loop integration, but has
# the advantage of working with even the Agg backend. This is not recommended
# for use in an interactive setting.
# -*- noplot -*-

import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import matplotlib.animation as manimation

FFMpegWriter = manimation.writers['ffmpeg']
metadata = dict(title='Movie Test', artist='Matplotlib',
        comment='Movie support!')
writer = FFMpegWriter(fps=15, metadata=metadata, extra_args=['-vcodec', 'libx264'])

fig = plt.figure()
ax = plt.subplot(111)
plt.axis('off')
fig.subplots_adjust(left=None, bottom=None, right=None, wspace=None, hspace=None)
ax.set_frame_on(False)
ax.set_xticks([])
ax.set_yticks([])
plt.axis('off')

with writer.saving(fig, "writer_test.mp4", 100):
    for i in range(100):
        mat = np.random.random((100,100))
        ax.imshow(mat,interpolation='nearest')
        writer.grab_frame()

Solution

  • Passing None as an arguement to subplots_adjust does not do what you think it does (doc). It means 'use the deault value'. To do what you want use the following instead:

    fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=None, hspace=None)
    

    You can also make your code much more efficent if you re-use your ImageAxes object

    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()
    

    By default imshow fixes the aspect ratio to be equal, that is so your pixels are square. You either need to re-size your figure to be the same aspect ratio as your images:

    fig.set_size_inches(w, h, forward=True)
    

    or tell imshow to use an arbitrary aspect ratio

    im = ax.imshow(..., aspect='auto')