matplotlib 绘制 3D Skeleton 的动画

动机

想画人体骨骼的3D动画,网上找了半天都是2D的连续曲线的动画,因此记录一下简单的3D动画。

说明

  • pycharm
  • KinectV2的人体skeleton数据,包含了Joint的xyz坐标
  • 数据来自PKU-MMD

碰到的问题与解决

  • pycharm 没法直接显示FuncAnimation 。开头加入 matplotlib.use('Qt5Agg')即可解决
  • FuncAnimationupdate方法。我并不需要连续的数据,因此每次更新都需要清除原本的数据,但网上搜都是2D的update,因此直接看源码,找到了一种暴力清空的方式

    • ax.plot每次都会产生很多线段,因此使用ax.lines=[]清空axes的线段,
    • ax.scatter每次会产生很多散点,因此使用 ax.collections=[] 清空axes的点

代码

import matplotlib

from matplotlib import pyplot as plt
from Read_data.constant import JOINT
from mpl_toolkits.mplot3d import axes3d
from matplotlib.animation import FuncAnimation
import numpy as np

matplotlib.use('Qt5Agg')

data = list()
for line_i in open("E:\\Cache\\temp\\0002-M.txt"):
    data_line = [float(i) * 1000 for i in line_i.split()]
    data.append(data_line)
SkeletonConnectionMap = [[JOINT.Head, JOINT.Neck],
                         [JOINT.Neck, JOINT.SpineShoulder],
                         [JOINT.SpineShoulder, JOINT.ShoulderLeft],
                         [JOINT.ShoulderLeft, JOINT.ElbowLeft],
                         [JOINT.ElbowLeft, JOINT.WristLeft],
                         [JOINT.WristLeft, JOINT.HandLeft],
                         [JOINT.WristLeft, JOINT.ThumbLeft],
                         [JOINT.HandLeft, JOINT.HandTipLeft],
                         [JOINT.SpineShoulder, JOINT.ShoulderRight],
                         [JOINT.ShoulderRight, JOINT.ElbowRight],
                         [JOINT.ElbowRight, JOINT.WristRight],
                         [JOINT.WristRight, JOINT.HandRight],
                         [JOINT.WristRight, JOINT.ThumbRight],
                         [JOINT.HandRight, JOINT.HandTipRight],
                         [JOINT.SpineShoulder, JOINT.SpineMid],
                         [JOINT.SpineMid, JOINT.SpineBase],
                         [JOINT.SpineBase, JOINT.HipLeft],
                         [JOINT.HipLeft, JOINT.KneeLeft],
                         [JOINT.KneeLeft, JOINT.AnkleLeft],
                         [JOINT.AnkleLeft, JOINT.FootLeft],
                         [JOINT.SpineBase, JOINT.HipRight],
                         [JOINT.HipRight, JOINT.KneeRight],
                         [JOINT.KneeRight, JOINT.AnkleRight],
                         [JOINT.AnkleRight, JOINT.FootRight]]
data = np.array(data, dtype=int)

frames_number = data.shape[0]
print(data.shape)
data = data.reshape([frames_number, -1, 25, 3])  # [frame,bady,joint,xyz]
# print(data)
# print(np.sum(data, axis=0))
# print(np.sum(data, axis=1))

mean = np.mean(data, axis=2)
mean = mean[:, :, np.newaxis, :]
# print(mean)
# print(mean.shape)
data = data - mean
val = np.mean(data, axis=2)
print(val)


def init():
    ax.set_xlabel('x')
    ax.set_ylabel('z')
    ax.set_zlabel('y')
    ax.set_ylim(-600, 600)
    ax.set_xlim(-600, 600)
    ax.set_zlim(-600, 600)


fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# print(type(ax))
init()

print(len(SkeletonConnectionMap))


def update(index):
    ax.lines = []
    # ax.collections = []

    for joint_connection in SkeletonConnectionMap:
        endpoint1 = joint_connection[0]
        endpoint2 = joint_connection[1]
        endpoint_x = [data[index, 0, endpoint1, 0], data[index, 0, endpoint2, 0]]
        endpoint_y = [data[index, 0, endpoint1, 1], data[index, 0, endpoint2, 1]]
        endpoint_z = [data[index, 0, endpoint1, 2], data[index, 0, endpoint2, 2]]
        ax.plot(endpoint_x, endpoint_z, endpoint_y, c='r')

    # ax.scatter(data[index, 0, :, 0], data[index, 0, :, 2], data[index, 0, :, 1], c='b', marker='^')


print(data.shape[0])
ani = FuncAnimation(fig, update, frames=frames_number, interval=40, repeat=False)
plt.show()

效果

效果图只是截取了一小段

改进

评论区的观众,有更好做法欢迎在下面留言,互相交流,互相进步嘛

你可能感兴趣的:(matplotlib)