matplotlib animation save is not obeying blit=True but it seems to work just fine in plt.show()
Asked Answered
I

2

2

I'm quite new to Python and am trying to animate text using matplotlib. used several online examples to arrive at the following code:

import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()

plt.xlabel('Distance')
plt.ylabel('Height')
plt.title('Object Trajectory \n')

plt.legend(loc="upper right", markerscale=4, fontsize=10)
plt.grid()

text=ax.text(3,1,'Moving Text', ha="left", va="bottom",clip_on=True,rotation=90,fontsize=15)    
text2=ax.text(0,1,'Moving Text', ha="left", va="bottom",clip_on=True,fontsize=15)    

def init():
    ax.set_xlim(0,10)
    ax.set_ylim(0,10)
    return text,text2

def update(frame):        
    #Moving a text
    text=ax.text(3,1+(int(frame))/30,'Moving Text', ha="left", va="bottom",clip_on=True,rotation=90,fontsize=15)    
    text2=ax.text(0+(int(frame))/30,1,'Moving Text', ha="left", va="bottom",clip_on=True,fontsize=15)    

    return text,text2

anim = animation.FuncAnimation(fig, update, init_func=init, frames=120, interval=10, blit=True)

anim.save('try_animation.mp4',dpi=160,fps=30, writer="ffmpeg")

plt.show()

So when I run it in console, I can see the texts moving nicely. But when I save it to a MP4 file the text doesn't seem to blit. Please Help.

Thank You

This is a screenshot of saved video file

Industrious answered 27/1, 2019 at 7:55 Comment(0)
O
2

What you observe is the expected behaviour. Blitting is a technique used to refresh only part of a graphics output. In the matplotlib case, instead of drawing the complete figure, only part of it, namely the region inside the axes, is refreshed and only those artists returned by the animating function are drawn. This allows to have a faster animation speed on screen.

However, when an animation is saved, each frame needs to be drawn in completeness.

So in order to have a text moving, one should rather update a single text's position, instead of creating new texts over and over again. This can be done with

text.set_position((x,y))

The example would hence look like

import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()

plt.xlabel('Distance')
plt.ylabel('Height')
plt.title('Object Trajectory \n')
plt.grid()

text=ax.text(3,1,'Moving Text', ha="left", va="bottom",clip_on=True,rotation=90,fontsize=15)    
text2=ax.text(0,1,'Moving Text', ha="left", va="bottom",clip_on=True,fontsize=15)    

def init():
    ax.set_xlim(0,10)
    ax.set_ylim(0,10)
    return text,text2

def update(frame):        
    #Moving a text
    text.set_position((3, 1+(int(frame))/30))
    text2.set_position((0+(int(frame))/30,1))
    return text,text2

anim = animation.FuncAnimation(fig, update, init_func=init, frames=120, interval=10, blit=True)

anim.save('try_animation.mp4',dpi=160,fps=30, writer="ffmpeg")

plt.show()
Ovular answered 27/1, 2019 at 9:55 Comment(2)
Thanks a lot. I had a bigger code in which I was also trying to move polygons. But to shorten question details, I deleted that part. I'll try implementing your corrections for the original code too.Industrious
How would this be done for a regular point (or coordinate) on a matplotlib plot? ax.plot(x,y) doesn't seem to blit when saved as a gif file or etc.Cortez
S
0

For a line2D object you can use the set_data( ) method for a moving point:

line , = ax.plot( x[0], y[0] , "ro")

...

def animar(i):
   line.set_data( x[i] , y[i], "ro" )
   return line

In the matplotlib.animation examples there is a little script with such an approach.

Santos answered 17/9, 2021 at 12:6 Comment(1)
Welcome to StackOverflow! It is unclear how exactly are you trying to invoke animation save, and where the blit=True argument occurs. Please edit your question so other users could answer it.Hibbler

© 2022 - 2024 — McMap. All rights reserved.