matplotlib 繪製 3D Skeleton 的動畫

動機

想畫人體骨骼的3D動畫,網上找了半天都是2D的連續曲線的動畫,所以記錄一下簡單的3D動畫。html

說明

  • pycharm
  • KinectV2的人體skeleton數據,包含了Joint的xyz座標
  • 數據來自PKU-MMD

碰到的問題與解決

  • pycharm 無法直接顯示FuncAnimation 。開頭加入 matplotlib.use('Qt5Agg')便可解決
  • FuncAnimationupdate方法。每次只顯示最新的動做,不須要保留過往的記錄,所以每次更新都須要清除本來的數據,但網上搜都是2D的update,所以直接看源碼,找到了一種暴力清空的方式app

    • 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()

效果

效果圖只是截取了一小段
圖片描述動畫

改進

評論區的觀衆,有更好作法歡迎在下面留言,互相交流,互相進步嘛😁spa

相關文章
相關標籤/搜索