动机
想画人体骨骼的3D动画,网上找了半天都是2D的连续曲线的动画,因此记录一下简单的3D动画。
说明
- pycharm
- KinectV2的人体skeleton数据,包含了Joint的xyz坐标
- 数据来自PKU-MMD
碰到的问题与解决
- pycharm 没法直接显示
FuncAnimation
。开头加入matplotlib.use('Qt5Agg')
即可解决 -
FuncAnimation
的update
方法。我并不需要连续的数据,因此每次更新都需要清除原本的数据,但网上搜都是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()
效果
效果图只是截取了一小段
改进
评论区的观众,有更好做法欢迎在下面留言,互相交流,互相进步嘛