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.
ani.save(...)
line is the bottleneck, correct?