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

2 Answers2

1

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()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • 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. – Vaibhav Ahire Jan 27 '19 at 10:15
  • 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. – Star Man Aug 28 '21 at 01:28
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.

Ente
  • 2,301
  • 1
  • 16
  • 34
  • 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. – Commander Tvis Sep 17 '21 at 13:59