1

I have a large dataset containing x, y, z coordinates of limbs from multiple people over several frames. I am using Python with Matplotlib to visualize this data as an animation, where each frame shows the positions of the limbs as stick figures representing the movement of people.

The current approach involves reading the data from multiple CSV files (each file is one frame with all the x,y,z coordinates of 25 limbs of 25 persons (soccer match), I defined the connections of the limbs and plotted the connection lines, so the individual stick figures appear. I used the FuncAnimation to update the plot for each frame. The animation creation process works well, but saving the animation as an mp4 video takes a significant amount of time, especially for a large number of frames.

Here is a version of the code I am using:

#read data and create a df with all the data from the different frame files
#...

# Initialize the plot
fig = plt.figure(figsize=(10, 30), dpi = 100)
ax = fig.add_subplot(projection='3d')

# Set axis limits
ax.set_xlim(-50, 50)
ax.set_ylim(-35, 35)
ax.set_zlim(0, 2)
ax.set_aspect('equal')


# Define the connections between joints
connections = [
    ('neck', 'r_shoulder'),
    ('r_shoulder', 'r_elbow'),
    ('r_elbow', 'r_wrist'),
    ('neck', 'l_shoulder'),
    ('l_shoulder', 'l_elbow'),
    ('l_elbow', 'l_wrist'),
    ('neck', 'pelvis'),
    ('pelvis', 'r_hip'),
    ...
]

 # Create a color map for unique colors for each team
team_ids = frame_data['team_id'].unique()
team_colors = {
    "Home": 'red',  
    "Away": 'blue',  
    "Referees": 'green'  
}

# Create a list of unique frame numbers
unique_frames = frame_data['frame_number'].unique()


ball_row = 0


ani = FuncAnimation(fig, update_plot, frames=unique_frames, interval=50)


def update_plot(frame):
    ax.clear()

     # Filter data for the current frame
    frame_data_for_frame = frame_data[frame_data['frame_number'] == frame]
    
    # Plot the connections between joints
    for _, row in frame_data_for_frame.iterrows():
        team_id = row['team_id']
        # Get the color for the current player based on the team_id
        color = team_colors.get(team_id, 'black')  

        for connection in connections:
            start_joint = connection[0]
            end_joint = connection[1]
            start_x = row[start_joint+'_x']
            start_y = row[start_joint+'_y']
            start_z = row[start_joint+'_z']
            end_x = row[end_joint+'_x']
            end_y = row[end_joint+'_y']
            end_z = row[end_joint+'_z']
            ax.plot([start_x, end_x], [start_y, end_y], [start_z, end_z], marker='.', markersize=0.5, color=color, linewidth=0.5)


ani.save('basic_animation.mp4', writer="ffmpeg", fps=50)

Is it possible to improve the performance of the animation creation and saving process? Are there any optimizations or configurations that can significantly reduce the time taken to save the animation as an mp4 video? I have already tried using different encoders, bitrates, and FPS but it's not getting faster.

4
  • Just to confirm, the ani.save(...) line is the bottleneck, correct?
    – jared
    Commented Aug 3, 2023 at 14:39
  • @jared exactly. FuncAnimation is quite fast, the ani.save(...) takes for a 30 seconds animation at least 15 minutes.
    – Jmagb
    Commented Aug 24, 2023 at 16:37
  • Matplotlib animation saving can be pretty slow. You might want to consider saving individual frames and then using something like PIL or glob to convert a folder of PNGs to an animation.
    – jared
    Commented Aug 24, 2023 at 18:01
  • Creating the video is now very fast. At 50 frames per second, however, an enormous number of pngs are created, which also takes quite some time and requires a lot of memory. Seems like there isn't a fast way to animate this data.
    – Jmagb
    Commented Aug 28, 2023 at 8:39

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.