In [1]:
import matplotlib.pyplot as plt
import user_data_loader as udl
import pandas as pd
In [2]:
# draw a vector
# retrieved from: http://stackoverflow.com/a/11156353/630598
from matplotlib.patches import FancyArrowPatch
from mpl_toolkits.mplot3d import proj3d
class Arrow3D(FancyArrowPatch):
def __init__(self, xs, ys, zs, *args, **kwargs):
FancyArrowPatch.__init__(self, (0,0), (0,0), *args, **kwargs)
self._verts3d = xs, ys, zs
def draw(self, renderer):
xs3d, ys3d, zs3d = self._verts3d
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
self.set_positions((xs[0],ys[0]),(xs[1],ys[1]))
FancyArrowPatch.draw(self, renderer)
In [3]:
# Specifying all the links between joints:
def get_links(data):
''' Returns a dict with all the links of the skeleton.
Arguments:
data: a pd.DataFrame with columns with joint names'''
return { 'head_neck': list(zip(data.T['head'].values, data.T['neck'].values)),
'neck_lshoulder': zip(data.T['neck'].values, data.T['left_shoulder'].values),
'lshoulder_lelbow': zip(data.T['left_shoulder'].values, data.T['left_elbow'].values),
'lelbow_lhand': zip(data.T['left_elbow'].values, data.T['left_hand'].values),
'neck_rshoulder': zip(data.T['neck'].values, data.T['right_shoulder'].values),
'rshoulder_relbow': zip(data.T['right_shoulder'].values, data.T['right_elbow'].values),
'relbow_rhand': zip(data.T['right_elbow'].values, data.T['right_hand'].values),
'lshoulder_torso': zip(data.T['left_shoulder'].values, data.T['torso'].values),
'rshoulder_torso': zip(data.T['right_shoulder'].values, data.T['torso'].values),
'torso_lhip': zip(data.T['torso'].values, data.T['left_hip'].values),
'lhip_rhip': zip(data.T['left_hip'].values, data.T['right_hip'].values),
'lhip_lknee': zip(data.T['left_hip'].values, data.T['left_knee'].values),
'lknee_lfoot': zip(data.T['left_knee'].values, data.T['left_foot'].values),
'torso_rhip': zip(data.T['torso'].values, data.T['right_hip'].values),
'rhip_rknee': zip(data.T['right_hip'].values, data.T['right_knee'].values),
'rknee_rfoot': zip(data.T['right_knee'].values, data.T['right_foot'].values)
}
In [4]:
def plot_skeleton(axis, datapoints, links=False, **kwargs):
''' Plots a skeleton in 3D'''
axis.scatter(datapoints.x, datapoints.y, datapoints.z, **kwargs)
if links:
joint_links = get_links(datapoints)
for jl in joint_links: # adding joint links to the plot:
arrow = Arrow3D(joint_links[jl][0], joint_links[jl][1], joint_links[jl][2], lw=1, arrowstyle="-", **kwargs)
axis.add_artist(arrow)
In [4]:
In [5]:
def to_xyz(series, colors=None):
''' converts series with index = head_pos_x, head_pos_y, etc...
to a dataframe with index=joints and columns = x, y z '''
def_colors = {'STAND_POINTING_RIGHT':'red', 'STAND_POINTING_FORWARD':'green', 'STAND_POINTING_LEFT':'blue'}
c = colors if colors else def_colors
xyz = pd.DataFrame(index=udl.joints, columns=['x','y','z', 'color'])
x = series[udl.ind_pos_x]
y = series[udl.ind_pos_y]
z = series[udl.ind_pos_z]
for d in (x,y,z): # renaming index so it is the same as xyz
d.index = udl.joints
xyz.x, xyz.y, xyz.z = x, y, z
xyz.color = c[series[-1]]
return xyz
def irow_to_xyz(irow, **kwargs):
''' Helper function to pass the pd.iterrows tuple to the to_xyz function '''
return to_xyz(irow[1], **kwargs)
def df_to_xyz(df):
''' converts a a pd.Dataframe with user data to a '3D-plottable' dataframe '''
return pd.concat(map(irow_to_xyz, df.iterrows()))
In [6]:
user_file = '../data/exp03-user13.arff'
#user_file = 'data-torso-relative/exp03-user13.arff'
#user_file = 'data-torso-relative/exp03-user20.arff'
e03u01 = udl.load_user_file(user_file)
In [7]:
e03u01.head()
Out[7]:
Plotting an unnormalized skeleton
In [8]:
%pylab
Making the DataFrame plottable
In [9]:
e03u01.columns = udl.index
In [10]:
xyz_03u01 = df_to_xyz(e03u01)
Grouping the DataFrame points by color so later is easier to plot them
In [11]:
clouds = xyz_03u01.groupby('color')
Separating by pose and calculating the pose means so we can plot the skeleton links
In [12]:
means = e03u01.groupby('pose').mean()
means.insert(len(means.columns), 'pose', means.index )
# Prepare means to be printed:
m_groups = [to_xyz(means.ix[i]) for i,ind in enumerate(means.index)]
Plotting the skeleton cloud and its means
In [13]:
# Plot skeleton joints and links
ax = plt.axes(projection='3d')
for c, values in clouds:
ax.scatter(values.x, values.y, values.z, color=c, alpha=0.2, marker='o')
for m in m_groups:
col = m['color'][0] # Just need the 1st one
plot_skeleton(ax, m, links=True, color=col)
ax.view_init(-90,90)
#plt.savefig('/Users/almudenasanz/Downloads/skeleton.pdf', format='pdf')
In [14]:
udl = reload(udl)
In [15]:
user_file = '../data/exp03-user13.arff'
#user_file = 'data-torso-relative/exp03-user13.arff'
#user_file = 'data-torso-relative/exp03-user20.arff'
e03u01 = udl.load_user_file(user_file)
In [16]:
e03u01.head()
Out[16]:
In [21]:
e03u01.columns = udl.make_multiindex(udl.joints, udl.attribs)
In [22]:
e03u01.head()
Out[22]:
In [25]:
# Removing foots
#e03u01_norm.drop(['left_foot', 'right_foot'], axis=1, level='joint')
Normalize data. Note that we keep the original data of the torso in orig_torso
In [26]:
orig_torso, df_normalized = udl.normalize_joints(e03u01, 'torso')
In [27]:
df_normalized.head()
Out[27]:
Update e03u01 with the normalized data
In [28]:
e03u01.update(df_normalized)
In [29]:
e03u01.head()
Out[29]:
Note that torso values are not set to 0. If we want to make torso the origin of coordinates, we need to substract torso from itself.
In [30]:
e03u01['torso'].head()
Out[30]:
In [31]:
## Set torso values to 0 (the origing of coordinates)
e03u01.torso = e03u01.torso - e03u01.torso
e03u01.torso.head()
Out[31]:
Now, let's plot the skeletons
In [32]:
e03u01.columns = udl.index
xyz_03u01 = df_to_xyz(e03u01)
clouds = xyz_03u01.groupby('color')
means = e03u01.groupby('pose').mean()
means.insert(len(means.columns), 'pose', means.index )
# Prepare means to be printed:
m_groups = [to_xyz(means.ix[i]) for i,ind in enumerate(means.index)]
# Plot skeleton joints and links
ax = plt.axes(projection='3d')
for c, values in clouds:
ax.scatter(values.x, values.y, values.z, color=c, alpha=0.2, marker='o')
for m in m_groups:
col = m['color'][0] # Just need the 1st one
plot_skeleton(ax, m, links=True, color=col)
ax.view_init(-90,90)
#plt.savefig('/Users/almudenasanz/Downloads/skeleton.pdf', format='pdf')
In [73]:
In [ ]: