1. 说明
本文是对动作识别、动作预测常见数据集NTU RGB-D 60的3D可视化,运行中可以用鼠标拖动可以查看不同视角,可以保存成GIF图,可以将Gif解析成单帧PNG图片进行进一步处理,可以将所有帧图片凭借成一个整体,实现论文中的美观度。
当然,这个代码适用于所有的骨架数据集,只需要做出一点点修改即可
2. 实现效果
实现的效果如图:
旋转视角看看:
解析成单帧图片:
拼接成一个整体图:
基本上实现了一些论文中的可视化效果
3. NTU RGB-D 60数据集的3D可视化代码
话不多说,直接上代码:
编写不易,如果对你有帮助的话可以关注、点赞、收藏支持一波,有问题欢迎评论,一定会回复你的
有的人显示不出来可能是版本问题,贴一下我运行的版本:
- python: 3.8.12
- pillow(即PIL): 8.4.0
- matplotlib:3.4.3
- numpy:·1.21.3
from PIL import Image
import os
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
matplotlib.use('TkAgg')
def create_pose(ax,plots,vals, update=False):
connect = [
(1,2),(2,21),(21,3),(3,4), (9,21),
(9,10),(10,11),(11,12),(12,24),(12,25),
(1,17), (17,18), (18,19), (19,20), (5, 21),
(5,6), (6,7), (7,8), (8,22),(8,23),
(1,13), (13,14),(14,15),(15,16)
]
connect = [(i - 1, j - 1) for (i, j) in connect]
LR =[
False, False, False, False, True,
True, True, True, True, True,
True, True, True, True, False,
False, False, False, False, False,
False,False,False,False
] #这里可以设置哪些骨架是左边,哪些是右边,有时候不准可以全设置为True
# Start and endpoints of our representation
I = np.array([touple[0] for touple in connect])
J = np.array([touple[1] for touple in connect])
lcolor = "#9b59b6" #设置骨架颜色,左右颜色
rcolor = "#2ecc71"
for i in np.arange( len(I) ):
x = np.array( [vals[I[i], 0], vals[J[i], 0]] )
z = np.array( [vals[I[i], 1], vals[J[i], 1]] )
y = np.array( [vals[I[i], 2], vals[J[i], 2]] )
if not update:
plots.append(ax.plot(x, y, z, lw=2,linestyle='-' ,c=lcolor if LR[i] else rcolor))
elif update:
plots[i][0].set_xdata(x)
plots[i][0].set_ydata(y)
plots[i][0].set_3d_properties(z)
plots[i][0].set_color(lcolor if LR[i] else rcolor)
return plots
# ax.legend(loc='lower left')
def update_gt(num, data_gt, plots_gt, fig, ax):
gt_vals = data_gt[num]
plots_gt = create_pose(ax, plots_gt, gt_vals, update=True)
r = 0.75
xroot, zroot, yroot = gt_vals[0, 0], gt_vals[0, 1], gt_vals[0, 2]
ax.set_xlim3d([-r + xroot, r + xroot])
ax.set_ylim3d([-r + yroot, r + yroot])
ax.set_zlim3d([-r + zroot, r + zroot])
return plots_gt
def visualize(input ,vision_num, save_path):
# input dim : t, v, c
data_gt = input
print(data_gt.shape)
fig = plt.figure()
ax = Axes3D(fig)
ax.view_init(elev=20, azim=-40) #视角转换
vals = np.zeros((25, 3)) # or joints_to_consider
gt_plots=[]
gt_plots=create_pose(ax,gt_plots,vals,update=False)
#以下是关于坐标轴的设置,如果需要可以打开
# ax.set_xlabel("x")
# ax.set_ylabel("y")
# ax.set_zlabel("z")
# ax.legend(loc='lower left')
# ax.set_xlim3d([-1, 1.5])
# ax.set_xlabel('X')
# ax.set_ylim3d([-1, 1.5])
# ax.set_ylabel('Y')
# ax.set_zlim3d([0.0, 1.5])
# ax.set_zlabel('Z')
# ax.set_title('设置标题')
line_anim_gt = animation.FuncAnimation(fig, update_gt,vision_num, fargs=(data_gt,gt_plots,fig,ax),interval=70, blit=False)
#下面是关闭坐标轴和网格,如果需要可以取消注释,即可去掉坐标轴和网格
# ax.axis('off') # 关闭坐标轴
# ax.grid(b=None) #关闭网格
plt.show()
gt_name = 'test.gif' #保存名称
line_anim_gt.save(save_path + '/' + gt_name,writer='pillow')
def get_data(file_name):
max_V = 25 #节点数
max_M = 2 #骨架数量
with open(file_name, 'r') as fr:
frame_num = int(fr.readline())
point = np.zeros((3, frame_num, 25, 2))
for frame in range(frame_num):
person_num = int(fr.readline())
for person in range(person_num):
fr.readline()
joint_num = int(fr.readline())
for joint in range(joint_num):
v = fr.readline().split(' ')
if joint < max_V and person < max_M:
point[0,frame,joint,person] = float(v[0])#一个关节的一个坐标
point[1,frame,joint,person] = float(v[1])
point[2,frame,joint,person] = float(v[2])
point = point[:,:,:,0] #只取一个人
# point = np.expand_dims(point, -1)
return point
def get_gif_imgs(gif_path, save_path):
"""
提取动图中的每一帧图片,并保存到文件夹中
"""
new_path = save_path
gif = Image.open(gif_path)
try:
gif.save(f"{new_path}/{gif.tell()}"+"_frame.png")
while True:
gif.seek(gif.tell() + 1)
gif.save(f'{new_path}/{gif.tell()}'+"_frame.png")
except Exception as e:
print("处理结束")
if __name__ == '__main__':
file_name = 'S018C001P008R002A062.skeleton' #设置文件名
input = get_data(file_name).transpose(1,2,0)
vision_num = 70 #要可视化多少帧
print('视频帧数共{}帧,需要可视化{}帧'.format(input.shape[0], vision_num))
if vision_num > input.shape[0]:
print('要可视化的帧数大于视频总帧数!')
save_path = './result'
if not os.path.exists(save_path):
os.makedirs(save_path)
visualize(input, vision_num, save_path)
#解析gif
gif_path = save_path + '/' + 'test.gif'
get_gif_imgs(gif_path, save_path) #将gif解析成每一帧图片
编写不易,转载请注明出处
4. NTU RGB-D 60的 2D简单可视化
请查看我的上一篇博客:如何用Matplotlib优雅地实现NTU-RGB D骨架可视化文章来源:https://www.toymoban.com/news/detail-567304.html
5. 联系方式
有问题欢迎邮件联系:
1759412770@qq,com文章来源地址https://www.toymoban.com/news/detail-567304.html
到了这里,关于NTU RGB-D 60 骨架数据集3D可视化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!