目录
1--NTU_RGB+D数据集
1-1--NTU_RGB+D数据集下载
1-2--NTU_RGB+D数据集介绍
2--骨架数据可视化代码
3--参考
NTU_RGB+D数据集论文 -- CVPR2016
NTU_RGB+D数据集官方下载地址
Skeleton_Data_Only ->(BaiDuYun)-> Code:75gs
NTU_RGB+D动作识别数据集由56880个动作样本组成,涵盖每个样本的RGB视频、深度图序列、3D骨架数据和红外视频等。数据集由3个Microsoft Kinect v.2相机同时捕获,RGB视频的分辨率为1920×1080,深度图和红外视频均为512×424,3D骨架数据包含每帧25个身体关节的三维位置,数据集大小如下图所示:
这里将着重介绍3D骨架数据,3D骨架数据包含每帧25个身体关节的三维坐标,25个身体关节的编号如下图所示:
分析3D skeleton数据集:
--文件命名格式:(示例:S010C001P019R001A010.skeleton)
S:设置号,共有17组设置;
C:相机ID,共有3架相机;
P:人物ID,共有40个人;
R:同一个动作的表演次数;
A:动作类别,共有60个。
--以 'S010C001P019R001A010.skeleton' 文件为例,具体分析其数据组成:
分析上图:
第一行:帧数,数字71表示该skeleton文件共有71帧;
第二行:body数,数字1表示该视频帧中出现了一个body;
第三行:共有10个数字,依次表示:'bodyID', 'clipedEdges', 'handLeftConfidence',
'handLeftState', 'handRightConfidence', 'handRightState', 'isResticted', 'leanX', 'leanY', 'trackingState';
第四行:关节数,数字25表示共有25个关节;
5-29行:25个关节的数据,共有12个数字,依次表示:'x', 'y', 'z', 'depthX', 'depthY', 'colorX', 'colorY', 'orientationW', 'orientationX', 'orientationY', 'orientationZ', 'trackingState';
之后便是第2帧的数据,遵循上述规则。
######################################
######################################
代码用到的样本数据下载:
'S010C001P019R001A010.skeleton'下载地址 -> Code:97mm
## 导入第三方库
import os
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import sys
## 读取关节数据
def read_skeleton(file):
with open(file, 'r') as f: # 打开file(.skeleton)文件
skeleton_sequence = {} # 初始化skeleton_sequence
skeleton_sequence['numFrame'] = int(f.readline()) # 读取.skeleton文件第一行,即帧数
skeleton_sequence['frameInfo'] = []
for t in range(skeleton_sequence['numFrame']): # 遍历每一帧
frame_info = {} # 初始化frame_info
frame_info['numBody'] = int(f.readline()) # 再次调用.readline函数,读取.skeleton文件的下一行,即body数
frame_info['bodyInfo'] = []
for m in range(frame_info['numBody']): # 遍历每一个body
body_info = {} # 初始化body_info
body_info_key = [ # key: 数字表示的意义,即对应的key
'bodyID', 'clipedEdges', 'handLeftConfidence',
'handLeftState', 'handRightConfidence', 'handRightState',
'isResticted', 'leanX', 'leanY', 'trackingState'
]
body_info = {
k: float(v) # 字典类型; key: value(float类型)
for k, v in zip(body_info_key, f.readline().split()) # 读取下一行数据,根据key打包数据,遍历返回key, value
}
body_info['numJoint'] = int(f.readline()) # 读取下一行数据,即关节数
body_info['jointInfo'] = []
for v in range(body_info['numJoint']): # 遍历25个关节的数据
joint_info_key = [ # Key: 数字表示的意义,即对应的key
'x', 'y', 'z', 'depthX', 'depthY', 'colorX', 'colorY',
'orientationW', 'orientationX', 'orientationY',
'orientationZ', 'trackingState'
]
joint_info = {
k: float(v) # 字典类型; key: value(float类型)
for k, v in zip(joint_info_key, f.readline().split()) # 读取下一行数据,根据key打包数据,遍历返回key, value
}
body_info['jointInfo'].append(joint_info) # 保存关节数据
frame_info['bodyInfo'].append(body_info) # 保存body数据
skeleton_sequence['frameInfo'].append(frame_info) # 保存当前帧的数据
return skeleton_sequence
## 读取关节的x,y,z三个坐标
def read_xyz(file, max_body=2, num_joint=25):
seq_info = read_skeleton(file) # 调用read_skeleton()函数读取.skeleton文件的数据
data = np.zeros((3, seq_info['numFrame'], num_joint, max_body)) # 初始化数据; 3 × 帧数 × 25 × max_body
for n, f in enumerate(seq_info['frameInfo']): # 遍历每一帧的数据
for m, b in enumerate(f['bodyInfo']): # 遍历每一个body的数据
for j, v in enumerate(b['jointInfo']): # 遍历每一个关节的数据
if m < max_body and j < num_joint:
data[:, n, j, m] = [v['x'], v['y'], v['z']] # 保存 x,y,z三个坐标的数据
else:
pass
return data
## 2D展示
def Print2D(num_frame, point, arms, rightHand, leftHand, legs, body):
# 求坐标最大值
xmax = np.max(point[0, :, :, :])
xmin = np.min(point[0, :, :, :])
ymax = np.max(point[1, :, :, :])
ymin = np.min(point[1, :, :, :])
zmax = np.max(point[2, :, :, :])
zmin = np.min(point[2, :, :, :])
n = 0 # 从第n帧开始展示
m = num_frame # 到第m帧结束,n 11 <-> 10 ...
rightHand = [11, 24] # 11 <-> 24
leftHand = [7, 22] # 7 <-> 22
legs = [19, 18, 17, 16, 0, 12, 13, 14, 15] # 19 <-> 18 <-> 17 ...
body = [3, 2, 20, 1, 0] # 3 <-> 2 <-> 20 ...
Print2D(num_frame, point, arms, rightHand, leftHand, legs, body) # 2D可视化
#Print3D(num_frame, point, arms, rightHand, leftHand, legs, body) # 3D可视化
main()
分析:上述代码有2D展示和3D展示两个版本,3D展示效果不是很理想,样本文件是拍手(clapping)的动作。
另附一个握手(handshaking)的动作展示:(文件名:S001C001P001R001A058.skeleton)
######################################
######################################
参考链接1
参考链接2
骨架可视化的时候,多出来了一个点,那个不是原点来的,是另外一个body的骨架点。由于有些动作只有一个body参与,所以另外一个body全为0,画散点图的时候将其画了出来。修改也很简单,代码如下:
原代码:
plt.scatter(point[0, i, :, :], point[1, i, :, :], c='red', s=40.0)
修改为:
plt.scatter(point[0, i, :, 0], point[1, i, :, 0], c='red', s=40.0)
# 相当于对于一个body的图像,只画第一个body的散点图