KINECAL 1.0.2
(8,907 bytes)
# -*- coding: utf-8 -*-
"""
Created on Wed March 2 13:44:00 2022
@author: seanmb
This file will show you some of the basic uses of KINECAL
It uses the sway_utils library to calculate the metrics.
"""
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from matplotlib import cm
import numpy as np
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
import os
import sys
sys.path.append(os.path.abspath('..')) #if this is not working, update this path with the locatiojn of your sway_utils folder
from sway_utils.recordings import KinectRecording
import sway_utils.metrics as sm
start_frame = 200
end_frame = 500
HAs = [25, 504, 505] #Healthy Adults
CaRs = [201, 309, 311] #Clinically at Risk
#%%
"""
view depth files
The depth files are stored as ushort values in binary format.
Below, is a code sippit to allow you to open individual files.
"""
file_path = os.path.abspath('../505/505_Quiet-Standing-Eyes-Open/depth/DepthUshort63638319336726.bin')
depth_image = np.fromfile(file_path, dtype='ushort')
depth_image = depth_image.reshape([424, 512])
"""
It is can be useful to use different colour maps to view the depth informaiton
"""
plt.imshow(depth_image, cmap='binary')
plt.show()
plt.imshow(depth_image, cmap='jet')
plt.show()
plt.imshow(depth_image, cmap='prism')
plt.show()
plt.imshow(depth_image, cmap='bone')
plt.show()
#%%
"""
Save in depth files as images
If you are saving the depth images scaling the images to 0-255 and converting to unit8 is a advisable
Note it this is a destrucive process and you should work with the raw depth data in your models
"""
import imageio
depth_image_for_saving = (depth_image-np.min(depth_image))/(np.max(depth_image)-np.min(depth_image))*255
depth_image_for_saving = depth_image_for_saving.astype('uint8')
imageio.imwrite('depth_image_for_saving.jpeg', depth_image_for_saving)
# %%
def centre(data):
"""
This method is uesed to centre the CoM pathes by subtrcting the
mean value from each value in the CoM path
"""
data_mean = np.mean(data)
centred_data = np.subtract(data, data_mean)
return centred_data
#%%
"""
This section uses the sway_utils library to produce a stabilogram for each of the participant records.
Three healthy adults and three Clinically-at-risk participants are used to provide a comparison.
The records are processed using the recording object from the sway_utils library.
NOTE: The first time the files are processed, cache files for joint positions
will be created (.csv and .npy). Subsequent runs will use the cache, making analysis much quicker.
In addition, the csv file is a convenient format for 3rd party analysis.
The data are filtered using a butterworth filter and is saved into a [3, 26, 599] (axis, joint, frame) array called stacked_filtered_XYZ_values
The raw values are also cached and stored in an array called stacked_raw_XYZ_values.
CoM positions are estimated using the Euclidean mean of the HIP_LEFT HIP_RIGHT SPINE_MID.
the mean position of HIP_LEFTx HIP_RIGHTx SPINE_MIDx represents the ML-axis
the mean position of HIP_LEFTz HIP_RIGHTz, SPINE_MIDz represents the AP-axis
The CoM values can be converted to stabilograms, using the confidence_ellips method of the sway_utils library,
and displayed using Matplotlib
NOTE: the data are centred, and a standardised x and y scale is used to make the comparison easier.
Quiet standing, eyes open, is used in this comparison.
"""
start_frame = 200
end_frame = start_frame + (30*10)
for part_id in HAs+CaRs:
str_part_id = str(part_id)
fig = plt.figure(figsize=(6,6))
ax = fig.add_subplot(111)
ax.set_xlim([-5, 5])
ax.set_ylim([-5, 5])
skel_root_path = os.path.abspath('../' + str_part_id + '/' + str_part_id + '_Quiet-Standing-Eyes-Open/skel')
recording = KinectRecording(skel_root_path, "", 'Quiet-Standing-Eyes-Open', str_part_id)
#recording.calculate_walked_skel_angles()
#ML_path = recording.stacked_filtered_XYZ_values[0, 25][start_frame:end_frame]*100
#AP_path = recording.stacked_filtered_XYZ_values[2, 25][start_frame:end_frame]*100
ML_path = centre(recording.stacked_filtered_XYZ_values[0, 25][start_frame:end_frame]*100) # the midle 10 seconds are retreived and converted to cm
AP_path = centre(recording.stacked_filtered_XYZ_values[2, 25][start_frame:end_frame]*100)
#ML_path = centre(recording.stacked_raw_XYZ_values[0, 25][start_frame:end_frame])*100 # the midle 10 seconds are retreived and converted to cm
#AP_path = centre(recording.stacked_raw_XYZ_values[2, 25][start_frame:end_frame])*100
elp, width, height, AREA_CE, angle = sm.confidence_ellipse(ML_path,
AP_path,
ax,
n_std=1.96,
edgecolor='red')
AREA_CE = round(AREA_CE, 2)
ax.scatter(ML_path, AP_path, s=1)
#AREA_CE = round((elp.height/2) * (elp.width/2) * np.pi, 2)
ax.set_title('Quiet-Standing-Eyes-Open ' + str_part_id + '\n CoM 95% CE' +
'\n' + str(round(width, 2)) + 'cm' +
' x ' +
str(round(height, 2)) + 'cm' +
' Area:' + str(AREA_CE) + '$cm^2$')
ax.set_aspect('equal')
plt.xlabel('ML (cm)')
plt.ylabel('AP (cm)')
plt.show()
#%%
"""
Read in Skeleton files using the recording object
Note if this is the first time you are reading the files cache files for joint positions
will be created (.csv and .npy). Subsiquent runns with use the cashe.
These values are filterd using a butterworth filter and is saved into a [3, 26, 599] (axis, joint, frame) array called stacked_filtered_XYZ_values
The CoM value is used here to create a stabilogram.
Note the value are centred to make comparison eaiser.
"""
plt.figure(figsize=(6, 6), dpi=72)
plt.xlim([-5, 5])
plt.ylim([-5, 5])
line_style = ['-', '--', '-.', ':']
line_index = 0
for part_id in HAs:
str_part_id = str(part_id)
#skel_root_path = os.path.abspath('../504/504_Quiet-Standing-Eyes-Open/skel')
skel_root_path = os.path.abspath('../' + str_part_id + '/' + str_part_id + '_Quiet-Standing-Eyes-Open/skel')
recording = KinectRecording(skel_root_path, "", 'Quiet-Standing-Eyes-Open', str_part_id)
plt.plot(centre(recording.stacked_filtered_XYZ_values[0, 25][start_frame:end_frame])*100,
centre(recording.stacked_filtered_XYZ_values[2, 25][start_frame:end_frame])*100,
color='black', linestyle=line_style[line_index])
line_index += 1
line_index = 0
for part_id in CaRs:
str_part_id = str(part_id)
#skel_root_path = os.path.abspath('../504/504_Quiet-Standing-Eyes-Open/skel')
skel_root_path = os.path.abspath('../' + str_part_id + '/' + str_part_id + '_Quiet-Standing-Eyes-Open/skel')
recording = KinectRecording(skel_root_path, "", 'Quiet-Standing-Eyes-Open', part_id)
plt.plot(centre(recording.stacked_filtered_XYZ_values[0, 25][start_frame:end_frame])*100,
centre(recording.stacked_filtered_XYZ_values[2, 25][start_frame:end_frame])*100,
color='red', linestyle=line_style[line_index])
line_index += 1
plt.legend(HAs + CaRs, loc=1)
plt.title('Stacked Stabilogram')
plt.xlabel('ML (cm)')
plt.ylabel('AP (cm)')
plt.show()
#%%
"""
JOint angles, in Sagital (SP), Frontal (FR) and Transvers (TR) planies can
also be caclulated using the sway_utils library
As before, once processed the calulated values are cached.
"""
plt.figure(figsize=(8, 6), dpi=72)
skel_root_path = os.path.abspath('../' + str(HAs[0]) +'/' + str(HAs[0]) +'_STS-5/skel')
recording = KinectRecording(skel_root_path, "", 'STS-5', HAs[0])
recording.calculate_walked_skel_angles()
KNEE_left = recording.walked_skel_angles['KNEELEFT_a_SP']
KNEE_right = recording.walked_skel_angles['KNEERIGHT_a_SP']
plt.plot(KNEE_left, color='black')
plt.plot(KNEE_right, color='black')
skel_root_path = os.path.abspath('../' + str(CaRs[0]) +'/' + str(CaRs[0]) +'_STS-5/skel')
recording = KinectRecording(skel_root_path, "", 'STS-5', CaRs[0])
recording.calculate_walked_skel_angles()
KNEE_left = recording.walked_skel_angles['KNEELEFT_a_SP']
KNEE_right = recording.walked_skel_angles['KNEERIGHT_a_SP']
plt.plot(KNEE_left, color='red')
plt.plot(KNEE_right, color='red')
plt.legend([str(HAs[0])+ '_KNEE_left', str(HAs[0]) + '_KNEE_right',
str(CaRs[0])+ '_KNEE_left', str(CaRs[0]) + '_KNEE_right'], loc=1)
plt.xlabel('frame #')
plt.ylabel('relitive angle (deg)')
plt.show()