slightly tweaked mocapnet alt container

This commit is contained in:
Kasisnu
2024-01-18 19:23:00 +05:30
parent 881c2fc840
commit 0d662c5b9d
294 changed files with 99862 additions and 2 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,177 @@
import sys
import cv2
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import load_model
from readCOCO import resize_image_with_borders
dataType = np.uint8 #
useGPU = True
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--float32"):
dataType = np.float32
if (sys.argv[i]=="--uint8"):
dataType = np.uint8
if (sys.argv[i]=="--cpu"):
useGPU = False
# Set CUDA_VISIBLE_DEVICES to an empty string to force TensorFlow to use the CPU
if (not useGPU):
os.environ['CUDA_VISIBLE_DEVICES'] = '' #<- Force CPU
def load_keypoints_model(model_path):
from readCOCO import PCKMetric,RSquaredMetric,FocalLoss,focal_loss,JointsMSELoss,jointsMSE_loss,VanillaMSELoss,vanilla_mse_loss
model = load_model(model_path, custom_objects={'PCKMetric': PCKMetric, 'RSquaredMetric':RSquaredMetric, 'focal_loss': focal_loss, 'jointsMSE_loss': jointsMSE_loss, 'vanilla_mse_loss':vanilla_mse_loss})
# Check the shape of the input layer
input_layer = model.layers[0] # Assuming the input layer is the first layer
input_shape = input_layer.input_shape
input_size = (input_shape[0][1],input_shape[0][2])
print("Input shape is ",input_size)
# Get the output layer of the model
output_layer = model.layers[-1] # Assuming the output layer is the last layer
output_shape = output_layer.output_shape
output_size = (output_shape[2],output_shape[3])
numberOfHeatmaps = output_shape[1]
print("Number of Heatmaps is ", numberOfHeatmaps)
print("Output Shape is ", output_size)
return model,input_size,output_size,numberOfHeatmaps
def preprocess_image(frame, target_size=(128, 128)):
# Resize the frame to the target size and normalize pixel values
# Step 1: Convert the image to float32
image = frame.astype(dataType)
#print("Input Image Range:", np.min(image), np.max(image))
#print("Input Image Mean:", np.mean(image))
#print("Input Image STD:", np.std(image))
# Step 2: Normalize the pixel values to be in the range [0, 1]
#image = image / 255
image, keypointXMultiplier, keypointYMultiplier, keypointXOffset, keypointYOffset = resize_image_with_borders(image,target_size)
return image
def predict_keypoints(model, image):
# Use the model call for predictions
image_batch = np.expand_dims(image, axis=0)
predictions = model(image_batch, training=False)
return predictions[0]
def visualize_heatmaps(frame, frameNumber, heatmaps, keypoint_names, threshold=0.0):
i=0
wnd_x = 0
wnd_y = 0
#Scale back window
#rgb_uint8_image = frame * 255
rgb_uint8_image = frame
# Convert to uint8 type for display
rgb_uint8_image = np.uint8(rgb_uint8_image)
# Display the result
cv2.imshow('RGB Input', rgb_uint8_image)
if (frameNumber==0):
cv2.moveWindow("RGB Input", wnd_x, wnd_y)
wnd_y+=231
#print("Heatmaps ",heatmaps.shape)
for i in range(0,heatmaps.shape[2]):
heatmap = heatmaps[:,:,i]
resized_heatmap = np.array(heatmap,dtype=dataType)
if (threshold>0.0):
# Create a boolean mask for values above the threshold
resized_heatmap[resized_heatmap <= threshold] = 0
#heatmap_uint8 = np.uint8(resized_heatmap)
#print("Heatmap ",i," shape ",heatmap.shape)
cv2.imshow('Heatmap %s'% keypoint_names[i], resized_heatmap)
if (frameNumber==0):
cv2.moveWindow('Heatmap %s'% keypoint_names[i], wnd_x, wnd_y)
wnd_y+=170
if ( wnd_y > 900 ):
wnd_x+=384
wnd_y =0
i=i+1
cv2.waitKey(1)
def webcam_keypoints_detection(model_path, keypoint_names, threshold=0.0):
# Load the 2D Pose Estimation model
keypoints_model,input_size,output_size,numberOfHeatmaps = load_keypoints_model(model_path)
# Open a connection to the webcam (0 indicates the default camera)
cap = cv2.VideoCapture(0)
frameNumber = 0
while True:
# Capture a single frame from the webcam
ret, frame = cap.read()
if not ret:
print("Failed to capture frame")
break
# Preprocess the frame for the model
input_image = preprocess_image(frame, target_size=input_size)
# Make predictions using the model
keypoints_predictions = predict_keypoints(keypoints_model, input_image)
#i=0
#for keypoint in keypoints_predictions:
# print("Prediction ",keypoint_names[i]," Range:", np.min(keypoint), np.max(keypoint))
# print("Prediction ",keypoint_names[i]," Mean:", np.mean(keypoint))
# print("Prediction ",keypoint_names[i]," STD:", np.std(keypoint))
# i=i+1
# Visualize the heatmaps on the source image
visualize_heatmaps(input_image,frameNumber, keypoints_predictions, keypoint_names, threshold=threshold)
frameNumber = frameNumber + 1
# Release the webcam and close all OpenCV windows
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
# Specify the path to the trained 2D Pose Estimation model
model_path = '2d_pose_estimation'
# Specify the names of keypoints (change accordingly based on your model's keypoint order)
keypoint_names = [
"nose",
"left_eye",
"right_eye",
"left_ear",
"right_ear",
"left_shoulder",
"right_shoulder",
"left_elbow",
"right_elbow",
"left_wrist",
"right_wrist",
"left_hip",
"right_hip",
"left_knee",
"right_knee",
"left_ankle",
"right_ankle",
"bkg"
]
print("Reported Keypoints : ",keypoint_names)
# Run the webcam keypoints detection
webcam_keypoints_detection(model_path, keypoint_names, threshold = 0.0)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,395 @@
#Written by Ammar Qammaz 2022-2023
#This is a Blender Python script that upon loaded can facilitate animating a skinned model created by
#the MakeHuman plugin for Blender ( http://static.makehumancommunity.org/mpfb.html )
mnetPluginVersion=float(0.02)
import bpy
from bpy.props import EnumProperty
def retrieveSkinToBVHAssotiationDict(doBody=True,doHands=True,doFeet=True,doFace=False):
r = dict()
if (doBody):
r["root"]="Hip" #This should be hip not Hip but for some reason (ZYX rotation) there is a discrepancy
r["spine03"]="abdomen"
r["spine04"]="chest"
#---------------------------
r["shoulder01.L"]="lCollar"
r["upperarm01.L"]="lShldr"
r["lowerarm01.L"]="lForeArm"
r["wrist.L"]="lHand"
#---------------------------
r["shoulder01.R"]="rCollar"
r["upperarm01.R"]="rShldr"
r["lowerarm01.R"]="rForeArm"
r["wrist.R"]="rHand"
#---------------------------
if (doHands):
#---------------------------
# L Hand
#---------------------------
r["finger1-1.L"]="lthumb"
r["finger1-2.L"]="finger1-2.l"
r["finger1-3.L"]="finger1-3.l"
#---------------------------
r["metacarpal1.L"]="metacarpal1.l"
r["finger2-1.L"]="finger2-1.l"
r["finger2-2.L"]="finger2-2.l"
r["finger2-3.L"]="finger2-3.l"
#---------------------------
r["metacarpal2.L"]="metacarpal2.l"
r["finger3-1.L"]="finger3-1.l"
r["finger3-2.L"]="finger3-2.l"
r["finger3-3.L"]="finger3-3.l"
#---------------------------
r["metacarpal3.L"]="metacarpal3.l"
r["finger4-1.L"]="finger4-1.l"
r["finger4-2.L"]="finger4-2.l"
r["finger4-3.L"]="finger4-3.l"
#---------------------------
r["metacarpal4.L"]="metacarpal4.l"
r["finger5-1.L"]="finger5-1.l"
r["finger5-2.L"]="finger5-2.l"
r["finger5-3.L"]="finger5-3.l"
#---------------------------
# R Hand
#---------------------------
r["finger1-1.R"]="rthumb"
r["finger1-2.R"]="finger1-2.r"
r["finger1-3.R"]="finger1-3.r"
#---------------------------
r["metacarpal1.R"]="metacarpal1.r"
r["finger2-1.R"]="finger2-1.r"
r["finger2-2.R"]="finger2-2.r"
r["finger2-3.R"]="finger2-3.r"
#---------------------------
r["metacarpal2.R"]="metacarpal2.r"
r["finger3-1.R"]="finger3-1.r"
r["finger3-2.R"]="finger3-2.r"
r["finger3-3.R"]="finger3-3.r"
#---------------------------
r["metacarpal3.R"]="metacarpal3.r"
r["finger4-1.R"]="finger4-1.r"
r["finger4-2.R"]="finger4-2.r"
r["finger4-3.R"]="finger4-3.r"
#---------------------------
r["metacarpal4.R"]="metacarpal4.r"
r["finger5-1.R"]="finger5-1.r"
r["finger5-2.R"]="finger5-2.r"
r["finger5-3.R"]="finger5-3.r"
#---------------------------
if (doFeet):
r["upperleg02.L"]="lThigh"
r["lowerleg01.L"]="lShin"
r["foot.L"]="lFoot"
#---------------------------
r["upperleg02.R"]="rThigh"
r["lowerleg01.R"]="rShin"
r["foot.R"]="rFoot"
#---------------------------
# L Foot
#---------------------------
r["toe1-1.L"]="toe1-1.L"
r["toe1-2.L"]="toe1-2.L"
for toe in range(2,6):
for part in range(1,4):
r["toe%u-%u.L"%(toe,part)]="toe%u-%u.L"%(toe,part)
#---------------------------
#---------------------------
# R Foot
#---------------------------
r["toe1-1.R"]="toe1-1.R"
r["toe1-2.R"]="toe1-2.R"
for toe in range(2,6):
for part in range(1,4):
r["toe%u-%u.R"%(toe,part)]="toe%u-%u.R"%(toe,part)
#---------------------------
#---------------------------
# Face
#---------------------------
#---------------------------
if (doFace):
r["neck01"]="neck1"
r["head"]="head"
r["__jaw"]="__jaw"
r["jaw"]="jaw"
r["special04"]="special04"
r["oris02"]="oris02"
r["oris01"]="oris01"
r["oris06.L"]="oris06.l"
r["oris07.L"]="oris07.l"
r["oris06.R"]="oris06.r"
r["oris07.R"]="oris07.r"
r["tongue00"]="tongue00"
r["tongue01"]="tongue01"
r["tongue02"]="tongue02"
r["tongue03"]="tongue03"
r["__tongue04"]="__tongue04"
r["tongue04"]="tongue04"
r["tongue07.L"]="tongue07.l"
r["tongue07.R"]="tongue07.r"
r["tongue06.L"]="tongue06.l"
r["tongue06.R"]="tongue06.r"
r["tongue05.L"]="tongue05.l"
r["tongue05.R"]="tongue05.r"
r["__levator02.L"]="__levator02.l"
r["levator02.L"]="levator02.l"
r["levator03.L"]="levator03.l"
r["levator04.L"]="levator04.l"
r["levator05.L"]="levator05.l"
r["__levator02.R"]="__levator02.r"
r["levator02.R"]="levator02.r"
r["levator03.R"]="levator03.r"
r["levator04.R"]="levator04.r"
r["levator05.R"]="levator05.r"
r["__special01"]="__special01"
r["special01"]="special01"
r["oris04.L"]="oris04.l"
r["oris03.L"]="oris03.l"
r["oris04.R"]="oris04.r"
r["oris03.R"]="oris03.r"
r["oris06"]="oris06"
r["oris05"]="oris05"
r["__special03"]="__special03"
r["special03"]="special03"
r["__levator06.L"]="__levator06.l"
r["levator06.L"]="levator06.l"
r["__levator06.R"]="__levator06.r"
r["levator06.R"]="levator06.r"
r["special06.L"]="special06.l"
r["special05.L"]="special05.l"
r["eye.L"]="eye.l"
r["orbicularis03.L"]="orbicularis03.l"
r["orbicularis04.L"]="orbicularis04.l"
r["special06.R"]="special06.r"
r["special05.R"]="special05.r"
r["eye.R"]="eye.r"
r["orbicularis03.R"]="orbicularis03.r"
r["orbicularis04.R"]="orbicularis04.r"
r["__temporalis01.L"]="__temporalis01.l"
r["temporalis01.L"]="temporalis01.l"
r["oculi02.L"]="oculi02.l"
r["oculi01.L"]="oculi01.l"
r["__temporalis01.R"]="__temporalis01.r"
r["temporalis01.R"]="temporalis01.r"
r["oculi02.R"]="oculi02.r"
r["oculi01.R"]="oculi01.r"
r["__temporalis02.L"]="__temporalis02.l"
r["temporalis02.L"]="temporalis02.l"
r["risorius02.L"]="risorius02.l"
r["risorius03.L"]="risorius03.l"
r["__temporalis02.R"]="__temporalis02.r"
r["temporalis02.R"]="temporalis02.r"
r["risorius02.R"]="risorius02.r"
r["risorius03.R"]="risorius03.r"
return r
class MocapNETBVHAnimationPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "MocapNET BVH Animation Helper"
bl_idname = "OBJECT_PT_mocapnet_panel"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
context = bpy.context
scene = context.scene
layout = self.layout
obj = context.object
#layout = layout.split(factor=0.96, align=True)
#------------------------------------------------------------------
#------------------------------------------------------------------
row = layout.row()
row.label(text="MocapNET BVH Animation Helper v%0.2f" % mnetPluginVersion, icon='WORLD_DATA')
#------------------------------------------------------------------
row = layout.row()
row.label(text="BVH file to use as source: ")
row = layout.row()
row.prop_search(scene, "mnetSource", scene, "objects", icon='ARMATURE_DATA')
#------------------------------------------------------------------
row = layout.row()
row.label(text="Skinned Body to use as target: ")
row = layout.row()
row.prop_search(scene, "mnetTarget", scene, "objects", icon='OUTLINER_OB_ARMATURE')
#------------------------------------------------------------------
row = layout.row()
row.label(text="Parts of MocapNET BVH file to link: ")
row = layout.row()
row.operator("mocapnet.mocapnet_op",text='Automatic').action='LINK'
row.operator("mocapnet.mocapnet_op",text='Upperbody').action='LINKUP'
row.operator("mocapnet.mocapnet_op",text='Face').action='LINKFACE'
row = layout.row()
row.label(text="Positional Component : ")
row = layout.row()
row.operator("mocapnet.mocapnet_op",text='Link Position').action='LINKPOS'
class MocapNETBVHAnimation(bpy.types.Operator):
"""Creates a Panel in the Object properties window"""
bl_label = "MocapNET BVH Animation"
bl_idname = "mocapnet.mocapnet_op"
bl_description = 'MocapNET operation control'
bl_options = {'REGISTER', 'UNDO'}
action: EnumProperty(
items=[
('LINK', 'Link MocapNET to Skinned Model', 'Link MocapNET to Skinned Model'),
('LINKUP', 'Link MocapNET to Upper Body Only', 'Link MocapNET to Upper Body Only'),
('LINKFACE', 'Link MocapNET to Face', 'Link MocapNET to Face'),
('LINKPOS', 'Link MocapNET positional component', 'Link MocapNET positional component')
]
)
@staticmethod
def add_cube(context):
bpy.ops.mesh.primitive_cube_add()
@staticmethod
def add_sphere(context):
bpy.ops.mesh.primitive_uv_sphere_add()
@staticmethod
def copyPosition(context,doBody=True,doHands=True,doFeet=True,doFace=False):
context = bpy.context
scene = context.scene
#-------------------------------------------------------
#associations = retrieveSkinToBVHAssotiationDict(doBody=doBody,doHands=doHands,doFeet=doFeet,doFace=doFace)
#-------------------------------------------------------
bvhObjectName = bpy.context.scene.mnetSource
skinnedObjectName = bpy.context.scene.mnetTarget
print("bvhObjectName",bvhObjectName)
print("skinnedObjectName",skinnedObjectName)
#-------------------------------------------------------
skinnedObject = scene.objects.get(skinnedObjectName)
bvhObject = scene.objects.get(bvhObjectName)
if (skinnedObject is not None) and (bvhObject is not None):
skinnedBoneName = "root"
bvhBoneName = "hip"
#------------------------------------------------
#bvhBoneName = associations[skinnedBoneName]
#------------------------------------------------
skinnedBone = skinnedObject.pose.bones.get(skinnedBoneName)
bvhBone = bvhObject.pose.bones.get(bvhBoneName)
print("pos associate ",skinnedBoneName," -> ",bvhBoneName)
# give it a copy rotation constraint
if (skinnedBone is not None) and (bvhBone is not None):
if (skinnedBoneName=="root"):
crc = skinnedBone.constraints.new('COPY_LOCATION')
crc.target = bvhObject
crc.subtarget = bvhBoneName
print("DONE ",skinnedBoneName)
@staticmethod
def copySkeletonConstraints(context,doBody=True,doHands=True,doFeet=True,doFace=False,doPosition=False,doRotation=True):
context = bpy.context
scene = context.scene
#-------------------------------------------------------
associations = retrieveSkinToBVHAssotiationDict(doBody=doBody,doHands=doHands,doFeet=doFeet,doFace=doFace)
#-------------------------------------------------------
bvhObjectName = bpy.context.scene.mnetSource
skinnedObjectName = bpy.context.scene.mnetTarget
print("bvhObjectName",bvhObjectName)
print("skinnedObjectName",skinnedObjectName)
#-------------------------------------------------------
skinnedObject = scene.objects.get(skinnedObjectName)
bvhObject = scene.objects.get(bvhObjectName)
if (skinnedObject is not None) and (bvhObject is not None):
for skinnedBoneName in associations:
#------------------------------------------------
bvhBoneName = associations[skinnedBoneName]
#------------------------------------------------
skinnedBone = skinnedObject.pose.bones.get(skinnedBoneName)
bvhBone = bvhObject.pose.bones.get(bvhBoneName)
# give it a copy rotation constraint
if (skinnedBone is not None) and (bvhBone is not None):
if (len(skinnedBone.constraints)>0):
for c in skinnedBone.constraints:
skinnedBone.constraints.remove(c) # Remove constraint
if (skinnedBoneName=="root") and (doPosition):
crc = skinnedBone.constraints.new('COPY_LOCATION')
crc.target = bvhObject
crc.subtarget = bvhBoneName
if (doRotation):
crc = skinnedBone.constraints.new('COPY_ROTATION')
crc.target = bvhObject
crc.subtarget = bvhBoneName
def execute(self, context):
if self.action == 'LINK':
self.copySkeletonConstraints(context=context,doBody=True,doHands=True,doFeet=True,doFace=False)
elif self.action == 'LINKUP':
self.copySkeletonConstraints(context=context,doBody=True,doHands=True,doFeet=False,doFace=False)
elif self.action == 'LINKFACE':
self.copySkeletonConstraints(context=context,doBody=False,doHands=False,doFeet=False,doFace=True)
elif self.action == 'LINKPOS':
self.copyPosition(context=context,doBody=True,doHands=False,doFeet=False,doFace=False)
return {'FINISHED'}
classes = (MocapNETBVHAnimationPanel,
MocapNETBVHAnimation)
def register():
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.Scene.mnetSource = bpy.props.StringProperty(name="Source BVH", default="Select BVH Object")
bpy.types.Scene.mnetTarget = bpy.props.StringProperty(name="Target Obj", default="Select Skinned Object")
def unregister():
for cls in classes:
bpy.utils.unregister_class(cls)
del bpy.types.Scene.mnetSource
del bpy.types.Scene.mnetTarget
if __name__ == "__main__":
register()
# Get a list of all add-ons that are currently activated
activated_addons = [addon.module for addon in bpy.context.preferences.addons if addon]
haveMPFB = False
# Print the name of each activated add-on
for addon in activated_addons:
print(addon)
if (addon=="mpfb"):
haveMPFB = True
print("We already have MPFB!")
if (not haveMPFB):
import os
print("Receiving a fresh copy of MPFB!")
current_directory = os.getcwd()
print("Working from ",current_directory," directory")
os.system("wget http://download.tuxfamily.org/makehuman/plugins/mpfb2-latest.zip")
print(" Downloaded mpfb2-latest.zip and will now auto-install it for your convinience ")
bpy.ops.preferences.addon_install(filepath='%s/mpfb2-latest.zip' % os.getcwd())
bpy.ops.preferences.addon_enable(module='mpfb')
bpy.ops.wm.save_userpref()
# Get the path to the user preferences file
prefs_file = bpy.utils.user_resource('CONFIG') #bpy.context.preferences.filepath
# Get the directory that contains the preferences file
prefs_dir = os.path.dirname(prefs_file)
print(" Also installing the makehuman system assets!")
os.system("cd %s/mpfb/data && wget http://files.makehumancommunity.org/asset_packs/makehuman_system_assets/makehuman_system_assets_cc0.zip && unzip makehuman_system_assets_cc0.zip && rm makehuman_system_assets_cc0.zip" % prefs_dir)
@@ -0,0 +1,37 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$DIR"
BLENDER="blender-3.4.1-linux-x64"
if [[ -d "$BLENDER" ]]
then
echo "Blender seems to exist on your filesystem."
else
echo "Will get a copy of blender."
#https://www.blender.org/download/release/Blender3.4/blender-3.4.1-linux-x64.tar.xz/
wget https://ftp.halifax.rwth-aachen.de/blender/release/Blender3.4/$BLENDER.tar.xz
tar -xf $BLENDER.tar.xz
fi
#This now happens from inside the blender_mocapnet.py script in the main function
#--------------------------------------------------------------------------------
#git clone https://github.com/makehumancommunity/mpfb2
#mkdir -p ~/.config/blender/3.4/scripts/addons/
#cd ~/.config/blender/3.4/scripts/addons/
#ln -s $DIR/mpfb2/src/mpfb
#OR
#wget http://download.tuxfamily.org/makehuman/plugins/mpfb2-latest.zip
#wget http://files.makehumancommunity.org/asset_packs/makehuman_system_assets/makehuman_system_assets_cc0.zip
#--------------------------------------------------------------------------------
xdg-open "https://www.youtube.com/watch?v=ooLRUS5j4AI"&
cd "$DIR"
$BLENDER/blender -y --python blender_mocapnet.py
exit 0
@@ -0,0 +1,2 @@
head_reye_2,head_reye_5,head_leye_1,head_leye_4,head_nostrills_2,head_chin,head_outmouth_0,head_outmouth_3,head_outmouth_6,head_outmouth_9
4865,36,11483,6820,297,5171,402,466,7162,492
1 head_reye_2 head_reye_5 head_leye_1 head_leye_4 head_nostrills_2 head_chin head_outmouth_0 head_outmouth_3 head_outmouth_6 head_outmouth_9
2 4865 36 11483 6820 297 5171 402 466 7162 492
@@ -0,0 +1,2 @@
head_reyebrow_2,head_reyebrow_4,head_leyebrow_2,head_leyebrow_4
102,121,40,59
1 head_reyebrow_2 head_reyebrow_4 head_leyebrow_2 head_leyebrow_4
2 102 121 40 59
@@ -0,0 +1,2 @@
head_reye,head_leye
1023,485
1 head_reye head_leye
2 1023 485
@@ -0,0 +1,2 @@
head_reye_0,head_reye_1,head_reye_2,head_reye_3,head_reye_4,head_reye_5,head_leye_0,head_leye_1,head_leye_2,head_leye_3,head_leye_4,head_leye_5,head_nosebone_0,head_nosebone_1,head_nosebone_2,head_nosebone_3,head_nostrills_0,head_nostrills_1,head_nostrills_2,head_nostrills_3,head_nostrills_4,head_rchin_0,head_rchin_1,head_rchin_2,head_rchin_3,head_rchin_4,head_rchin_5,head_rchin_6,head_rchin_7,head_chin,head_lchin_7,head_lchin_6,head_lchin_5,head_lchin_4,head_lchin_3,head_lchin_2,head_lchin_1,head_lchin_0,head_outmouth_0,head_outmouth_1,head_outmouth_2,head_outmouth_3,head_outmouth_4,head_outmouth_5,head_outmouth_6,head_outmouth_7,head_outmouth_8,head_outmouth_9,head_outmouth_10,head_outmouth_11,head_inmouth_0,head_inmouth_1,head_inmouth_2,head_inmouth_3,head_inmouth_4,head_inmouth_5,head_inmouth_6,head_inmouth_7
4854,4849,4865,67,47,36,6851,11483,11467,11472,6820,13368,136,135,5063,5134,5095,295,297,7062,11710,256,5181,5176,5153,5299,5227,5172,5166,5171,11779,11835,11903,11904,11767,11929,11796,7025,402,448,460,466,7219,7208,7162,7233,7245,492,490,478,432,704,468,7429,7192,7279,494,534
1 head_reye_0 head_reye_1 head_reye_2 head_reye_3 head_reye_4 head_reye_5 head_leye_0 head_leye_1 head_leye_2 head_leye_3 head_leye_4 head_leye_5 head_nosebone_0 head_nosebone_1 head_nosebone_2 head_nosebone_3 head_nostrills_0 head_nostrills_1 head_nostrills_2 head_nostrills_3 head_nostrills_4 head_rchin_0 head_rchin_1 head_rchin_2 head_rchin_3 head_rchin_4 head_rchin_5 head_rchin_6 head_rchin_7 head_chin head_lchin_7 head_lchin_6 head_lchin_5 head_lchin_4 head_lchin_3 head_lchin_2 head_lchin_1 head_lchin_0 head_outmouth_0 head_outmouth_1 head_outmouth_2 head_outmouth_3 head_outmouth_4 head_outmouth_5 head_outmouth_6 head_outmouth_7 head_outmouth_8 head_outmouth_9 head_outmouth_10 head_outmouth_11 head_inmouth_0 head_inmouth_1 head_inmouth_2 head_inmouth_3 head_inmouth_4 head_inmouth_5 head_inmouth_6 head_inmouth_7
2 4854 4849 4865 67 47 36 6851 11483 11467 11472 6820 13368 136 135 5063 5134 5095 295 297 7062 11710 256 5181 5176 5153 5299 5227 5172 5166 5171 11779 11835 11903 11904 11767 11929 11796 7025 402 448 460 466 7219 7208 7162 7233 7245 492 490 478 432 704 468 7429 7192 7279 494 534
@@ -0,0 +1,2 @@
head_reyebrow_0,head_reyebrow_1,head_reyebrow_2,head_reyebrow_3,head_reyebrow_4,head_leyebrow_4,head_leyebrow_3,head_leyebrow_2,head_leyebrow_1,head_leyebrow_0
96,93,102,111,121,59,49,40,31,57
1 head_reyebrow_0 head_reyebrow_1 head_reyebrow_2 head_reyebrow_3 head_reyebrow_4 head_leyebrow_4 head_leyebrow_3 head_leyebrow_2 head_leyebrow_1 head_leyebrow_0
2 96 93 102 111 121 59 49 40 31 57
@@ -0,0 +1,2 @@
head_reye,head_leye
1023,485
1 head_reye head_leye
2 1023 485
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,2 @@
head_nostrills_2,head_chin,head_outmouth_0,head_outmouth_1,head_outmouth_2,head_outmouth_3,head_outmouth_4,head_outmouth_5,head_outmouth_6,head_outmouth_7,head_outmouth_8,head_outmouth_9,head_outmouth_10,head_outmouth_11,head_inmouth_0,head_inmouth_1,head_inmouth_2,head_inmouth_3,head_inmouth_4,head_inmouth_5,head_inmouth_6,head_inmouth_7
297,5171,402,448,460,466,7219,7208,7162,7233,7245,492,490,478,432,704,468,7429,7192,7279,494,534
1 head_nostrills_2 head_chin head_outmouth_0 head_outmouth_1 head_outmouth_2 head_outmouth_3 head_outmouth_4 head_outmouth_5 head_outmouth_6 head_outmouth_7 head_outmouth_8 head_outmouth_9 head_outmouth_10 head_outmouth_11 head_inmouth_0 head_inmouth_1 head_inmouth_2 head_inmouth_3 head_inmouth_4 head_inmouth_5 head_inmouth_6 head_inmouth_7
2 297 5171 402 448 460 466 7219 7208 7162 7233 7245 492 490 478 432 704 468 7429 7192 7279 494 534
@@ -0,0 +1,2 @@
head_reye_0,head_reye_1,head_reye_2,head_reye_3,head_reye_4,head_reye_5,head_nostrills_2,head_rchin_0,head_chin
4854,4849,4865,67,47,36,297,256,5171
1 head_reye_0 head_reye_1 head_reye_2 head_reye_3 head_reye_4 head_reye_5 head_nostrills_2 head_rchin_0 head_chin
2 4854 4849 4865 67 47 36 297 256 5171
@@ -0,0 +1,2 @@
head_reyebrow_0,head_reyebrow_1,head_reyebrow_2,head_reyebrow_3,head_reyebrow_4
96,93,102,111,121
1 head_reyebrow_0 head_reyebrow_1 head_reyebrow_2 head_reyebrow_3 head_reyebrow_4
2 96 93 102 111 121
@@ -0,0 +1,2 @@
head_reye
764
1 head_reye
2 764
+62
View File
@@ -0,0 +1,62 @@
#!/bin/bash
#Written by Ammar Qammaz a.k.a AmmarkoV - 2020
# This bash script uses gnuplot and R so make sure to :
# sudo apt-get install gnuplot r-base
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$DIR"
ORIG_DIR=`pwd`
function getStatistics
{
#use R to generate statistics
#sudo apt-get install r-base
R -q -e "x <- read.csv('$1', header = F); summary(x); sd(x[ , 1])" > $2
cat $1 | wc -l >> $2
}
IN="$1"
OUTPUT_IMAGE="AllDistancesFrequency_$2.png"
echo "plotAllJointsDistanceFrequency.sh $IN $OUTPUT_IMAGE"
getStatistics $IN $IN-statsraw.txt
cat $IN-statsraw.txt | grep -E 'Min|Qu|Median|Mean|Max' > $IN-stats.txt
STATS=`cat $IN-stats.txt`
MEAN=`cat $IN-stats.txt | grep "Mean" | cut -d':' -f2 `
MEDIAN=`cat $IN-stats.txt | grep "Median" | cut -d':' -f2 `
MAXIMUM=`cat $IN-stats.txt | grep "Max" | cut -d':' -f2 `
PLACETEXT=`cat $IN-stats.txt | grep "3rd" | cut -d':' -f2 `
LOW_LIMIT="50";
LIMIT="150";
NUMBER_OF_RECORDS=`wc -l $1 | cut -d' ' -f1`
GNUPLOT_CMD="set terminal png; \
set output \"$OUTPUT_IMAGE\"; set yrange [0:1];\
set title \"Frequency precision diagram $IN \";\
set xlabel \"Distance Of Joints(mm)\"; \
set ylabel \"Frequency Of Value\"; \
set arrow from $MEAN, graph 0 to $MEAN, graph 1 nohead; \
set label \"Mean Value of $MEAN mm \" at $MEAN,0.40; \
set arrow from $MEDIAN, graph 0 to $MEDIAN, graph 1 nohead; \
set label \"Median Value of $MEDIAN mm \" at $MEDIAN,0.30; \
set label \"$STATS\" at $PLACETEXT,0.85; \
binwidth=3;\
bin(x,width)=width*floor(x/width);\
plot [0:] '$IN' using (bin(\$1,binwidth)):(1.0) smooth cnorm t 'smooth cumulative'"
echo "WE WILL RUN "
echo "gnuplot -e \"$GNUPLOT_CMD\""
echo " "
echo " "
gnuplot -e "$GNUPLOT_CMD"
rm $IN-statsraw.txt
rm $IN-stats.txt
exit 0
@@ -0,0 +1,108 @@
#!/usr/bin/env python3
#Written by Ammar Qammaz a.k.a AmmarkoV - 2020
import h5py
import numpy as np
import csv
import os
import sys
from scipy.spatial import procrustes
from scipy.linalg import orthogonal_procrustes
#Taken from https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/procrustes.py
def compute_similarity_transform(X, Y, compute_optimal_scale=False):
"""
A port of MATLAB's `procrustes` function to Numpy.
Adapted from http://stackoverflow.com/a/18927641/1884420
Args
X: array NxM of targets, with N number of points and M point dimensionality
Y: array NxM of inputs
compute_optimal_scale: whether we compute optimal scale or force it to be 1
Returns:
d: squared error after transformation
Z: transformed Y
T: computed rotation
b: scaling
c: translation
"""
muX = X.mean(0)
muY = Y.mean(0)
X0 = X - muX
Y0 = Y - muY
ssX = (X0**2.).sum()
ssY = (Y0**2.).sum()
# centred Frobenius norm
normX = np.sqrt(ssX)
normY = np.sqrt(ssY)
# scale to equal (unit) norm
X0 = X0 / normX
Y0 = Y0 / normY
# optimum rotation matrix of Y
A = np.dot(X0.T, Y0)
U,s,Vt = np.linalg.svd(A,full_matrices=False)
V = Vt.T
T = np.dot(V, U.T)
# Make sure we have a rotation
detT = np.linalg.det(T)
V[:,-1] *= np.sign( detT )
s[-1] *= np.sign( detT )
T = np.dot(V, U.T)
traceTA = s.sum()
if compute_optimal_scale: # Compute optimum scaling of Y.
b = traceTA * normX / normY
d = 1 - traceTA**2
Z = normX*traceTA*np.dot(Y0, T) + muX
else: # If no scaling allowed
b = 1
d = 1 + ssY/ssX - 2 * traceTA * normY / normX
Z = normY*np.dot(Y0, T) + muX
c = muX - b*np.dot(muY, T)
return d, Z, T, b, c
def pointListsReturnAvgDistance(A,B):
numberOfPoints=A.shape[0]
if (A.shape[0]!=B.shape[0]):
print("Error comparing point lists of different length")
return inf
distance=0.0
for i in range(0,numberOfPoints):
#---------
xA=A[i][0]
yA=A[i][1]
zA=A[i][2]
#---------
xB=B[i][0]
yB=B[i][1]
zB=B[i][2]
#---------
xAB=xA-xB
yAB=yA-yB
zAB=zA-zB
#Pythagorean theorem for 3 dimensions
#distance = squareRoot( xAB^2 + yAB^2 + zAB^2 )
distance+=np.sqrt( (xAB*xAB) + (yAB*yAB) + (zAB*zAB) )
return distance/numberOfPoints
@@ -0,0 +1,622 @@
#!/usr/bin/env python3
#Written by Ammar Qammaz a.k.a AmmarkoV - 2020
from align2DPoints import pointListsReturnAvgDistance,compute_similarity_transform
from drawPointClouds import findJointID,get3DDistance,setupDrawing,drawLimbDimensions,drawLimbError,drawFrameError,drawAfterEndOfComparison
from writeCSVResults import writeCSVFileResults,appendRAWResultsForGNUplot
import numpy as np
import gc
import os
import sys
import csv
import time
import array
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import axes3d, Axes3D
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
#I have added a seperate list with the joints we want to compare
#to avoid the weird parent lists when you remove one joint
JOINTS_TO_COMPARE=list()
#JOINTS_TO_COMPARE.append('Nose') #0
JOINTS_TO_COMPARE.append('Neck') #1
JOINTS_TO_COMPARE.append('RShoulder') #2
JOINTS_TO_COMPARE.append('RElbow') #3
JOINTS_TO_COMPARE.append('RWrist') #4
JOINTS_TO_COMPARE.append('LShoulder') #5
JOINTS_TO_COMPARE.append('LElbow') #6
JOINTS_TO_COMPARE.append('LWrist') #7
JOINTS_TO_COMPARE.append('MidHip') #8
JOINTS_TO_COMPARE.append('RHip') #9
JOINTS_TO_COMPARE.append('RKnee') #10
JOINTS_TO_COMPARE.append('RAnkle') #11
JOINTS_TO_COMPARE.append('LHip') #12
JOINTS_TO_COMPARE.append('LKnee') #13
JOINTS_TO_COMPARE.append('LAnkle') #14
#These are our labels they have to match what we want to process
#If you don't want something to be part of the measurment remove it from here
#as well as from the JOINT_PARENTS list
#---------------------------------------------------------------------
JOINT_LABELS=list()
JOINT_LABELS.append('Nose') #0
JOINT_LABELS.append('Neck') #1
JOINT_LABELS.append('RShoulder') #2
JOINT_LABELS.append('RElbow') #3
JOINT_LABELS.append('RWrist') #4
JOINT_LABELS.append('LShoulder') #5
JOINT_LABELS.append('LElbow') #6
JOINT_LABELS.append('LWrist') #7
JOINT_LABELS.append('MidHip') #8
JOINT_LABELS.append('RHip') #9
JOINT_LABELS.append('RKnee') #10
JOINT_LABELS.append('RAnkle') #11
JOINT_LABELS.append('LHip') #12
JOINT_LABELS.append('LKnee') #13
JOINT_LABELS.append('LAnkle') #14
JOINT_LABELS.append('REye') #15
JOINT_LABELS.append('LEye') #16
JOINT_LABELS.append('REar') #17
JOINT_LABELS.append('LEar') #18
JOINT_LABELS.append('LBigToe') #19
JOINT_LABELS.append('LSmallToe') #20
JOINT_LABELS.append('LHeel') #21
JOINT_LABELS.append('RBigToe') #22
JOINT_LABELS.append('RSmallToe') #23
JOINT_LABELS.append('RHeel') #24
#These are our parents they have to match JOINT_LABELS
#If you don't want something to be part of the measurment remove it from here
#as well as from the JOINT_LABELS list
#---------------------------------------------------------------------
JOINT_PARENTS=list()
JOINT_PARENTS.append(findJointID("Neck",JOINT_LABELS)) #0 Parent of Nose is Neck
JOINT_PARENTS.append(findJointID("MidHip",JOINT_LABELS)) #1 Parent of Neck is MidHip
JOINT_PARENTS.append(findJointID("Neck",JOINT_LABELS)) #2 Parent of RShoulder is Neck
JOINT_PARENTS.append(findJointID("RShoulder",JOINT_LABELS)) #3 Parent of RElbow is RShoulder
JOINT_PARENTS.append(findJointID("RElbow",JOINT_LABELS)) #4 etc ...
JOINT_PARENTS.append(findJointID("Neck",JOINT_LABELS)) #5
JOINT_PARENTS.append(findJointID("LShoulder",JOINT_LABELS)) #6
JOINT_PARENTS.append(findJointID("LElbow",JOINT_LABELS)) #7
JOINT_PARENTS.append(findJointID("MidHip",JOINT_LABELS)) #8
JOINT_PARENTS.append(findJointID("MidHip",JOINT_LABELS)) #9
JOINT_PARENTS.append(findJointID("RHip",JOINT_LABELS)) #10
JOINT_PARENTS.append(findJointID("RKnee",JOINT_LABELS)) #11
JOINT_PARENTS.append(findJointID("MidHip",JOINT_LABELS)) #12
JOINT_PARENTS.append(findJointID("LHip",JOINT_LABELS)) #13
JOINT_PARENTS.append(findJointID("LKnee",JOINT_LABELS)) #14
JOINT_PARENTS.append(findJointID("Nose",JOINT_LABELS)) #15
JOINT_PARENTS.append(findJointID("Nose",JOINT_LABELS)) #16
JOINT_PARENTS.append(findJointID("Nose",JOINT_LABELS)) #17
JOINT_PARENTS.append(findJointID("Nose",JOINT_LABELS)) #18
JOINT_PARENTS.append(findJointID("LAnkle",JOINT_LABELS)) #19
JOINT_PARENTS.append(findJointID("LAnkle",JOINT_LABELS)) #20
JOINT_PARENTS.append(findJointID("LAnkle",JOINT_LABELS)) #21
JOINT_PARENTS.append(findJointID("RAnkle",JOINT_LABELS)) #22
JOINT_PARENTS.append(findJointID("RAnkle",JOINT_LABELS)) #23
JOINT_PARENTS.append(findJointID("RAnkle",JOINT_LABELS)) #24
#These are our labels that based on JOINT_PARENTS auto-create the appropriate labels
#---------------------------------------------------------------------
JOINT_PARENT_LABELS=list()
for i in range(0,len(JOINT_LABELS)):
JOINT_PARENT_LABELS.append(JOINT_LABELS[JOINT_PARENTS[i]])
#---------------------------------------------------------------------
def checkIfFileExists(filename):
return os.path.isfile(filename)
def convert_bytes(num):
"""
this function will convert bytes to MB.... GB... etc
"""
step_unit = 1000.0 #1024 bad the size
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
if num < step_unit:
return "%3.1f %s" % (num, x)
num /= step_unit
def getNumberOfLines(filename):
print("Counting number of lines in file ",filename)
with open(filename) as f:
return sum(1 for line in f)
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
def readCSVFile(filename,memPercentage,csvDelimiter,useHalfFloats,groupOutput):
print("CSV file :",filename,"..\n")
if (not checkIfFileExists(filename)):
print( bcolors.WARNING + "Input file "+filename+" does not exist, cannot read ground truth.." + bcolors.ENDC)
print("Current Directory was "+os.getcwd())
sys.exit(0)
start = time.time()
dtypeSelected=np.dtype(np.float32)
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
if (useHalfFloats):
dtypeSelected=np.dtype(np.float16)
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
progress=0.0
sampleNumber=0
receivedHeader=0
inputNumberOfColumns=0
inputLabels=list()
#-------------------------------------------------------------------------------------------------
numberOfSamplesInput=getNumberOfLines(filename)-2
print(" Input file has ",numberOfSamplesInput," training samples\n")
#-------------------------------------------------------------------------------------------------
numberOfSamples = numberOfSamplesInput
numberOfSamplesLimit=int(numberOfSamples*memPercentage)
#-------------------------------------------------------------------------------------------------
if (memPercentage==0.0):
print("readGroundTruthFile was asked to occupy 0 memory so this probably means we just want one record")
numberOfSamplesLimit=2
if (memPercentage>1.0):
print("Memory Limit will be interpreted as a raw value..")
numberOfSamplesLimit=int(memPercentage)
#-------------------------------------------------------------------------------------------------
thisInput = array.array('f')
#---------------------------------
fi = open(filename, "r")
readerIn = csv.reader( fi , delimiter=csvDelimiter, skipinitialspace=True)
for rowIn in readerIn:
#------------------------------------------------------
if (not receivedHeader): #use header to get labels
#------------------------------------------------------
inputNumberOfColumns=len(rowIn)
#Make sure CSV files that end with delimiter are correctly handled..
if (inputNumberOfColumns>0):
if (rowIn[inputNumberOfColumns-1]==''):
inputNumberOfColumns=inputNumberOfColumns-1
#-----------------------------------------------------
inputLabels = list(rowIn[i] for i in range(0,inputNumberOfColumns) )
print("Number of Input elements : ",len(inputLabels))
#------------------------------------------------------
if (memPercentage==0):
print("Will only return labels\n")
return {'labels':inputLabels};
#i=0
#print("class Input(Enum):")
#for label in inputLabels:
# print(" ",label," = ",i," #",int(i/3))
# print(" ",label,"=",int(i/3))
# i=i+1
#---------------------------------
# Allocate Lists
#---------------------------------
for i in range(inputNumberOfColumns):
thisInput.append(0.0)
#---------------------------------
#---------------------------------
# Allocate Numpy Arrays
#---------------------------------
inputSize=0
startCompressed=0
inputSize=inputSize+inputNumberOfColumns
startCompressed=inputNumberOfColumns
npInputBytesize=0+numberOfSamplesLimit * inputSize * dtypeSelectedByteSize
print(" Input file on disk has a shape of [",numberOfSamples,",",inputSize,"]")
print(" Input we will read has a shape of [",numberOfSamplesLimit,",",inputSize,"]")
print(" Input will occupy ",convert_bytes(npInputBytesize)," of RAM\n")
npInput = np.full([numberOfSamplesLimit,inputSize],fill_value=0,dtype=dtypeSelected,order='C')
#----------------------------------------------------------------------------------------------------------
receivedHeader=1
#sys.exit(0)
else:
#-------------------------------------------
# First convert our string INPUT to floats
#-------------------------------------------
for i in range(inputNumberOfColumns):
thisInput[i]=float(rowIn[i])
#-------------------------------------------
for num in range(0,inputNumberOfColumns):
npInput[sampleNumber,num]=float(thisInput[num]);
#-------------------------------------------
sampleNumber=sampleNumber+1
if (numberOfSamples>0):
progress=sampleNumber/numberOfSamplesLimit
if (sampleNumber%1000==0) :
progressString = "%0.2f"%float(100*progress)
print("\rReading from disk (",sampleNumber,") - ",progressString," % \r", end="", flush=True)
if (numberOfSamplesLimit<=sampleNumber):
print("\rStopping reading file to obey memory limit given by parameter --mem ",memPercentage,"\n")
break
#-------------------------------------------
fi.close()
del readerIn
gc.collect()
print("\n read, Samples: ",sampleNumber,", was expecting ",numberOfSamples," samples\n")
print(npInput.shape)
totalNumberOfBytes=npInput.nbytes;
totalNumberOfGigaBytes=totalNumberOfBytes/1073741824;
print("Size Occupied by data = ",totalNumberOfGigaBytes," GB \n")
end = time.time()
print("Time elapsed : ",(end-start)/60," mins")
#---------------------------------------------------------------------
if (groupOutput==0):
#New better dictionary
output = dict()
for i in range(0,len(inputLabels)):
lowerCaseName = inputLabels[i].lower()
#print("Joint ",lowerCaseName)
output[lowerCaseName]=list()
for frameID in range(0,len(npInput)):
output[lowerCaseName].append(npInput[frameID][i])
return output
else:
#This is the old dictionary way (better for tensorflow training)
return {'label':inputLabels, 'body':npInput };
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#Main() program
#-------------------------------------
averageErrorDistances=list()
averageMotionEstimationDistancesBetweenFrames=list()
#These are labeling infos
#Used to correctly pack the results
#-------------------------
subject="S?"
action="Unknown"
subaction="?"
camera="?"
actionLabel="?"
addedPixelNoise=0
#These are configuration parameters
#-------------------------------------------------------------------
everyNFrames=0 # Run on every frame of the CSV files by default
drawPlot=0 # Don't Draw plot by default
doProcrustes=1 # Do procrustes analysis
procrustesScale=1 # Let procrustes also scale the point clouds
ground="h36.csv" # A default h36.csv filename
groundDelim=',' # By default the h36.csv has a ',' delimiter
output="out.csv" # A default output filename
outputDelim=';' # Damien's output has ';' delimiters, mine has ','
ourScaleX=1.0
ourScaleY=1.0
ourScaleZ=1.0
#Modifiers on comparisons..
#------------------------------------------------------------------------------------------------
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--ourscale"):
ourScaleX=float(sys.argv[i+1])
ourScaleY=float(sys.argv[i+2])
ourScaleZ=float(sys.argv[i+3])
if (sys.argv[i]=="--draw"):
drawPlot=1
if (sys.argv[i]=="--from"):
output=sys.argv[i+1]
outputDelim=sys.argv[i+2]
if (sys.argv[i]=="--ground"):
ground=sys.argv[i+1]
groundDelim=sys.argv[i+2]
if (sys.argv[i]=="--noprocrustes"):
doProcrustes=0
if (sys.argv[i]=="--every"):
everyNFrames=int(sys.argv[i+1])
if (sys.argv[i]=="--info"):
subject=sys.argv[i+1]
action=sys.argv[i+2]
camera=sys.argv[i+3]
addedPixelNoise=float(sys.argv[i+4])
print("\n Infos Set ",sys.argv[i+1])
actionLabel=action
s=actionLabel.split("-")
subaction=s[1]
action=s[0]
action=action.replace('/','')
subaction=subaction.replace('/','')
actionLabel=actionLabel.replace('/','')
camera=camera.replace('/','')
print("Subject ",subject," Action ",action," Subaction ",subaction," Camera ",camera)
#------------------------------------------------------------------------------------------------
if (drawPlot):
print("Using matplotlib:",matplotlib.__version__)
# === Plot and animate ===
fig = plt.figure()
fig.set_size_inches(19.2, 10.8, forward=True)
ax = fig.add_subplot(2, 2, 1, projection='3d')
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
ax4 = fig.add_subplot(2, 2, 4)
fig.subplots_adjust(left=0.05, bottom=0.05, right=0.95, top=0.95)
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
ax.set_zlabel('Z Axis')
ax.view_init(90, 90)
out=readCSVFile(output,1.0,outputDelim,0,0)
ground=readCSVFile(ground,1.0,groundDelim,0,0)
print("Output number of keys : %u " % len(out.keys()) )
print("GroundTruth number of keys : %u " % len(ground.keys()) )
if ( len(out.keys()) != len(ground.keys()) ):
print(bcolors.WARNING,"Inconsistent keys",bcolors.ENDC)
#sys.exit(0)
totalError=0.0
totalSamples=0
numberOfJointsToCompare = len(JOINTS_TO_COMPARE)
numberOfFrames = len(out['3dx_nose'])
#-----------------------
alljointDistances=list()
#-----------------------
jointDistance=list()
for jointID in range(0,numberOfJointsToCompare):
jointDistance.append(list())
#-----------------------
#------------------------------------------------------------------------------------------------
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--frames"):
numberOfFrames=int(sys.argv[i+1])
#------------------------------------------------------------------------------------------------
#We want to loop over every frame that we loaded..
for frameID in range(0,numberOfFrames):
#In many papers they run the comparison ever N frames
#So depending on this setting you can actually execute
#the comparison computation everyNFrames
#-----------------------------------------------------
if ( (everyNFrames==0) or (frameID%everyNFrames==0) ):
executeComputations=1
else:
executeComputations=0
#-----------------------------------------------------
if (executeComputations==1):
ourPointCloud=list()
h36PointCloud=list()
xlineStart=list()
xlineEnd=list()
ylineStart=list()
ylineEnd=list()
zlineStart=list()
zlineEnd=list()
#Align midhip to make sure we start from a sane position
offsetX=(ourScaleX*out['3dx_midhip'][frameID])-ground['3dx_midhip'][frameID]
offsetY=(ourScaleY*out['3dy_midhip'][frameID])-ground['3dy_midhip'][frameID]
offsetZ=(ourScaleZ*out['3dz_midhip'][frameID])-ground['3dz_midhip'][frameID]
for jointIDUnresolved in range(0,numberOfJointsToCompare):
#------------------------------------------------------------------
#Our Joints to compare list has a different indexing
jointID = findJointID(JOINTS_TO_COMPARE[jointIDUnresolved],JOINT_LABELS)
if (jointID==-1):
print(bcolors.WARNING,"Failed to resolve joint: ",JOINTS_TO_COMPARE[jointIDUnresolved],bcolors.ENDC)
sys.exit(0)
#-----------------------------------------------------------
jointKey = JOINT_LABELS[jointID].lower()
parentKey = JOINT_PARENT_LABELS[jointID].lower()
#print("Frame %u / Key %s ( prev %s ) "% (frameID,jointKey,parentKey) )
#------------------------------------------------------------------
#We select the joint and push it to the point cloud for this particular frame
xM=(ourScaleX*out['3dx_%s' % jointKey][frameID])-offsetX
yM=(ourScaleY*out['3dy_%s' % jointKey][frameID])-offsetY
zM=(ourScaleZ*out['3dz_%s' % jointKey][frameID])-offsetZ
ourPointCloud.append([xM,yM,zM])
#These lineStarts/lineEnds and parentKeys help draw lines connecting
#the dots in skeletons
xParentM=(ourScaleX*out['3dx_%s' % parentKey][frameID])-offsetX
yParentM=(ourScaleY*out['3dy_%s' % parentKey][frameID])-offsetY
zParentM=(ourScaleZ*out['3dz_%s' % parentKey][frameID])-offsetZ
xlineStart.append(xM)
ylineStart.append(yM)
zlineStart.append(zM)
xlineEnd.append(xParentM)
ylineEnd.append(yParentM)
zlineEnd.append(zParentM)
#------------------------------------------------------------------
#We select the h36 joint and push it to the point cloud for this particular frame
xH=ground['3dx_%s' % jointKey][frameID]
yH=ground['3dy_%s' % jointKey][frameID]
zH=ground['3dz_%s' % jointKey][frameID]
h36PointCloud.append([xH,yH,zH])
#These lineStarts/lineEnds and parentKeys help draw lines connecting
#the dots in skeletons
xParentH=ground['3dx_%s' % parentKey][frameID]
yParentH=ground['3dy_%s' % parentKey][frameID]
zParentH=ground['3dz_%s' % parentKey][frameID]
xlineStart.append(xH)
ylineStart.append(yH)
zlineStart.append(zH)
xlineEnd.append(xParentH)
ylineEnd.append(yParentH)
zlineEnd.append(zParentH)
#------------------------------------------------------------------
#------------------------------------------------------------------
#We package our lists in numpy to be able to easily manipulate them
#------------------------------------------------------------------
np_h36PointCloud = np.asarray(h36PointCloud,dtype=np.float32)
np_ourPointCloud = np.asarray(ourPointCloud,dtype=np.float32)
#This is the main comparison after using procrustes and transforming the pointcloud
#to align it or when just doing plain old euclidean distance
#--------------------------------------------------------------------------------
if (doProcrustes):
d, Z, T, b, c = compute_similarity_transform(np_h36PointCloud,np_ourPointCloud,compute_optimal_scale=procrustesScale)
#disparity=np.sqrt(d) #d: squared error after transformation
#print("compute_similarity_transform : ",disparity)
#Our point cloud is brought to the same translation and rotation as h36 point cloud
np_ourPointCloud = (b*np_ourPointCloud.dot(T))+c
disparity = pointListsReturnAvgDistance(np_ourPointCloud,np_h36PointCloud)
else:
disparity = pointListsReturnAvgDistance(np_ourPointCloud,np_h36PointCloud)
#--------------------------------------------------------------------------------
#We want to calculate Mean Per Joint Position Error (MPJPE)
#to do so we have to calculate the position error of each of the joints in our point cloud
#sum it up and then divide it through the number of samples
for jID in range(0,numberOfJointsToCompare):
#------------------------------------------------------------------
#We use the np_ourPointCloud and np_h36PointCloud so that if procrustes analysis is enabled it will be used..
perJointDisparity=get3DDistance(
np_ourPointCloud[jID][0],np_ourPointCloud[jID][1],np_ourPointCloud[jID][2],
np_h36PointCloud[jID][0],np_h36PointCloud[jID][1],np_h36PointCloud[jID][2]
)
totalError+=perJointDisparity
totalSamples+=1
#We also keep every sample on a list to do an analysis in the end
alljointDistances.append(perJointDisparity)
jointDistance[jID].append(perJointDisparity)
#------------------------------------------------------------------
print("Frame %u / Disparity %f " % (frameID,disparity))
averageErrorDistances.append(disparity)
#Draw the plot that summarizes what is happening if --draw is given
if (drawPlot):
drawAfterEndOfComparison(
JOINTS_TO_COMPARE,
JOINT_LABELS,
JOINT_PARENTS,
JOINT_PARENT_LABELS,
plt,ax,ax2,ax3,ax4,
xlineStart,xlineEnd,
ylineStart,ylineEnd,
zlineStart,zlineEnd,
np_ourPointCloud,
np_h36PointCloud,
frameID,
numberOfFrames,
everyNFrames,
disparity,
averageErrorDistances,
averageMotionEstimationDistancesBetweenFrames
)
#Since this always appends results be sure to remove the gnuplot.raw
#file before starting a new session..
appendRAWResultsForGNUplot("gnuplot.raw",alljointDistances)
#Final results we want is Mean Per Joint Position Error (MPJPE) so we rely on the perJointDisparities etc..
#The result unit depends on the input to the script but it should be in millimeters for MocapNET output
#to change units you can use the --ourscale X Y Z commandline parameter, however millimeters of accuracy
#is the norm for 3D pose estimation work..
print("\nMean Per Joint Error for ",totalSamples," samples is ",totalError/totalSamples)
median = np.median(alljointDistances)
mean = np.mean(alljointDistances)
average = np.average(alljointDistances)
std = np.std(alljointDistances)
var = np.var(alljointDistances)
print("Mean is ",mean," Std is ",std," Var is ",var)
writeHeader=0
if not os.path.exists("results.csv"):
writeHeader=1
writeCSVFileResults(
JOINTS_TO_COMPARE,
"results.csv",
writeHeader,
alljointDistances,
jointDistance,
numberOfJointsToCompare,
subject,
action,
subaction,
camera,
actionLabel,
addedPixelNoise
)
if (drawPlot):
os.system("ffmpeg -framerate 25 -i p%05d.png -s 1920x1080 -y -r 30 -pix_fmt yuv420p -threads 8 lastcomp.mp4 && rm ./p*.png") #
sys.exit(0)
@@ -0,0 +1,233 @@
#!/usr/bin/env python3
#Written by Ammar Qammaz a.k.a AmmarkoV - 2020
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import axes3d, Axes3D
print("Using matplotlib:",matplotlib.__version__)
def pointListReturnXYZListForScatterPlot(A):
numberOfPoints=A.shape[0]
xs=list()
ys=list()
zs=list()
for i in range(0,numberOfPoints):
xs.append(A[i][0])
ys.append(A[i][1])
zs.append(A[i][2])
return xs,ys,zs
def setupDrawing(fig,ax,ax2,ax3,ax4):
# === Plot and animate ===
fig = plt.figure()
fig.set_size_inches(19.2, 10.8, forward=True)
ax = fig.add_subplot(2, 2, 1, projection='3d')
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
ax4 = fig.add_subplot(2, 2, 4)
fig.subplots_adjust(left=0.05, bottom=0.05, right=0.95, top=0.95)
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
ax.set_zlabel('Z Axis')
ax.view_init(90, 90)
def get3DDistance(jX,jY,jZ,pX,pY,pZ):
return np.sqrt( ((jX-pX)*(jX-pX)) + ((jY-pY)*(jY-pY)) + ((jZ-pZ)*(jZ-pZ)) )
def findJointID(jointName,labels):
for i in range(0,len(labels)):
if (jointName==labels[i]):
return i
print("Cannot find joint ",jointName," !")
return -1
#-----------------------------------------------------------------------------------------------------------------------
def drawLimbDimensions(JOINTS_TO_COMPARE,JOINT_LABELS,JOINT_PARENTS,JOINT_PARENT_LABELS,h36mPoints,ourPoints,numberOfJoints,ax2):
labels = list()
h36m_distances = list()
mnet_distances = list()
for jointID in range(0,len(JOINTS_TO_COMPARE)):
#---------------------------------------
jointIDGlobal = findJointID(JOINTS_TO_COMPARE[jointID],JOINT_LABELS)
jointParentID=findJointID(JOINT_PARENT_LABELS[JOINT_PARENTS[jointIDGlobal]],JOINTS_TO_COMPARE)
#---------------------------------------
if (jointParentID!=-1) and (jointIDGlobal!=-1):
labels.append(JOINT_LABELS[jointIDGlobal])
jX=h36mPoints[jointID][0]
jY=h36mPoints[jointID][1]
jZ=h36mPoints[jointID][2]
pX=h36mPoints[jointParentID][0]
pY=h36mPoints[jointParentID][1]
pZ=h36mPoints[jointParentID][2]
distances=get3DDistance(jX,jY,jZ,pX,pY,pZ)
h36m_distances.append(distances)
#---------------------------------------
jX=ourPoints[jointID][0]
jY=ourPoints[jointID][1]
jZ=ourPoints[jointID][2]
pX=ourPoints[jointParentID][0]
pY=ourPoints[jointParentID][1]
pZ=ourPoints[jointParentID][2]
distances=get3DDistance(jX,jY,jZ,pX,pY,pZ)
mnet_distances.append(distances)
#---------------------------------------
#-------------------------------------------------
x = np.arange(len(labels)) # the label locations
width = 0.35 # the width of the bars
rects1 = ax2.bar(x - width/2, h36m_distances, width, label='H36M')
rects2 = ax2.bar(x + width/2, mnet_distances, width, label='Our Method')
# Add some text for labels, title and custom x-axis tick labels, etc.
ax2.set_ylim(auto=False,bottom=0,top=800)
ax2.set_ylabel('Limb dimensions in millimeters')
ax2.set_title('Comparison of H36M limb dimensions')
ax2.set_xticks(x)
ax2.set_xticklabels(labels, rotation=45, rotation_mode="anchor")
ax2.legend()
#autolabel(rects1)
#autolabel(rects2)
#-----------------------------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------------------------
def drawLimbError(JOINTS_TO_COMPARE,JOINT_LABELS,JOINT_PARENTS,JOINT_PARENT_LABELS,h36mPoints,ourPoints,numberOfJoints,ax3):
labels = list()
error_distances = list()
for jointID in range(0,len(JOINTS_TO_COMPARE)):
#---------------------------------------
jointIDGlobal = findJointID(JOINTS_TO_COMPARE[jointID],JOINT_LABELS)
#---------------------------------------
if (jointIDGlobal!=-1):
labels.append(JOINT_LABELS[jointIDGlobal])
jX=h36mPoints[jointID][0]
jY=h36mPoints[jointID][1]
jZ=h36mPoints[jointID][2]
pX=ourPoints[jointID][0]
pY=ourPoints[jointID][1]
pZ=ourPoints[jointID][2]
distances=get3DDistance(jX,jY,jZ,pX,pY,pZ)
error_distances.append(distances)
#---------------------------------------
#-------------------------------------------------
x = np.arange(len(labels)) # the label locations
width = 0.35 # the width of the bars
rects1 = ax3.bar(x - width/2, error_distances, width, label='Error in millimeters')
# Add some text for labels, title and custom x-axis tick labels, etc.
ax3.set_ylim(auto=False,bottom=0,top=250)
ax3.set_ylabel('Error in millimeters')
ax3.set_title('Comparison of 3D estimation error')
ax3.set_xticks(x)
ax3.set_xticklabels(labels, rotation=45, rotation_mode="anchor")
ax3.legend()
#-----------------------------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------------------------
def drawFrameError(averageErrorDistances,averageMotionEstimationDistancesBetweenFrames,ax4):
#minimum=np.min(averageErrorDistances)
#ax4.plot((0,len(averageErrorDistances)), (minimum,minimum),label='Minimum Error')
#maximum=np.max(averageErrorDistances)
#ax4.plot((0,len(averageErrorDistances)), (maximum,maximum),label='Maximum Error')
#median=np.median(averageErrorDistances)
#ax4.plot((0,len(averageErrorDistances)), (median,median),label='Median Error (%0.2f mm)'% median)
average=np.average(averageErrorDistances)
ax4.plot((0,len(averageErrorDistances)), (average,average),label='Average of average errors (%0.2f mm)' % average)
ax4.plot(averageErrorDistances, label='Our method average error in millimeters')
ax4.plot(averageMotionEstimationDistancesBetweenFrames, label='Distance of average joint from previous frame')
#ax4.set_ylim(auto=False,bottom=0,top=250)
ax4.set_xlabel('Experiment frame number')
ax4.set_ylabel('Millimeters')
ax4.set_title('Average 3D estimation error per frame')
#ax4.set_xticklabels(labels, rotation=45, rotation_mode="anchor")
ax4.legend()
#-----------------------------------------------------------------------------------------------------------------------
def drawAfterEndOfComparison(
JOINTS_TO_COMPARE,
JOINT_LABELS,
JOINT_PARENTS,
JOINT_PARENT_LABELS,
plt,ax,ax2,ax3,ax4,
xlineStart,xlineEnd,
ylineStart,ylineEnd,
zlineStart,zlineEnd,
ourPointCloud,
h36PointCloud,
frameID,
numberOfFrames,
everyNFrames,
disparity,
averageErrorDistances,
averageMotionEstimationDistancesBetweenFrames
):
plt.cla()
ax.cla()
ax2.cla()
ax3.cla()
ax4.cla()
#Print Skeletons and their connected lines..
#for i in range(0,len(xlineStart)):
# ax.plot([xlineStart[i],xlineEnd[i]],[ylineStart[i],ylineEnd[i]],zs=[zlineStart[i],zlineEnd[i]])
#--------------------------------------------
xs, ys, zs = pointListReturnXYZListForScatterPlot(ourPointCloud)
ax.scatter(xs, ys, zs)
xs, ys, zs = pointListReturnXYZListForScatterPlot(h36PointCloud)
ax.scatter(xs, ys, zs)
#Secondary plots for limb lengths etc..
numberOfJoints = len(ourPointCloud)
drawLimbDimensions(JOINTS_TO_COMPARE,JOINT_LABELS,JOINT_PARENTS,JOINT_PARENT_LABELS,h36PointCloud,ourPointCloud,numberOfJoints,ax2)
drawLimbError(JOINTS_TO_COMPARE,JOINT_LABELS,JOINT_PARENTS,JOINT_PARENT_LABELS,h36PointCloud,ourPointCloud,numberOfJoints,ax3)
drawFrameError(averageErrorDistances,averageMotionEstimationDistancesBetweenFrames,ax4)
#-------------------------
ax.text2D(0.05, 0.95, "Frame %u/%u - Increment %u - Procrustes Average Error %0.2f mm"%(frameID,numberOfFrames,everyNFrames,disparity) , transform=ax.transAxes)
#ax.text2D(0.05, 0.05, "RHand %0.2f mm / LHand %0.2f mm / RFoot %0.2f mm / LFoot %0.2f mm "%(currentDistances[4],currentDistances[7],currentDistances[11],currentDistances[14]) , transform=ax.transAxes)
#-------------------------
ax.set_xlim(auto=False,left=-600,right=300)
ax.set_ylim(auto=False,bottom=-1600,top=200)
ax.set_zlim(auto=False,bottom=2000,top=6000)
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
ax.set_zlabel('Z Axis')
#-------------------------
plt.show(block=False)
plt.savefig('p%05u.png'%frameID)
#fig.canvas.draw()
plt.pause(0.001)
@@ -0,0 +1,110 @@
#!/usr/bin/env python3
#Written by Ammar Qammaz a.k.a AmmarkoV - 2020
import numpy as np
#-----------------------------------------------------------------------------------------------------------------------
def writeCSVFileResults(
JOINT_LABELS,
outputFile,
addHeader,
globalJointDistances,
perJointDistance,
numberOfJoints,
subject,
action,
subaction,
camera,
actionLabel,
addedPixelNoise
):
#Write header----------------
if (addHeader):
file = open(outputFile,"w")
file.write("Subject,")
file.write("Action,")
file.write("ActionLabel,")
file.write("Subaction,")
file.write("Camera,")
file.write("Noise,")
file.write("Global_Median,")
#file.write("Global_Mean,")
file.write("Global_Average,")
file.write("Global_Std,")
file.write("Global_Var,")
for jointID in range(0,numberOfJoints):
file.write("%s_Median,"%JOINT_LABELS[jointID])
#file.write("%s_Mean,"%JOINT_LABELS[jointID])
file.write("%s_Average,"%JOINT_LABELS[jointID])
file.write("%s_Std,"%JOINT_LABELS[jointID])
file.write("%s_Var"%JOINT_LABELS[jointID])
if (jointID!=numberOfJoints-1):
file.write(",")
else:
file.write("\n")
else:
file = open(outputFile,"a")
#----------------------------
median=np.median(globalJointDistances)
mean=np.mean(globalJointDistances)
average=np.average(globalJointDistances)
std=np.std(globalJointDistances)
var=np.var(globalJointDistances)
print("\nGlobal Median:",median," Average:",average," Std:",std,"Var:",var) #file.write(subject)
file.write(subject)
file.write(",")
file.write(action)
file.write(",")
file.write(actionLabel)
file.write(",")
file.write(subaction)
file.write(",")
file.write(camera)
file.write(",")
file.write(str(addedPixelNoise))
file.write(",")
file.write(str(median))
file.write(",")
#file.write(str(mean))
#file.write(",")
file.write(str(average))
file.write(",")
file.write(str(std))
file.write(",")
file.write(str(var))
file.write(",")
for jointID in range(0,numberOfJoints):
median=np.median(perJointDistance[jointID])
mean=np.mean(perJointDistance[jointID])
average=np.average(perJointDistance[jointID])
std=np.std(perJointDistance[jointID])
var=np.var(perJointDistance[jointID])
print("Joint ",JOINT_LABELS[jointID]," Median:",median," Mean:",mean," Average:",average," Std:",std,"Var:",var)
file.write(str(median))
file.write(",")
#file.write(str(mean))
#file.write(",")
file.write(str(average))
file.write(",")
file.write(str(std))
file.write(",")
file.write(str(var))
if (jointID!=numberOfJoints-1):
file.write(",")
else:
file.write("\n")
file.close()
#--------------------------------------------
#-----------------------------------------------------------------------------------------------------------------------
def appendRAWResultsForGNUplot(outputFile,globalJointDistances):
fileHandler = open(outputFile, "a")
for measurement in globalJointDistances:
fileHandler.write(str(measurement))
fileHandler.write("\n")
fileHandler.close()
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
#gcc -c -fPIC c.c -o c.o
#gcc c.o -shared -o libcalci.so
gcc -shared -o libcalci.so -fPIC c.c
python3 p.py
exit 0
@@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdlib.h>
#include "c.h"
void connect()
{
printf("Connected to C extension...\n");
}
//return random value in range of 0-50
int randNum()
{
int nRand = rand() % 50;
return nRand;
}
//add two number and return value
int addNum(int a, int b)
{
int nAdd = a + b;
return nAdd;
}
int printFloatList(float * l,int lSize)
{
for (int i=0; i<lSize; i++)
{
printf("%u = %f\n",i,l[i]);
}
}
@@ -0,0 +1,8 @@
void connect();
//return random value in range of 0-50
int randNum();
//add two number and return value
int addNum(int a, int b);
Binary file not shown.
@@ -0,0 +1,21 @@
import ctypes
from ctypes import *
libCalc = CDLL("./libcalci.so")
#call C function to check connection
libCalc.connect()
#calling randNum() C function
#it returns random number
varRand = libCalc.randNum()
print("Random Number:", varRand, type(varRand))
#calling addNum() C function
#it returns addition of two numbers
varAdd = libCalc.addNum(20,30)
print("Addition : ", varAdd)
pyarr = [0.1, 0.2, 0.3, 0.4]
arr = (ctypes.c_float * len(pyarr))(*pyarr)
libCalc.printFloatList(arr,len(pyarr))
@@ -0,0 +1,43 @@
# import required module
import sys
import cv2
import numpy as np
from datetime import datetime
pathToDataset="/home/ammar/Documents/Datasets/ai_challenger"
filename = "%s/train/annotation.json" % pathToDataset
import json
with open(filename) as jsonData:
data = json.load(jsonData)
print (len(data))
print (data.keys())
if ( len(data['images']) != len(data['annotations']) ):
print("Mismatching image/annotation data")
sys.exit(0)
for imageID in range(0,len(data['images'])):
imageData=data['images'][imageID]
imageAnnotations=data['annotations'][imageID]
print(imageData)
loadImage=cv2.imread("%s/train/images/%s"%(pathToDataset,imageData['file_name']),-1)
#Draw Bounding Box
cv2.rectangle(loadImage, (imageAnnotations['bbox'][0],imageAnnotations['bbox'][1]),(imageAnnotations['bbox'][2],imageAnnotations['bbox'][3]), (255,255,255), 5)
radius = 5
color = (123,123,123)
for keypointID in range(0,int( len(imageAnnotations['keypoints'])/3 ) ):
cv2.circle(loadImage, (imageAnnotations['keypoints'][keypointID*3+0],imageAnnotations['keypoints'][keypointID*3+1]) , radius, color, -1)
cv2.imshow("Annotations", loadImage)
print(imageAnnotations)
cv2.waitKey(1000)
@@ -0,0 +1,36 @@
def readCListFromFile(filename,listName):
result=list()
fi = open(filename, "r")
Lines = fi.readlines()
print("readCListFromFile ",filename," ",listName)
appendIncomingLines=0
for line in Lines:
#Switch appending on and off
#-----------------------------
if (line.find(listName)!=-1):
appendIncomingLines=1
if (appendIncomingLines):
if (line.find("};")!=-1):
appendIncomingLines=0
break;
#-----------------------------
if (appendIncomingLines):
#print(line)
startOfString = line.find("\"")
endOfString = line.rfind("\"")
#print(startOfString)
#print(endOfString)
if ( (startOfString!=-1) and (endOfString!=-1) ):
label = line[startOfString+1:endOfString]
#The C Lists have an End of X element we detect it and discard it
if (label.find("End of")==-1 ):
#print(label)
result.append(label)
fi.close()
return result
@@ -0,0 +1,31 @@
To convert video files ready for use as input to MocapNET in a *relatively* easy way I have included a python converter that uses mediapipe/opencv to create the CSV files needed for MocapNET.
![MediaPipe Video 2 CSV utility](https://raw.githubusercontent.com/FORTH-ModelBasedTracker/MocapNET/master/doc/mediapipeConverter.jpg)
You can get mediapipe using this [src/python/mediapipe/setup.sh](https://github.com/FORTH-ModelBasedTracker/MocapNET/blob/master/src/python/mediapipe/setup.sh) script or by executing
```
pip install --user mediapipe opencv-python
```
The converter utility receives an input video stream and creates an output directory with all image frames and the CSV file with 2D joint estimations.
After going to the root directory of the project
```
python3 src/python/mediapipe/mediapipeHolistic2CSV.py --from shuffle.webm -o tester
```
After the conversion finishes you can process the generated "dataset" using MocapNET2CSV
```
./MocapNET2CSV --from tester-mpdata/2dJoints_mediapipe.csv --show 3
```
Due to the higher accuracy of [mediapipe holistic](https://google.github.io/mediapipe/solutions/holistic.html) (as well as inclusion of heads and hands which makes data forward compatible with the next versions of MocapNET) this might be a very useful tool to use in conjunction with MocapNET. In particular if you use this dumper be sure to checkout [MocapNET version 3](https://github.com/FORTH-ModelBasedTracker/MocapNET/tree/mnet3) that also supports hand pose estimation!
This is a python holistic mediapipe wrapper that can dump datasets in CSV files
https://ai.googleblog.com/2020/12/mediapipe-holistic-simultaneous-face.html
https://google.github.io/mediapipe/solutions/holistic
+59
View File
@@ -0,0 +1,59 @@
#!/usr/bin/python3
import os
import sys
import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
# For webcam input:
#pathToFiles='/media/ammar/CVRLDatasets/vae-hands-3d/RHD/RHD_published_v2/evaluation/color'
pathToFiles='/home/ammar/Documents/Datasets/RHD/images'
files=os.listdir(pathToFiles)
files.sort()
#Check everything ok
#print(files)
#sys.exit(0)
with mp_hands.Hands( min_detection_confidence=0.5, min_tracking_confidence=0.5, max_num_hands=1) as hands:
#for filename in files:
for i in range(0,2727):
filename='im%u.png'%i
fullPathToImageFile="%s/%s"%(pathToFiles,filename)
image = cv2.imread(fullPathToImageFile)
# Flip the image horizontally for a later selfie-view display, and convert
# the BGR image to RGB.
image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
results = hands.process(image)
# Draw the hand annotations on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_drawing.draw_landmarks(image,hand_landmarks,mp_hands.HAND_CONNECTIONS)
cv2.imshow('MediaPipe Hands', image)
if (results.multi_handedness!=None):
handedness = [ handedness.classification[0].label for handedness in results.multi_handedness ]
print(filename,",",handedness[0])
else:
#print(filename,",?")
key = cv2.waitKey(0)
#print(key)
if key==49 :
print(filename,",Left")
if key==48 :
print(filename,",Right")
if cv2.waitKey(1) & 0xFF == 27:
break
@@ -0,0 +1,50 @@
#!/usr/bin/python3
import cv2
import mediapipe as mp
import time
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
# For webcam input:
cap = cv2.VideoCapture(0)
with mp_hands.Hands( min_detection_confidence=0.5, min_tracking_confidence=0.5) as hands:
while cap.isOpened():
success, image = cap.read()
if not success:
print("Ignoring empty camera frame.")
# If loading a video, use 'break' instead of 'continue'.
continue
start = time.time()
# Flip the image horizontally for a later selfie-view display, and convert
# the BGR image to RGB.
image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
results = hands.process(image)
end = time.time()
# Time elapsed
seconds = end - start
#print ("Time taken : {0} seconds".format(seconds))
# Calculate frames per second
fps = 1 / seconds
print("{0} fps".format(fps))
# Draw the hand annotations on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_drawing.draw_landmarks(
image, hand_landmarks, mp_hands.HAND_CONNECTIONS)
cv2.imshow('MediaPipe Hands', image)
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()
@@ -0,0 +1,666 @@
def processPoseLandmarks(mnetPose2D,correctLabels,holisticPose):
itemNumber=0
if holisticPose is not None:
for item in holisticPose.landmark:
thisLandmarkName = correctLabels[itemNumber].lower()
if (thisLandmarkName!=''):
labelX = "2DX_"+thisLandmarkName
mnetPose2D[labelX]=1.0-item.x #Do Flip X
labelY = "2DY_"+thisLandmarkName
mnetPose2D[labelY]=item.y
labelV = "visible_"+thisLandmarkName
mnetPose2D[labelV]=item.visibility
#print("Joint ",thisLandmarkName,"(",itemNumber,") x=",item.x," y=",item.y," z=",item.z)
itemNumber = itemNumber +1
return mnetPose2D
def guessLandmarks(mnetPose2D):
if mnetPose2D is not None:
if ("2DX_rshoulder" in mnetPose2D) and ("2DY_rshoulder" in mnetPose2D) and ("visible_rshoulder" in mnetPose2D) and ("2DX_lshoulder" in mnetPose2D) and ("2DY_lshoulder" in mnetPose2D) and ("visible_lshoulder" in mnetPose2D) :
#---------------------------------------------
rX = float(mnetPose2D["2DX_rshoulder"])
rY = float(mnetPose2D["2DY_rshoulder"])
rV = float(mnetPose2D["visible_rshoulder"])
#---------------------------------------------
lX = float(mnetPose2D["2DX_lshoulder"])
lY = float(mnetPose2D["2DY_lshoulder"])
lV = float(mnetPose2D["visible_lshoulder"])
#---------------------------------------------
if (rV>0.0) and (lV>0.0):
mnetPose2D["2DX_neck"]=(rX+lX)/2
mnetPose2D["2DY_neck"]=(rY+lY)/2
mnetPose2D["visible_neck"]=(rV+lV)/2
#---------------------------------------------------
if ("2DX_rhip" in mnetPose2D) and ("2DY_rhip" in mnetPose2D) and ("visible_rhip" in mnetPose2D) and ("2DX_lhip" in mnetPose2D) and ("2DY_lhip" in mnetPose2D) and ("visible_lhip" in mnetPose2D) :
#---------------------------------------------
rX = float(mnetPose2D["2DX_rhip"])
rY = float(mnetPose2D["2DY_rhip"])
rV = float(mnetPose2D["visible_rhip"])
#---------------------------------------------
lX = float(mnetPose2D["2DX_lhip"])
lY = float(mnetPose2D["2DY_lhip"])
lV = float(mnetPose2D["visible_lhip"])
#---------------------------------------------
if (rV>0.0) and (lV>0.0):
mnetPose2D["2DX_hip"]=(rX+lX)/2
mnetPose2D["2DY_hip"]=(rY+lY)/2
mnetPose2D["visible_hip"]=(rV+lV)/2
#---------------------------------------------------
return mnetPose2D
#MocapNET list of expected inputs
#frameNumber,skeletonID,totalSkeletons,2DX_head,2DY_head,visible_head,2DX_neck,2DY_neck,visible_neck,2DX_rshoulder,2DY_rshoulder,visible_rshoulder,2DX_relbow,2DY_relbow,visible_relbow,2DX_rhand,2DY_rhand,visible_rhand,2DX_lshoulder,2DY_lshoulder,visible_lshoulder,2DX_lelbow,2DY_lelbow,visible_lelbow,2DX_lhand,2DY_lhand,visible_lhand,2DX_hip,2DY_hip,visible_hip,2DX_rhip,2DY_rhip,visible_rhip,2DX_rknee,2DY_rknee,visible_rknee,2DX_rfoot,2DY_rfoot,visible_rfoot,2DX_lhip,2DY_lhip,visible_lhip,2DX_lknee,2DY_lknee,visible_lknee,2DX_lfoot,2DY_lfoot,visible_lfoot,2DX_endsite_eye.r,2DY_endsite_eye.r,visible_endsite_eye.r,2DX_endsite_eye.l,2DY_endsite_eye.l,visible_endsite_eye.l,2DX_rear,2DY_rear,visible_rear,2DX_lear,2DY_lear,visible_lear,2DX_endsite_toe1-2.l,2DY_endsite_toe1-2.l,visible_endsite_toe1-2.l,2DX_endsite_toe5-3.l,2DY_endsite_toe5-3.l,visible_endsite_toe5-3.l,2DX_lheel,2DY_lheel,visible_lheel,2DX_endsite_toe1-2.r,2DY_endsite_toe1-2.r,visible_endsite_toe1-2.r,2DX_endsite_toe5-3.r,2DY_endsite_toe5-3.r,visible_endsite_toe5-3.r,2DX_rheel,2DY_rheel,visible_rheel,2DX_bkg,2DY_bkg,visible_bkg,
def getHolisticBodyNameList():
bn=list()
#---------------------------------------------------
bn.append("head") #0 - nose
bn.append("head_leye_0") #1 - left_eye_inner
bn.append("endsite_eye.l") #2 - left_eye
bn.append("head_leye_3") #3 - left_eye_outer
bn.append("head_reye_3") #4 - right_eye_inner
bn.append("endsite_eye.r") #5 - right_eye
bn.append("head_reye_0") #6 - right_eye_outer
bn.append("lear") #7 - left_ear
bn.append("rear") #8 - right_ear
bn.append("head_outmouth_0") #9 - mouth_left
bn.append("head_outmouth_6") #10 - mouth_right
bn.append("lshoulder") #11 - left_shoulder
bn.append("rshoulder") #12 - right_shoulder
bn.append("lelbow") #13 - left_elbow
bn.append("relbow") #14 - right_elbow
bn.append("lhand") #15 - left_wrist
bn.append("rhand") #16 - right_wrist
bn.append("left_hand_pinky_4") #17 - left_pinky
bn.append("right_hand_pinky_4")#18 - right_pinky
bn.append("left_hand_index_4") #19 - left_index
bn.append("right_hand_index_4")#20 - right_index
bn.append("left_hand_thumb_4") #21 - left_thumb
bn.append("right_hand_thumb_4")#22 - right_thumb
bn.append("lhip") #23 - left_hip
bn.append("rhip") #24 - right_hip
bn.append("lknee") #25 - left_knee
bn.append("rknee") #26 - right_knee
bn.append("lfoot") #27 - left_ankle
bn.append("rfoot") #28 - right_ankle
bn.append("lheel") #29 - left_heel
bn.append("rheel") #30 - right_heel
bn.append("endsite_toe1-2.l") #31 - left_foot_index
bn.append("endsite_toe1-2.r") #32 - right_foot_index
return bn
#---------------------------------------------------
#2DX_lhand,2DY_lhand,visible_lhand,2DX_lthumb,2DY_lthumb,visible_lthumb,2DX_finger1-2.l,2DY_finger1-2.l,visible_finger1-2.l,2DX_finger1-3.l,2DY_finger1-3.l,visible_finger1-3.l,2DX_endsite_finger1-3.l,2DY_endsite_finger1-3.l,visible_endsite_finger1-3.l,2DX_finger2-1.l,2DY_finger2-1.l,visible_finger2-1.l,2DX_finger2-2.l,2DY_finger2-2.l,visible_finger2-2.l,2DX_finger2-3.l,2DY_finger2-3.l,visible_finger2-3.l,2DX_endsite_finger2-3.l,2DY_endsite_finger2-3.l,visible_endsite_finger2-3.l,2DX_finger3-1.l,2DY_finger3-1.l,visible_finger3-1.l,2DX_finger3-2.l,2DY_finger3-2.l,visible_finger3-2.l,2DX_finger3-3.l,2DY_finger3-3.l,visible_finger3-3.l,2DX_endsite_finger3-3.l,2DY_endsite_finger3-3.l,visible_endsite_finger3-3.l,2DX_finger4-1.l,2DY_finger4-1.l,visible_finger4-1.l,2DX_finger4-2.l,2DY_finger4-2.l,visible_finger4-2.l,2DX_finger4-3.l,2DY_finger4-3.l,visible_finger4-3.l,2DX_endsite_finger4-3.l,2DY_endsite_finger4-3.l,visible_endsite_finger4-3.l,2DX_finger5-1.l,2DY_finger5-1.l,visible_finger5-1.l,2DX_finger5-2.l,2DY_finger5-2.l,visible_finger5-2.l,2DX_finger5-3.l,2DY_finger5-3.l,visible_finger5-3.l,2DX_endsite_finger5-3.l,2DY_endsite_finger5-3.l,visible_endsite_finger5-3.l
def getHolisticLHandNameList():
bn=list()
#---------------------------------------------------
bn.append("lhand") #0 - wrist
bn.append("lthumb") #1 - thumb_cmc
bn.append("finger1-2.l") #2 - thumb_mcp
bn.append("finger1-3.l") #3 - thumb_ip
bn.append("endsite_finger1-3.l") #4 - thumb_tip
bn.append("finger2-1.l") #5 - index_finger_mcp
bn.append("finger2-2.l") #6 - index_finger_pip
bn.append("finger2-3.l") #7 - index_finger_dip
bn.append("endsite_finger2-3.l") #8 - index_finger_tip
bn.append("finger3-1.l") #9 - middle_finger_mcp
bn.append("finger3-2.l") #10 - middle_finger_pip
bn.append("finger3-3.l") #11 - middle_finger_dip
bn.append("endsite_finger3-3.l") #12 - middle_finger_tip
bn.append("finger4-1.l") #13 - ring_finger_mcp
bn.append("finger4-2.l") #14 - ring_finger_pip
bn.append("finger4-3.l") #15 - ring_finger_dip
bn.append("endsite_finger4-3.l") #16 - ring_tip
bn.append("finger5-1.l") #17 - pinky_mcp
bn.append("finger5-2.l") #18 - pinky_pip
bn.append("finger5-3.l") #19 - pinky_dip
bn.append("endsite_finger5-3.l") #20 - pinky_tip
return bn
#---------------------------------------------------
#2DX_rhand,2DY_rhand,visible_rhand,2DX_rthumb,2DY_rthumb,visible_rthumb,2DX_finger1-2.r,2DY_finger1-2.r,visible_finger1-2.r,2DX_finger1-3.r,2DY_finger1-3.r,visible_finger1-3.r,2DX_endsite_finger1-3.r,2DY_endsite_finger1-3.r,visible_endsite_finger1-3.r,2DX_finger2-1.r,2DY_finger2-1.r,visible_finger2-1.r,2DX_finger2-2.r,2DY_finger2-2.r,visible_finger2-2.r,2DX_finger2-3.r,2DY_finger2-3.r,visible_finger2-3.r,2DX_endsite_finger2-3.r,2DY_endsite_finger2-3.r,visible_endsite_finger2-3.r,2DX_finger3-1.r,2DY_finger3-1.r,visible_finger3-1.r,2DX_finger3-2.r,2DY_finger3-2.r,visible_finger3-2.r,2DX_finger3-3.r,2DY_finger3-3.r,visible_finger3-3.r,2DX_endsite_finger3-3.r,2DY_endsite_finger3-3.r,visible_endsite_finger3-3.r,2DX_finger4-1.r,2DY_finger4-1.r,visible_finger4-1.r,2DX_finger4-2.r,2DY_finger4-2.r,visible_finger4-2.r,2DX_finger4-3.r,2DY_finger4-3.r,visible_finger4-3.r,2DX_endsite_finger4-3.r,2DY_endsite_finger4-3.r,visible_endsite_finger4-3.r,2DX_finger5-1.r,2DY_finger5-1.r,visible_finger5-1.r,2DX_finger5-2.r,2DY_finger5-2.r,visible_finger5-2.r,2DX_finger5-3.r,2DY_finger5-3.r,visible_finger5-3.r,2DX_endsite_finger5-3.r,2DY_endsite_finger5-3.r,visible_endsite_finger5-3.r
def getHolisticRHandNameList():
bn=list()
#---------------------------------------------------
bn.append("rhand") #0 - wrist
bn.append("rthumb") #1 - thumb_cmc
bn.append("finger1-2.r") #2 - thumb_mcp
bn.append("finger1-3.r") #3 - thumb_ip
bn.append("endsite_finger1-3.r") #4 - thumb_tip
bn.append("finger2-1.r") #5 - index_finger_mcp
bn.append("finger2-2.r") #6 - index_finger_pip
bn.append("finger2-3.r") #7 - index_finger_dip
bn.append("endsite_finger2-3.r") #8 - index_finger_tip
bn.append("finger3-1.r") #9 - middle_finger_mcp
bn.append("finger3-2.r") #10 - middle_finger_pip
bn.append("finger3-3.r") #11 - middle_finger_dip
bn.append("endsite_finger3-3.r") #12 - middle_finger_tip
bn.append("finger4-1.r") #13 - ring_finger_mcp
bn.append("finger4-2.r") #14 - ring_finger_pip
bn.append("finger4-3.r") #15 - ring_finger_dip
bn.append("endsite_finger4-3.r") #16 - ring_tip
bn.append("finger5-1.r") #17 - pinky_mcp
bn.append("finger5-2.r") #18 - pinky_pip
bn.append("finger5-3.r") #19 - pinky_dip
bn.append("endsite_finger5-3.r") #20 - pinky_tip
return bn
#---------------------------------------------------
#2DX_head_rchin_0,2DY_head_rchin_0,visible_head_rchin_0,2DX_head_rchin_1,2DY_head_rchin_1,visible_head_rchin_1,2DX_head_rchin_2,2DY_head_rchin_2,visible_head_rchin_2,2DX_head_rchin_3,2DY_head_rchin_3,visible_head_rchin_3,2DX_head_rchin_4,2DY_head_rchin_4,visible_head_rchin_4,2DX_head_rchin_5,2DY_head_rchin_5,visible_head_rchin_5,2DX_head_rchin_6,2DY_head_rchin_6,visible_head_rchin_6,2DX_head_rchin_7,2DY_head_rchin_7,visible_head_rchin_7,2DX_head_chin,2DY_head_chin,visible_head_chin,2DX_head_lchin_7,2DY_head_lchin_7,visible_head_lchin_7,2DX_head_lchin_6,2DY_head_lchin_6,visible_head_lchin_6,2DX_head_lchin_5,2DY_head_lchin_5,visible_head_lchin_5,2DX_head_lchin_4,2DY_head_lchin_4,visible_head_lchin_4,2DX_head_lchin_3,2DY_head_lchin_3,visible_head_lchin_3,2DX_head_lchin_2,2DY_head_lchin_2,visible_head_lchin_2,2DX_head_lchin_1,2DY_head_lchin_1,visible_head_lchin_1,2DX_head_lchin_0,2DY_head_lchin_0,visible_head_lchin_0,2DX_head_reyebrow_0,2DY_head_reyebrow_0,visible_head_reyebrow_0,2DX_head_reyebrow_1,2DY_head_reyebrow_1,visible_head_reyebrow_1,2DX_head_reyebrow_2,2DY_head_reyebrow_2,visible_head_reyebrow_2,2DX_head_reyebrow_3,2DY_head_reyebrow_3,visible_head_reyebrow_3,2DX_head_reyebrow_4,2DY_head_reyebrow_4,visible_head_reyebrow_4,2DX_head_leyebrow_4,2DY_head_leyebrow_4,visible_head_leyebrow_4,2DX_head_leyebrow_3,2DY_head_leyebrow_3,visible_head_leyebrow_3,2DX_head_leyebrow_2,2DY_head_leyebrow_2,visible_head_leyebrow_2,2DX_head_leyebrow_1,2DY_head_leyebrow_1,visible_head_leyebrow_1,2DX_head_leyebrow_0,2DY_head_leyebrow_0,visible_head_leyebrow_0,2DX_head_nosebone_0,2DY_head_nosebone_0,visible_head_nosebone_0,2DX_head_nosebone_1,2DY_head_nosebone_1,visible_head_nosebone_1,2DX_head_nosebone_2,2DY_head_nosebone_2,visible_head_nosebone_2,2DX_head_nosebone_3,2DY_head_nosebone_3,visible_head_nosebone_3,2DX_head_nostrills_0,2DY_head_nostrills_0,visible_head_nostrills_0,2DX_head_nostrills_1,2DY_head_nostrills_1,visible_head_nostrills_1,2DX_head_nostrills_2,2DY_head_nostrills_2,visible_head_nostrills_2,2DX_head_nostrills_3,2DY_head_nostrills_3,visible_head_nostrills_3,2DX_head_nostrills_4,2DY_head_nostrills_4,visible_head_nostrills_4,2DX_head_reye_0,2DY_head_reye_0,visible_head_reye_0,2DX_head_reye_1,2DY_head_reye_1,visible_head_reye_1,2DX_head_reye_2,2DY_head_reye_2,visible_head_reye_2,2DX_head_reye_3,2DY_head_reye_3,visible_head_reye_3,2DX_head_reye_4,2DY_head_reye_4,visible_head_reye_4,2DX_head_reye_5,2DY_head_reye_5,visible_head_reye_5,2DX_head_leye_0,2DY_head_leye_0,visible_head_leye_0,2DX_head_leye_1,2DY_head_leye_1,visible_head_leye_1,2DX_head_leye_2,2DY_head_leye_2,visible_head_leye_2,2DX_head_leye_3,2DY_head_leye_3,visible_head_leye_3,2DX_head_leye_4,2DY_head_leye_4,visible_head_leye_4,2DX_head_leye_5,2DY_head_leye_5,visible_head_leye_5,2DX_head_outmouth_0,2DY_head_outmouth_0,visible_head_outmouth_0,2DX_head_outmouth_1,2DY_head_outmouth_1,visible_head_outmouth_1,2DX_head_outmouth_2,2DY_head_outmouth_2,visible_head_outmouth_2,2DX_head_outmouth_3,2DY_head_outmouth_3,visible_head_outmouth_3,2DX_head_outmouth_4,2DY_head_outmouth_4,visible_head_outmouth_4,2DX_head_outmouth_5,2DY_head_outmouth_5,visible_head_outmouth_5,2DX_head_outmouth_6,2DY_head_outmouth_6,visible_head_outmouth_6,2DX_head_outmouth_7,2DY_head_outmouth_7,visible_head_outmouth_7,2DX_head_outmouth_8,2DY_head_outmouth_8,visible_head_outmouth_8,2DX_head_outmouth_9,2DY_head_outmouth_9,visible_head_outmouth_9,2DX_head_outmouth_10,2DY_head_outmouth_10,visible_head_outmouth_10,2DX_head_outmouth_11,2DY_head_outmouth_11,visible_head_outmouth_11,2DX_head_inmouth_0,2DY_head_inmouth_0,visible_head_inmouth_0,2DX_head_inmouth_1,2DY_head_inmouth_1,visible_head_inmouth_1,2DX_head_inmouth_2,2DY_head_inmouth_2,visible_head_inmouth_2,2DX_head_inmouth_3,2DY_head_inmouth_3,visible_head_inmouth_3,2DX_head_inmouth_4,2DY_head_inmouth_4,visible_head_inmouth_4,2DX_head_inmouth_5,2DY_head_inmouth_5,visible_head_inmouth_5,2DX_head_inmouth_6,2DY_head_inmouth_6,visible_head_inmouth_6,2DX_head_inmouth_7,2DY_head_inmouth_7,visible_head_inmouth_7,2DX_head_reye,2DY_head_reye,visible_head_reye,2DX_head_leye,2DY_head_leye,visible_head_leye
def getHolisticFaceNameList():
bn=list()
#---------------------------------------------------
bn.append("head_outmouth_3") #0 -
bn.append("head_nosebone_3") #1 -
bn.append("head_nostrills_2") #2 -
bn.append("") #3 -
bn.append("") #4 -
bn.append("head_nosebone_2") #5 -
bn.append("head_nosebone_1") #6 -
bn.append("") #7 -
bn.append("") #8 -
bn.append("") #9 -
bn.append("") #10 -
bn.append("") #11 -
bn.append("head_inmouth_2") #12 -
bn.append("") #13 -
bn.append("") #14 -
bn.append("head_inmouth_6") #15 -
bn.append("") #16 -
bn.append("head_outmouth_9") #17 -
bn.append("") #18 -
bn.append("") #19 -
bn.append("") #20 -
bn.append("") #21 -
bn.append("") #22 -
bn.append("") #23 -
bn.append("") #24 -
bn.append("") #25 -
bn.append("") #26 -
bn.append("head_outmouth_2") #27 -
bn.append("") #28 -
bn.append("") #29 -
bn.append("") #30 -
bn.append("") #31 -
bn.append("") #32 -
bn.append("head_reye_0") #33 -
bn.append("") #34 -
bn.append("") #35 -
bn.append("") #36 -
bn.append("") #37 -
bn.append("") #38 -
bn.append("") #39 -
bn.append("head_outmouth_1") #40 -
bn.append("head_inmouth_1") #41 -
bn.append("") #42 -
bn.append("") #43 -
bn.append("") #44 -
bn.append("") #45 -
bn.append("") #46 -
bn.append("") #47 -
bn.append("") #48 -
bn.append("") #49 -
bn.append("") #50 -
bn.append("") #51 -
bn.append("") #52 -
bn.append("") #53 -
bn.append("") #54 -
bn.append("head_reyebrow_4") #55 -
bn.append("") #56 -
bn.append("") #57 -
bn.append("") #58 -
bn.append("") #59 -
bn.append("") #60 -
bn.append("head_outmouth_0") #61 -
bn.append("") #62 -
bn.append("head_reyebrow_1") #63 -
bn.append("") #64 -
bn.append("") #65 -
bn.append("head_reyebrow_3") #66 -
bn.append("") #67 -
bn.append("") #68 -
bn.append("") #69 -
bn.append("head_reyebrow_0") #70 -
bn.append("") #71 -
bn.append("") #72 -
bn.append("") #73 -
bn.append("") #74 -
bn.append("") #75 -
bn.append("") #76 -
bn.append("") #77 -
bn.append("head_inmouth_0") #78 -
bn.append("") #79 -
bn.append("") #80 -
bn.append("") #81 -
bn.append("") #82 -
bn.append("") #83 -
bn.append("head_outmouth_10") #84 -
bn.append("") #85 -
bn.append("") #86 -
bn.append("") #87 -
bn.append("") #88 -
bn.append("") #89 -
bn.append("") #90 -
bn.append("head_outmouth_11") #91 -
bn.append("") #92 -
bn.append("") #93 -
bn.append("") #94 -
bn.append("") #95 -
bn.append("") #96 -
bn.append("head_nostrills_1") #97 -
bn.append("head_nostrills_0") #98 -
bn.append("") #99 -
bn.append("") #100 -
bn.append("") #101 -
bn.append("") #102 -
bn.append("") #103 -
bn.append("") #104 -
bn.append("head_reyebrow_2") #105 -
bn.append("") #106 -
bn.append("") #107 -
bn.append("") #108 -
bn.append("") #109 -
bn.append("") #110 -
bn.append("") #111 -
bn.append("") #112 -
bn.append("") #113 -
bn.append("") #114 -
bn.append("") #115 -
bn.append("head_rchin_1") #116 -
bn.append("") #117 -
bn.append("") #118 -
bn.append("") #119 -
bn.append("") #120 -
bn.append("") #121 -
bn.append("") #122 -
bn.append("") #123 -
bn.append("") #124 -
bn.append("") #125 -
bn.append("") #126 -
bn.append("") #127 -
bn.append("") #128 -
bn.append("") #129 -
bn.append("") #130 -
bn.append("") #131 -
bn.append("") #132 -
bn.append("head_reye_3") #133 -
bn.append("") #134 -
bn.append("") #135 -
bn.append("") #136 -
bn.append("") #137 -
bn.append("") #138 -
bn.append("") #139 -
bn.append("") #140 -
bn.append("") #141 -
bn.append("") #142 -
bn.append("head_rchin_0") #143 -
bn.append("head_reye_4") #144 -
bn.append("") #145 -
bn.append("") #146 -
bn.append("head_rchin_2") #147 -
bn.append("head_rchin_7") #148 -
bn.append("") #149 -
bn.append("") #150 -
bn.append("") #151 -
bn.append("head_chin") #152 -
bn.append("head_reye_4") #153 -
bn.append("") #154 -
bn.append("") #155 -
bn.append("") #156 -
bn.append("") #157 -
bn.append("head_reye_2") #158 -
bn.append("") #159 -
bn.append("head_reye_1") #160 -
bn.append("") #161 -
bn.append("") #162 -
bn.append("") #163 -
bn.append("") #164 -
bn.append("") #165 -
bn.append("") #166 -
bn.append("") #167 -
bn.append("head_nosebone_0") #168 -
bn.append("") #169 -
bn.append("head_rchin_5") #170 -
bn.append("") #171 -
bn.append("") #172 -
bn.append("") #173 -
bn.append("") #174 -
bn.append("") #175 -
bn.append("head_rchin_6") #176 -
bn.append("") #177 -
bn.append("") #178 -
bn.append("head_inmouth_7") #179 -
bn.append("") #180 -
bn.append("") #181 -
bn.append("") #182 -
bn.append("") #183 -
bn.append("") #184 -
bn.append("") #185 -
bn.append("") #186 -
bn.append("") #187 -
bn.append("") #188 -
bn.append("") #189 -
bn.append("") #190 -
bn.append("") #191 -
bn.append("head_rchin_3") #192 -
bn.append("") #193 -
bn.append("") #194 -
bn.append("") #195 -
bn.append("") #196 -
bn.append("head_nosebone_2") #197 -
bn.append("") #198 -
bn.append("") #199 -
bn.append("") #200 -
bn.append("") #201 -
bn.append("") #202 -
bn.append("") #203 -
bn.append("") #204 -
bn.append("") #205 -
bn.append("") #206 -
bn.append("") #207 -
bn.append("") #208 -
bn.append("") #209 -
bn.append("head_rchin_4") #210 -
bn.append("") #211 -
bn.append("") #212 -
bn.append("") #213 -
bn.append("") #214 -
bn.append("") #215 -
bn.append("") #216 -
bn.append("") #217 -
bn.append("") #218 -
bn.append("") #219 -
bn.append("") #220 -
bn.append("") #221 -
bn.append("") #222 -
bn.append("") #223 -
bn.append("") #224 -
bn.append("") #225 -
bn.append("") #226 -
bn.append("") #227 -
bn.append("") #228 -
bn.append("") #229 -
bn.append("") #230 -
bn.append("") #231 -
bn.append("") #232 -
bn.append("") #233 -
bn.append("") #234 -
bn.append("") #235 -
bn.append("") #236 -
bn.append("") #237 -
bn.append("") #238 -
bn.append("") #239 -
bn.append("") #240 -
bn.append("") #241 -
bn.append("") #242 -
bn.append("") #243 -
bn.append("") #244 -
bn.append("") #245 -
bn.append("") #246 -
bn.append("") #247 -
bn.append("") #248 -
bn.append("") #249 -
bn.append("") #250 -
bn.append("") #251 -
bn.append("") #252 -
bn.append("head_leye_4") #253 -
bn.append("") #254 -
bn.append("") #255 -
bn.append("head_leye_5") #256 -
bn.append("") #257 -
bn.append("") #258 -
bn.append("") #259 -
bn.append("") #260 -
bn.append("") #261 -
bn.append("") #262 -
bn.append("head_leye_3") #263 -
bn.append("") #264 -
bn.append("head_lchin_0") #265 -
bn.append("") #266 -
bn.append("head_outmouth_4") #267 -
bn.append("") #268 -
bn.append("") #269 -
bn.append("") #270 -
bn.append("head_inmouth_3") #271 -
bn.append("") #272 -
bn.append("") #273 -
bn.append("") #274 -
bn.append("") #275 -
bn.append("head_leyebrow_0") #276 -
bn.append("") #277 -
bn.append("") #278 -
bn.append("") #279 -
bn.append("") #280 -
bn.append("") #281 -
bn.append("") #282 -
bn.append("") #283 -
bn.append("") #284 -
bn.append("head_leyebrow_4") #285 -
bn.append("") #286 -
bn.append("") #287 -
bn.append("") #288 -
bn.append("") #289 -
bn.append("") #290 -
bn.append("head_outmouth_6") #291 -
bn.append("") #292 -
bn.append("head_leyebrow_1") #293 -
bn.append("") #294 -
bn.append("") #295 -
bn.append("head_leyebrow_3") #296 -
bn.append("") #297 -
bn.append("") #298 -
bn.append("") #299 -
bn.append("") #300 -
bn.append("") #301 -
bn.append("") #302 -
bn.append("") #303 -
bn.append("") #304 -
bn.append("") #305 -
bn.append("") #306 -
bn.append("") #307 -
bn.append("head_inmouth_4") #308 -
bn.append("") #309 -
bn.append("") #310 -
bn.append("") #311 -
bn.append("") #312 -
bn.append("") #313 -
bn.append("head_outmouth_8") #314 -
bn.append("") #315 -
bn.append("") #316 -
bn.append("") #317 -
bn.append("") #318 -
bn.append("") #319 -
bn.append("") #320 -
bn.append("") #321 -
bn.append("") #322 -
bn.append("") #323 -
bn.append("") #324 -
bn.append("") #325 -
bn.append("head_nostrills_3") #326 -
bn.append("head_nostrills_4") #327 -
bn.append("") #328 -
bn.append("") #329 -
bn.append("") #330 -
bn.append("") #331 -
bn.append("") #332 -
bn.append("") #333 -
bn.append("head_leyebrow_2") #334 -
bn.append("") #335 -
bn.append("") #336 -
bn.append("") #337 -
bn.append("") #338 -
bn.append("") #339 -
bn.append("") #340 -
bn.append("") #341 -
bn.append("") #342 -
bn.append("") #343 -
bn.append("") #344 -
bn.append("") #345 -
bn.append("Head_LChin_1") #346 -
bn.append("") #347 -
bn.append("") #348 -
bn.append("") #349 -
bn.append("") #350 -
bn.append("") #351 -
bn.append("") #352 -
bn.append("") #353 -
bn.append("") #354 -
bn.append("") #355 -
bn.append("") #356 -
bn.append("") #357 -
bn.append("") #358 -
bn.append("") #359 -
bn.append("") #360 -
bn.append("") #361 -
bn.append("head_leye_0") #362 -
bn.append("") #363 -
bn.append("") #364 -
bn.append("") #365 -
bn.append("") #366 -
bn.append("") #367 -
bn.append("") #368 -
bn.append("") #369 -
bn.append("") #370 -
bn.append("") #371 -
bn.append("") #372 -
bn.append("") #373 -
bn.append("") #374 -
bn.append("") #375 -
bn.append("head_lchin_2") #376 -
bn.append("head_lchin_7") #377 -
bn.append("") #378 -
bn.append("") #379 -
bn.append("") #380 -
bn.append("") #381 -
bn.append("") #382 -
bn.append("") #383 -
bn.append("head_leye_1") #384 -
bn.append("") #385 -
bn.append("head_leye_2") #386 -
bn.append("") #387 -
bn.append("") #388 -
bn.append("") #389 -
bn.append("") #390 -
bn.append("") #391 -
bn.append("") #392 -
bn.append("") #393 -
bn.append("") #394 -
bn.append("head_lchin_5") #395 -
bn.append("") #396 -
bn.append("") #397 -
bn.append("") #398 -
bn.append("") #399 -
bn.append("head_lchin_6") #400 -
bn.append("") #401 -
bn.append("") #402 -
bn.append("head_inmouth_5") #403 -
bn.append("") #404 -
bn.append("head_outmouth_7") #405 -
bn.append("") #406 -
bn.append("") #407 -
bn.append("") #408 -
bn.append("") #409 -
bn.append("") #410 -
bn.append("") #411 -
bn.append("") #412 -
bn.append("") #413 -
bn.append("") #414 -
bn.append("") #415 -
bn.append("head_lchin_3") #416 -
bn.append("") #417 -
bn.append("") #418 -
bn.append("") #419 -
bn.append("") #420 -
bn.append("") #421 -
bn.append("") #422 -
bn.append("") #423 -
bn.append("") #424 -
bn.append("") #425 -
bn.append("") #426 -
bn.append("") #427 -
bn.append("") #428 -
bn.append("") #429 -
bn.append("head_lchin_4") #430 -
bn.append("") #431 -
bn.append("") #432 -
bn.append("") #433 -
bn.append("") #434 -
bn.append("") #435 -
bn.append("") #436 -
bn.append("") #437 -
bn.append("") #438 -
bn.append("") #439 -
bn.append("") #440 -
bn.append("") #441 -
bn.append("") #442 -
bn.append("") #443 -
bn.append("") #444 -
bn.append("") #445 -
bn.append("") #446 -
bn.append("") #447 -
bn.append("") #448 -
bn.append("") #449 -
bn.append("") #450 -
bn.append("") #451 -
bn.append("") #452 -
bn.append("") #453 -
bn.append("") #454 -
bn.append("") #455 -
bn.append("") #456 -
bn.append("") #457 -
bn.append("") #458 -
bn.append("") #459 -
bn.append("") #460 -
bn.append("") #461 -
bn.append("") #462 -
bn.append("") #463 -
bn.append("") #464 -
bn.append("") #465 -
bn.append("") #466 -
bn.append("") #467 -
bn.append("") #468 -
bn.append("") #469 -
bn.append("") #470 -
bn.append("") #471 -
bn.append("") #472 -
bn.append("") #473 -
bn.append("") #474 -
bn.append("") #475 -
bn.append("") #476 -
bn.append("") #477 -
bn.append("") #478 -
bn.append("") #479 -
bn.append("") #480 -
bn.append("") #481 -
bn.append("") #482 -
bn.append("") #483 -
bn.append("") #484 -
bn.append("") #485 -
bn.append("") #486 -
return bn
#---------------------------------------------------
@@ -0,0 +1,59 @@
#!/usr/bin/python3
import cv2
import mediapipe as mp
import time
mp_drawing = mp.solutions.drawing_utils
mp_holistic = mp.solutions.holistic
# For webcam input:
cap = cv2.VideoCapture(0)
with mp_holistic.Holistic(static_image_mode=True) as holistic:
while cap.isOpened():
success, image = cap.read()
if not success:
print("Ignoring empty camera frame.")
# If loading a video, use 'break' instead of 'continue'.
continue
start = time.time()
# Flip the image horizontally for a later selfie-view display, and convert
# the BGR image to RGB.
image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
results = holistic.process(image)
# Draw the hand annotations on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
end = time.time()
# Time elapsed
seconds = end - start
# Calculate frames per second
fps = 1 / seconds
print("\r Framerate : ",round(fps,2)," fps \r", end="", flush=True)
annotated_image = image.copy()
#Compensate for name mediapipe change..
try:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACEMESH_TESSELATION) #This used to be called FACE_CONNECTIONS
except:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACE_CONNECTIONS) #This used to be called FACE_CONNECTIONS
mp_drawing.draw_landmarks(annotated_image, results.left_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
mp_drawing.draw_landmarks(annotated_image, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
# Use mp_holistic.UPPER_BODY_POSE_CONNECTIONS for drawing below when
# upper_body_only is set to True.
mp_drawing.draw_landmarks(annotated_image, results.pose_landmarks, mp_holistic.POSE_CONNECTIONS)
cv2.imshow('MediaPipe Holistic', annotated_image)
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

@@ -0,0 +1,232 @@
#!/usr/bin/python3
import cv2
import mediapipe as mp
import time
import os
import sys
from tools import checkIfFileExists,createDirectory
#Get drawing/holistic
mp_drawing = mp.solutions.drawing_utils
mp_holistic = mp.solutions.holistic
#I have added a seperate list with the joints
from holisticPartNames import getHolisticBodyNameList, getHolisticFaceNameList, processPoseLandmarks, guessLandmarks
MEDIAPIPE_POSE_LANDMARK_NAMES=getHolisticBodyNameList()
MEDIAPIPE_FACE_LANDMARK_NAMES=getHolisticFaceNameList()
#In an attempt to reduce the upkeep of this codebase as much as possible
#the python code parses directly the C defines to get the order of joints
#sorry about that but I am just one person maintaining all of this code :P
#this also means you need to run the python script from the root directory of the repository!
from C_Parser import readCListFromFile
headNames = readCListFromFile("src/MocapNET2/MocapNETLib2/IO/commonSkeleton.hpp","HeadNames[]")
leftHandNames = readCListFromFile("src/MocapNET2/MocapNETLib2/IO/commonSkeleton.hpp","COCOLeftHandNames[]")
rightHandNames = readCListFromFile("src/MocapNET2/MocapNETLib2/IO/commonSkeleton.hpp","COCORightHandNames[]")
body25BodyNames = readCListFromFile("src/MocapNET2/MocapNETLib2/IO/commonSkeleton.hpp","Body25BodyNames[]")
#---------------------------------------------------------------------------
def appendListOf2DXY(fo,listToUse):
firstElement=0
for element in listToUse:
if (element.find("End of")==-1 ):
if (firstElement==0):
firstElement=1
else:
fo.write(",")
elementLowercased=element.lower()
fo.write("2DX_")
fo.write(elementLowercased)
fo.write(",2DY_")
fo.write(elementLowercased)
fo.write(",visible_")
fo.write(elementLowercased)
def appendValuesOfListOf2DXY(fo,listToUse,values):
itemNumber=0
for element in listToUse:
if (element.find("End of")==-1 ):
thisLandmarkName = listToUse[itemNumber].lower()
labelX = "2DX_"+thisLandmarkName
labelY = "2DY_"+thisLandmarkName
labelV = "visible_"+thisLandmarkName
#--------------------------------
fo.write(",")
if labelX in values:
fo.write(str(values[labelX]))
else:
fo.write("0.0")
#--------------------------------
fo.write(",")
if labelY in values:
fo.write(str(values[labelY]))
else:
fo.write("0.0")
#--------------------------------
fo.write(",")
if labelV in values:
fo.write(str(values[labelV]))
else:
fo.write("0.0")
#--------------------------------
itemNumber=itemNumber+1
def appendZerosForListOf2DXY(fo,listToUse):
for element in listToUse:
if (element.find("End of")==-1 ):
elementLowercased=element.lower()
fo.write(",0,0,0")
def drawListNumbers(image,lst):
font = cv2.FONT_HERSHEY_SIMPLEX
org = (50, 50)
fontScale = 1
color = (255, 0, 0)
thickness = 2
cv2.putText(image, 'Parsing dataset through MediaPipe Holistic', org, font, fontScale, color, thickness, cv2.LINE_AA)
itemNumber=0
#for item in lst['landmark']:
if lst is not None:
for item in lst.landmark:
org = ( int(item.x * image.shape[1]) , int(item.y * image.shape[0]) )
cv2.putText(image, '%u'%(itemNumber), org, font, fontScale, color, thickness, cv2.LINE_AA)
itemNumber = itemNumber +1
def convertStreamToMocapNETCSV():
videoFilePath ="shuffle.webm"
outputDatasetPath="frames/shuffle.webm"
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--from"):
videoFilePath=sys.argv[i+1]
if (sys.argv[i]=="-o"):
outputDatasetPath=sys.argv[i+1]
#Strip last character of output path if it is a /
if ( outputDatasetPath[len(outputDatasetPath)-1] == '/' ):
outputDatasetPath = outputDatasetPath[:-1]
#We append an -mpdata to make sure this is different from the OpenPose output
outputDatasetPath=outputDatasetPath+"-mpdata"
#Make sure output path exists..
createDirectory(outputDatasetPath)
fo = open("%s/2dJoints_mediapipe.csv" % (outputDatasetPath), "w")
#//Generate CSV header..
fo.write("frameNumber,skeletonID,totalSkeletons,")
appendListOf2DXY(fo,body25BodyNames)
fo.write(",")
appendListOf2DXY(fo,leftHandNames)
fo.write(",")
appendListOf2DXY(fo,rightHandNames)
fo.write(",")
appendListOf2DXY(fo,headNames)
fo.write("\n")
maxFailedFrames = 100
failedFrames = 0
frameNumber = 0
# For webcam input:
cap = cv2.VideoCapture(videoFilePath)
with mp_holistic.Holistic(static_image_mode=True) as holistic:
while cap.isOpened():
success, image = cap.read()
if not success:
print("\rIgnoring empty camera frame. ",failedFrames,"/",maxFailedFrames,"\r", end="", flush=True)
failedFrames = failedFrames + 1
# If loading a video, use 'break' instead of 'continue'.
if (failedFrames>100):
break
else:
failedFrames = 0
cv2.imwrite("%s/colorFrame_0_%05u.jpg"%(outputDatasetPath,frameNumber), image)
start = time.time()
# Flip the image horizontally for a later selfie-view display, and convert
# the BGR image to RGB.
image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
results = holistic.process(image)
# Draw the hand annotations on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
end = time.time()
# Time elapsed
seconds = end - start
# Calculate frames per second
fps = 1 / seconds
print("\r Frame : ",frameNumber," | ",round(fps,2)," fps \r", end="", flush=True)
annotated_image = image.copy()
#Compensate for name mediapipe change..
try:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACEMESH_TESSELATION) #This used to be called FACE_CONNECTIONS
except:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACE_CONNECTIONS) #This used to be called FACE_CONNECTIONS
mp_drawing.draw_landmarks(annotated_image, results.left_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
mp_drawing.draw_landmarks(annotated_image, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
# Use mp_holistic.UPPER_BODY_POSE_CONNECTIONS for drawing below when upper_body_only is set to True.
mp_drawing.draw_landmarks(annotated_image, results.pose_landmarks, mp_holistic.POSE_CONNECTIONS)
#Draw visualization of 2D joints!
drawListNumbers(annotated_image,results.pose_landmarks)
mnetPose2D = dict()
#------------------------------------------------------------------------------------
processPoseLandmarks(mnetPose2D,MEDIAPIPE_POSE_LANDMARK_NAMES,results.pose_landmarks)
processPoseLandmarks(mnetPose2D,leftHandNames ,results.left_hand_landmarks)
processPoseLandmarks(mnetPose2D,rightHandNames ,results.right_hand_landmarks)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_FACE_LANDMARK_NAMES,results.face_landmarks)
#------------------------------------------------------------------------------------
guessLandmarks(mnetPose2D) #Some landmarks ( neck, hip need to be guessed by others )
skeletonID = 0
totalSkeletons = 1
#Write this CSV record -------------------------------------
fo.write("%u,%u,%u,"%(frameNumber,skeletonID,totalSkeletons))
appendValuesOfListOf2DXY(fo,body25BodyNames,mnetPose2D)
appendValuesOfListOf2DXY(fo,leftHandNames ,mnetPose2D)
appendValuesOfListOf2DXY(fo,rightHandNames ,mnetPose2D)
appendValuesOfListOf2DXY(fo,headNames ,mnetPose2D)
fo.write("\n")
#-----------------------------------------------------------
#Done with frame -------------------------------------
frameNumber = frameNumber + 1
#Show visualization frame -------------------------------------
cv2.imshow('MediaPipe Holistic', annotated_image)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
fo.close()
print("Done dumping to CSV using mediapipe")
print(" try running with MocapNET using : ")
print(" ./MocapNET2CSV --from %s/2dJoints_mediapipe.csv --show 3 --hands" % (outputDatasetPath))
if __name__ == '__main__':
convertStreamToMocapNETCSV()
Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

+12
View File
@@ -0,0 +1,12 @@
python3 -m venv mp_env
source mp_env/bin/activate
#For RPI4
#sudo apt install libxcb-shm0 libcdio-paranoia-dev libsdl2-2.0-0 libxv1 libtheora0 libva-drm2 libva-x11-2 libvdpau1 libharfbuzz0b libbluray2 libatlas-base-dev libhdf5-103 libgtk-3-0 libdc1394-22 libopenexr23
#pip install mediapipe-rpi4 opencv-python
#For Regular x86_64
python3 -m pip install mediapipe opencv-python
python3 holisticWebcam.py
@@ -0,0 +1,8 @@
import os
def checkIfFileExists(filename):
return os.path.isfile(filename)
def createDirectory(path):
if not os.path.exists(path):
os.makedirs(path)
File diff suppressed because it is too large Load Diff
+177
View File
@@ -0,0 +1,177 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
#--------------------------------------------------------------
#--------------------------------------------------------------
#--------------------------------------------------------------
def pruneModel(model,trainIn,trainOut):
print("Will now attempt to optimize model..!")
import tensorflow as tf
import tensorflow_model_optimization as tfmot
initial_sparsity = 0.0
final_sparsity = 0.75
begin_step = 1000
end_step = 5000
pruning_params = {
'pruning_schedule': tfmot.sparsity.keras.PolynomialDecay(
initial_sparsity=initial_sparsity,
final_sparsity=final_sparsity,
begin_step=begin_step,
end_step=end_step
),
'BatchNormalization': []
}
model = tfmot.sparsity.keras.prune_low_magnitude(model, **pruning_params)
pruning_callback = tfmot.sparsity.keras.UpdatePruningStep()
model.compile(optimizer='rmsprop', loss='mse', metrics=['mae', 'acc'])
model.fit(
trainIn,
trainOut,
epochs=200,
batch_size=1024,
callbacks= pruning_callback,
verbose=1
)
return model
#--------------------------------------------------------------
#--------------------------------------------------------------
#--------------------------------------------------------------
def clusterModel(model,configuration,trainIn,trainOut):
#https://blog.tensorflow.org/2020/08/tensorflow-model-optimization-toolkit-weight-clustering-api.html
print("Will now attempt to cluster model..!")
import tensorflow as tf
import tensorflow_model_optimization as tfmot
rmsprop=tf.keras.optimizers.RMSprop(learning_rate=configuration['learningRate'], rho=0.9, epsilon=tf.keras.backend.epsilon())
model.compile(
optimizer=rmsprop,
loss='mse',
metrics=['mae', 'acc']
)
cluster_weights = tfmot.clustering.keras.cluster_weights
clustering_params = {
'number_of_clusters': 32,
'cluster_centroids_init': tfmot.clustering.keras.CentroidInitialization.LINEAR
}
clustered_model = cluster_weights(model, **clustering_params)
clustered_model.compile(
optimizer=rmsprop,
loss='mse',
metrics=['mae', 'acc']
)
clustered_model.fit(
trainIn,
trainOut,
epochs=200,
batch_size=1024,
verbose=1
)
# Prepare model for serving by removing training-only variables.
return tfmot.clustering.keras.strip_clustering(clustered_model)
#--------------------------------------------------------------
#--------------------------------------------------------------
#--------------------------------------------------------------
def quantizeModel(model,trainIn,trainOut):
print("Will now attempt to quantize model..!")
import tensorflow as tf
import tensorflow_model_optimization as tfmot
quantize_model = tfmot.quantization.keras.quantize_model
# q_aware stands for for quantization aware.
q_aware_model = quantize_model(model)
# `quantize_model` requires a recompile.
q_aware_model.compile(optimizer='rmsprop', loss='mse', metrics=['mae', 'acc'])
q_aware_model.fit(
trainIn,
trainOut,
epochs=1,
batch_size=500,
verbose=1,
validation_split=0.1
)
q_aware_model.summary()
return q_aware_model
#--------------------------------------------------------------
#--------------------------------------------------------------
#--------------------------------------------------------------
def convertToTensorRT(model,trainIn=0,precision="fp32"):
try:
import os
import sys
import tensorflow as tf
from tensorflow.python.compiler.tensorrt import trt_convert as trt
print("Convert Model to TensorRT / ",precision)
#-----------------------------------------------------------------
os.system("rm -rf tensorRTIntermediateTFModel/")
os.system("rm -rf tensorRTIntermediateTRTModel/")
#-----------------------------------------------------------------
model.save("tensorRTIntermediateTFModel", save_format='tf') #save directory..
if (precision=="fp32"):
precision_mode='FP32'
elif (precision=="fp16"):
precision_mode='FP16'
elif (precision=="int8"):
precision_mode='INT8'
else:
print("Unknown precision setting ",precision)
return model
# https://www.tensorflow.org/api_docs/python/tf/experimental/tensorrt/Converter
# https://docs.nvidia.com/deeplearning/frameworks/tf-trt-user-guide/index.html#usage-example
print("\nConverting to TensorRT/Tensorflow model")
converter = trt.TrtGraphConverterV2( input_saved_model_dir="tensorRTIntermediateTFModel", precision_mode=precision_mode )
#with trt.Builder(TRT_LOGGER) as builder, builder.create_network(network_creation_flag) as network, trt.OnnxParser(network, TRT_LOGGER) as parser, builder.create_builder_config() as config:
# profile = builder.create_optimization_profile()
# profile.set_shape("input_1", (1, 224, 224, 3), (1, 224, 224, 3), (1, 224, 224, 3))
# config.add_optimization_profile(profile)
# engine = builder.build_engine(network, config)
print("\nconverter.convert")
if (trainIn!=0):
converter.convert(calibration_input_fn=trainIn)
converter.build(input_fn=trainIn)
else:
converter.convert()
print("\nconverter.save")
converter.save("tensorRTIntermediateTRTModel")
model = tf.keras.models.load_model("tensorRTIntermediateTRTModel")
os.system("rm -rf tensorRTIntermediateTFModel/")
os.system("rm -rf tensorRTIntermediateTRTModel/")
except:
print("Error while performing TensorRT conversion")
return model
#--------------------------------------------------------------
#--------------------------------------------------------------
#--------------------------------------------------------------
if __name__ == '__main__':
print("DNNOptimize.py is a library and cannot be run on it's own")
+738
View File
@@ -0,0 +1,738 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import os
import sys
import gc
import time
import json
import tensorflow as tf
from tensorflow import keras
#from tensorflow.keras.backend.tensorflow_backend import set_session
#from tensorflow.keras import backend as K
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.models import Sequential
from tensorflow.keras.models import model_from_json
from tensorflow.keras.utils import plot_model
import tensorflow.keras.callbacks
import numpy as np
from numba import njit #Test
from tools import bcolors,checkIfFileExists
def printTrainingVersion():
print("""
███╗ ███╗ ██████╗ ██████╗ █████╗ ██████╗ ███╗ ██╗███████╗████████╗
████╗ ████║██╔═══██╗██╔════╝██╔══██╗██╔══██╗████╗ ██║██╔════╝╚══██╔══╝
██╔████╔██║██║ ██║██║ ███████║██████╔╝██╔██╗ ██║█████╗ ██║
██║╚██╔╝██║██║ ██║██║ ██╔══██║██╔═══╝ ██║╚██╗██║██╔══╝ ██║
██║ ╚═╝ ██║╚██████╔╝╚██████╗██║ ██║██║ ██║ ╚████║███████╗ ██║
╚═╝ ╚═╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝
""")
#-----------------------------
#BMVC 21 paper was submitted with Keras 2.2.4/Tensorflow 1.14/Numpy 1.16.2
#-----------------------------
print("")
print("Tensorflow version : ",tf.__version__)
#print("Keras version : ",keras.__version__) <- no longer available in TF-2.13
print("Numpy version : ",np.__version__)
#-----------------------------
from tensorflow.python.platform import build_info as tf_build_info
print("TF/CUDA version : ",tf_build_info.build_info['cuda_version'])
print("TF/CUDNN version : ",tf_build_info.build_info['cudnn_version'])
#-----------------------------
print("")
#-----------------------------
def forceCPU():
print(bcolors.WARNING,"User selected to use CPU mode",bcolors.ENDC)
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" # see issue #152
os.environ["CUDA_VISIBLE_DEVICES"] = ""
def limitGPUMemory():
print("Limiting GPU memory usage for multiple instances..\n")
config = tf.compat.v1.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.2
config.gpu_options.visible_device_list = "0"
set_session(tf.compat.v1.Session(config=config))
def setTensorflowBackendToHalfFloats():
dtype='float16'
#WARNING:tensorflow:Mixed precision compatibility check (mixed_float16): WARNING
#Your GPU may run slowly with dtype policy mixed_float16 because it does not have compute capability
#of at least 7.0. Your GPU: Quadro P6000, compute capability 6.1
from tensorflow.keras.mixed_precision import experimental as mixed_precision
policy = mixed_precision.Policy('mixed_float16')
mixed_precision.set_policy(policy)
tf.keras.backend.set_floatx(dtype)
# default is 1e-7 which is too small for float16. Without adjusting the epsilon, we will get NaN predictions because of divide by zero problems
tf.keras.backend.set_epsilon(1e-4)
print('Compute dtype: %s' % policy.compute_dtype)
print('Variable dtype: %s' % policy.variable_dtype)
print("\nUsing Half-Floats for training ")
def getRSquared(groundTruth, neuralNetworkOutput):
"""
Computes the R-squared metric.
https://en.wikipedia.org/wiki/Coefficient_of_determination
Parameters:
-- groundTruth (numpy.ndarray): 1D array representing the ground truth.
-- neuralNetworkOutput (numpy.ndarray): 1D array representing the neural network output.
Returns:
-- float: R-squared metric.
"""
# Compute the mean of the ground truth
mean_ground_truth = np.mean(groundTruth)
# Compute the sum of squares of the residuals
ss_residuals = np.sum((groundTruth - neuralNetworkOutput) ** 2)
# Compute the sum of squares of the total variation
ss_total = np.sum((groundTruth - mean_ground_truth) ** 2)
# Compute the R-squared metric
r_squared = 1 - (ss_residuals / ss_total)
return r_squared
@njit
def getRSquaredInPlace(groundTruth,mean_ground_truth,N,neuralNetworkOutput):
"""
Computes the R-squared metric.
https://en.wikipedia.org/wiki/Coefficient_of_determination
Parameters:
-- groundTruth (numpy.ndarray): 1D array representing the ground truth.
-- neuralNetworkOutput (numpy.ndarray): 1D array representing the neural network output.
Returns:
-- float: R-squared metric.
"""
#N = groundTruth.shape[0]
if N == 0:
return np.NAN
# Compute the mean of the ground truth
#mean_ground_truth = np.mean(groundTruth)
ss_residuals = np.float32(0.0)
ss_total = np.float32(0.0)
for i in range(N):
#--------------------------------------
gt = np.float32(groundTruth[i][0]) #groundTruth is a tensorflow array so each element is also an array -> thus we need [0]
nn_out = np.float32(neuralNetworkOutput[i][0]) #neuralNetworkOutput is a tensorflow array so each element is also an array -> thus we need [0]
#--------------------------------------
delta = gt - nn_out
ss_residuals += delta ** 2
#--------------------------------------
delta = gt - mean_ground_truth
ss_total += delta ** 2
# Compute the R-squared metric
r_squared = np.float32(1 - (ss_residuals / ss_total))
return r_squared
def getRSquaredForNeuralNetwork(mocapNETNetwork,networkInput,groundtruthOutput):
import time
startAt = time.time()
#-----------------------------------------------------
try:
print("Extracting R² : Getting neural network response..")
predictions = mocapNETNetwork.predict(networkInput)
#Since the groundtruth is very large and the machines I use don't have
#enough RAM this is an in place R^2 calculation to make sure the computer doesn't enter a page swapping
#loop that makes training grind to a halt..!
print("Extracting R² : Calculating..")
mean_ground_truth = np.float32(np.mean(groundtruthOutput))
#print("groundtruthOutput: ",groundtruthOutput)
rSQ = getRSquaredInPlace(groundtruthOutput,mean_ground_truth,groundtruthOutput.shape[0],predictions)
#This is faster (if you have spare memory..)
#rSQ = getRSquared(groundtruthOutput,predictions)
del predictions
#except:
except Exception as e:
print("Failed to extract R² ..")
print("Error was : ",e)
rSQ = np.NAN
#-----------------------------------------------------
#-----------------------------------------------------
endAt = time.time()
print("R² = ",rSQ," it took ",(endAt-startAt)/60," mins to compute")
return rSQ
def logTrainingResults(
filename,
configuration,
outputType,
outputName,
history,
metrics
):
if (outputType==0):
numberOfModelParametersStr="?"
if 'modelParameters' in configuration:
numberOfModelParametersStr="%u" % int(configuration['modelParameters'])
#First record - Start of File
inputProcessing=""
if (configuration['eNSRM']):
inputProcessing=inputProcessing+" eNSRM"
if ('NSRMNormalizeAngles' in configuration) and (configuration['NSRMNormalizeAngles']):
if (configuration['NSRMNormalizeAngles']==1):
inputProcessing=inputProcessing+" NSRMNormalizeAngles" #Half
elif (configuration['NSRMNormalizeAngles']==2):
inputProcessing=inputProcessing+" NSRMNormalizeAnglesFull"
else:
inputProcessing=inputProcessing+" NSRMNormalizeAnglesUNKNOWN"
if (configuration['EDM']):
inputProcessing=inputProcessing+" EDM"
if (configuration['eigenPoses']):
inputProcessing=inputProcessing+" eigenPoses"
if (configuration['autobuilder']):
inputProcessing=inputProcessing+" autobuilder"
if ( (configuration['decompositionType']!="") and (configuration['doPCA']!="") and ( int(configuration['PCADimensionsKept'])>0 ) ):
inputProcessing=inputProcessing+" %s(%u)"%(configuration['decompositionType'],configuration['PCADimensionsKept'])
if (configuration['PCAAlsoKeepRawData']):
inputProcessing=inputProcessing+"+PCA_RawData"
inputProcessing=inputProcessing+" act("+configuration['activationFunction']+")"
inputProcessing=inputProcessing+" rand("+configuration['weightRandomizationFunction']+")"
inputProcessing=inputProcessing+" "+configuration['optimizer']
if (configuration['balanced2DInputs']):
inputProcessing=inputProcessing+" balanced2DInputs"
if (configuration['useQuadLoss']!=0):
inputProcessing=inputProcessing+" quadLoss"
if (configuration['setConstantSeedForReproducibleTraining']!=1):
inputProcessing=inputProcessing+" random seed"
if (configuration['include2DInputVisibilityFlags']==0):
inputProcessing=inputProcessing+" novis2Dflag"
experimentDescription=""
experimentDescription=experimentDescription+"group %u"%(configuration["groupOutputs"])
if (configuration['useRadians']):
experimentDescription=experimentDescription+" radians"
#--------------------------------------------------------------------
if ('outputValueDistribution' in configuration):
if (configuration['outputValueDistribution']=='balanced'):
experimentDescription=experimentDescription+" balanced offset"
elif (configuration['outputValueDistribution']=='positive'):
experimentDescription=experimentDescription+" positive offset"
elif (configuration['outputValueDistribution']=='negative'):
experimentDescription=experimentDescription+" negative offset"
#--------------------------------------------------------------------
if ('outputNormalizationStrategy' in configuration):
experimentDescription=experimentDescription+" outputNormalizationStrategy="+configuration['outputNormalizationStrategy']
#--------------------------------------------------------------------
if (float(configuration['outputMultiplier'])!=1.0):
experimentDescription=experimentDescription+" outputScaling=%0.2f" % float(configuration['outputMultiplier'])
experimentDescription=experimentDescription+" NNDepth=%u"%configuration['neuralNetworkDepth']
#FIRST! RECORD!
with open(filename, 'w') as f:
f.write("""
<html>
<head>
<meta charset=\"UTF-8\">
<title>Training summary of experiment %s for %s </title>
</head>
<body>
"""%(configuration['label'],configuration['hierarchyPartName']))
#Add the hostname..
import socket
f.write("%s<br>\n"%socket.gethostname())
f.write("""
<table border=1>
<tr>
<td>Date</td>
<td>Part</td>
<td>BatchSize</td>
<td>Epochs</td>
<td>&lambda;</td>
<td>Remember</td>
<td>Occlusions</td>
<td>Input Processing</td>
<td>Hard Mining</td>
</tr>
<tr>
<td>%s</td>
<td>%s</td>
<td>%u</td>
<td>%u/%u/%u</td>
<td>%0.2f</td>
<td>c %u/p %u</td>
<td>%u</td>
<td>%s</td>
<td></td>
</tr>
</table>
"""% (
configuration['date'],
configuration['hierarchyPartName'],
configuration['defaultBatchSize'],
configuration["defaultNumberOfEpochs"],configuration["highNumberOfEpochs"],configuration["veryHighNumberOfEpochs"],
configuration["lamda"],
configuration["rememberConsecutiveWeights"],configuration["rememberWeights"],
configuration["ignoreOcclusions"]==0,
inputProcessing
)
)
f.write("""
<table border=1>
<tr>
<td>Serial</td>
<td>Start</td>
<td>End</td>
<td>Training Samples</td>
<td>Model Size</td>
<td>Dropout/L.R</td>
<td>Description</td>
</tr>
<tr>
<td>%s</td>
<td>%u</td>
<td>%u</td>
<td>%u</td>
<td>%s</td>
<td>%0.2f/%0.5f</td>
<td>%s</td>
</tr>
</table>
<table border=1>
<tr>
<td>Joint</td>
<td>R² / Start Loss / M.A.E</td>
<td>R² / End Loss / M.A.E</td>
<td>Tr.Epochs</td>
<td>Min/Max</td>
<td>Offset</td>
<td>Scalar</td>
<td>Scalar Fr.</td>
</tr>
"""% (
configuration['label'],
configuration['startPosition'],
configuration['endPosition'],
configuration['trainingSamples'],
numberOfModelParametersStr,
configuration['dropoutRate'],
configuration['learningRate'],
experimentDescription
)
)
f.close()
#----------------------------------
try:
lowestLossAchievedAt = 0
if ("loss" in history.history) and ("mae" in history.history):
# Initialize variables to store the initial and lowest loss
initial_loss = history.history['loss'][0]
lowest_loss = initial_loss
initial_mae = history.history['mae'][0]
lowest_mae = initial_mae
# Iterate through the history object
count = 0
for i, loss in enumerate(history.history['loss']):
# Update the lowest loss if a lower value is found
if loss < lowest_loss:
lowest_loss = loss
lowestLossAchievedAt = count
count = count + 1
lowest_mae = history.history['mae'][lowestLossAchievedAt]
#By default don't scale
#----------------------------------------------------------------------------
outputMinimumValue = 0.0
outputMaximumValue = 0.0
outputOffsetValue = 0.0
outputScalarValues = 1.0
outputScalarFractionValues = 1.0
#----------------------------------------------------------------------------
for v in range(0,len(configuration["outputOffsetLabels"])):
if (outputName.lower()==configuration["outputOffsetLabels"][v].lower()):
#we found a rule!
outputMinimumValue = float(configuration["outputOffsetMinima"][v])
outputMaximumValue = float(configuration["outputOffsetMaxima"][v])
outputOffsetValue = float(configuration["outputOffsetValues"][v])
outputScalarValues = float(configuration["outputScalarValues"][v])
outputScalarFractionValues = float(configuration["outputScalarFractionValues"][v])
#----------------------------------------------------------------------------
initialVAL = ""
lowestVAL = ""
if ("val_loss" in history.history) and ("val_mae" in history.history):
initial_VALloss = history.history['val_loss'][0]
lowest_VALloss = history.history['val_loss'][lowestLossAchievedAt]
initial_VALmae = history.history['val_mae'][0]
lowest_VALmae = history.history['val_mae'][lowestLossAchievedAt]
initial_VALmae = initial_VALmae * outputScalarFractionValues
lowest_VALmae = lowest_VALmae * outputScalarFractionValues
#--------------------------------------
initialVAL = " - "
if ("test_rsquared_start" in metrics):
initialVAL = " - R² %0.2f/"%(metrics["test_rsquared_start"])
initialVAL = initialVAL + "%0.4f/%0.4f" % (initial_VALloss,initial_VALmae)
#--------------------------------------
lowestVAL = " - "
if ("test_rsquared_end" in metrics):
lowestVAL = " - R² %0.2f/"%(metrics["test_rsquared_end"])
lowestVAL = lowestVAL + "%0.4f/%0.4f" % (lowest_VALloss,lowest_VALmae)
#Every output now gets scaled always
initial_mae = initial_mae * outputScalarFractionValues
lowest_mae = lowest_mae * outputScalarFractionValues
with open(filename, 'a') as f:
f.write("<tr><td>")
f.write(outputName)
f.write("</td>")
#------------------------------------------------
#Start Loss
f.write("<td>")
if ("train_rsquared_start" in metrics):
f.write("R² %0.2f/"%(metrics["train_rsquared_start"]))
f.write("%0.4f/%0.4f%s"%(initial_loss,initial_mae,initialVAL))
f.write("</td>")
#------------------------------------------------
#End Loss
f.write("<td>")
if ("train_rsquared_end" in metrics):
f.write("R² %0.2f/"%(metrics["train_rsquared_end"]))
f.write("%0.4f/%0.4f%s"%(lowest_loss,lowest_mae,lowestVAL))
f.write("</td>")
#------------------------------------------------
#Training Epochs ----------------------------
f.write("<td>")
f.write("%u"%(lowestLossAchievedAt))
f.write("</td>")
#Min/Max ----------------------------
f.write("<td>")
f.write("%0.4f/%0.4f"%(outputMinimumValue,outputMaximumValue))
f.write("</td>")
#Offset -----------------------------
f.write("<td>")
f.write("%0.4f"%(outputOffsetValue))
f.write("</td>")
#Scalar -----------------------------
f.write("<td>")
f.write("%0.4f"%(outputScalarValues))
f.write("</td>")
f.write("<td>")
f.write("%0.4f"%(outputScalarFractionValues))
f.write("</td>")
#------------------------------------------------
f.write("</tr>")
f.close()
except:
print("An exception occurred in logTrainingResults")
def regularTraining(tensorboardLabel,mocapNETNetwork,numberOfEpochs,batchSize,earlyStoppingPatience,trainInput,trainOutput,testInput,testOutput,minD,modelIsTrivial=False,haveTestSet=False,useHalfFloats=False):
#We use a checkpoint system to return best model..
if (os.path.isfile("bestW.hdf5")):
print(bcolors.WARNING,"Found a forgotten checkpoint file, erasing it to avoid trouble",bcolors.ENDC)
os.system('rm bestW.hdf5')
#whatToMonitor='mean_absolute_error'
#minimumDelta=0.05
whatToMonitor='loss'
metrics = dict()
if (useHalfFloats):
print("Early stopping will use MAE instead of loss due to half floats..")
whatToMonitor='mae'
minimumDelta=minD
#To see use :
#tensorboard --logdir step0_upperbody_all/tensorboard --bind_all
#------------------------------------------------------------------------
tensorboard = keras.callbacks.TensorBoard(log_dir=tensorboardLabel,histogram_freq=1)
#------------------------------------------------------------------------
earlystopper = keras.callbacks.EarlyStopping(
monitor=whatToMonitor,
min_delta=minimumDelta,
patience=earlyStoppingPatience,
verbose=1,
mode='auto'
)
#-------------------------------------------------------------------------
checkpointer = keras.callbacks.ModelCheckpoint(
filepath="bestW.hdf5",
monitor=whatToMonitor,
mode='min',
verbose=1,
save_freq='epoch',
save_best_only=True,
save_weights_only=True
)
#------------------------------------------------------------------------
callbacks = [
earlystopper,
checkpointer,
tensorboard
]
#------------------------------------------------------------------------
print("regularTraining begins -> BatchSize=%u / NumberOfEpochs=%u "%(batchSize,numberOfEpochs))
#------------------------------------------------------------------------
if (haveTestSet==False):
#Train without any test data ( probably to conserve memory )
if (not modelIsTrivial):
metrics["train_rsquared_start"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
history = mocapNETNetwork.fit(
trainInput,trainOutput,
epochs=numberOfEpochs,
batch_size=batchSize,
shuffle=True,
#steps_per_epoch=5, #<- Use more steps per epoch?
callbacks=callbacks
)
if (not modelIsTrivial):
metrics["train_rsquared_end"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
else:
#Train with test data
if (not modelIsTrivial):
metrics["train_rsquared_start"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
metrics["test_rsquared_start"] = getRSquaredForNeuralNetwork(mocapNETNetwork,testInput,testOutput)
history = mocapNETNetwork.fit(
trainInput,trainOutput,
epochs=numberOfEpochs,
batch_size=batchSize,
shuffle=True,
validation_data=(testInput,testOutput),
#validation_split=0.2,
callbacks=callbacks
)
if (not modelIsTrivial):
metrics["train_rsquared_end"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
metrics["test_rsquared_end"] = getRSquaredForNeuralNetwork(mocapNETNetwork,testInput,testOutput)
#------------------------------------------------------------------------
if (checkIfFileExists('bestW.hdf5')):
print("We use the best possible model from our ModelCheckpoint")
mocapNETNetwork.load_weights('bestW.hdf5')
os.system('rm bestW.hdf5') #Get rid of the checkpoint as soon as we are done reading it
else:
print("No bestW.hdf5 file found, just using last iteration..")
#------------------------------------------------------------------------
return history,mocapNETNetwork,metrics
#-------------------------------------------------------------------------------------------------------------------------------------------------
def compareTrainingOutputs(groundTruth,neuralOutput):
if (len(groundTruth)!=len(neuralOutput)):
print("Outputs have a different size")
return np.nan
values = len(groundTruth)
losses = (groundTruth[:]-neuralOutput[:])**2
return losses
#----------------------------------------------------
def appendHistory(baseHistory,historyToAppend):
#print("baseHistory -> ",type(baseHistory))
#print("baseHistory Contents -> ",baseHistory)
#print("historyToAppend -> ",type(historyToAppend))
#print("historyToAppend Contents -> ",historyToAppend)
#print("baseHistory.history -> ",type(baseHistory.history))
#print("historyToAppend.history -> ",type(historyToAppend.history))
#-----------------------------------------------------------------------------------------------------------
if ("mae" in baseHistory.history) and ("mae" in historyToAppend.history):
baseHistory.history['mae'] = baseHistory.history['mae'] + historyToAppend.history['mae']
if ("loss" in baseHistory.history) and ("loss" in historyToAppend.history):
baseHistory.history['loss'] = baseHistory.history['loss'] + historyToAppend.history['loss']
if ("val_loss" in baseHistory.history) and ("val_loss" in historyToAppend.history):
baseHistory.history['val_loss'] = baseHistory.history['val_loss'] + historyToAppend.history['val_loss']
if ("val_mae" in baseHistory.history) and ("val_mae" in historyToAppend.history):
baseHistory.history['val_mae'] = baseHistory.history['val_mae'] + historyToAppend.history['val_mae']
#-----------------------------------------------------------------------------------------------------------
return baseHistory
def getLossManually(mocapNETNetwork,trainInput,trainOutput):
predictions = mocapNETNetwork.predict(trainInput)
losses = compareTrainingOutputs(predictions,trainOutput)
#print(losses)
print("Calculating Loss Statistics :")
#--------------------------
maximum = np.max(losses)
minimum = np.min(losses)
median = np.median(losses)
mean = np.mean(losses)
from tools import calculateStandardDeviationInPlaceKnowingMean,convertStandardDeviationToVariance
std = calculateStandardDeviationInPlaceKnowingMean(losses,mean) #np.std(losses)
var = convertStandardDeviationToVariance(std) #np.var(losses)
#--------------------------
titleString="Min=%0.2f,Max=%0.2f,Median=%0.2f,Mean=%0.2f,Std=%0.2f,Var=%0.2f" % (minimum,maximum,median,mean,std,var)
print(bcolors.WARNING," %s " % titleString,bcolors.ENDC)
#difficultyRating = 1.5
difficultyRating = 5.0 # 4.0 1.5 2.8
badScoreAbove = mean + difficultyRating * np.sqrt(std)
print("Threshold for difficult poses is ",badScoreAbove)
difficultPosesIndexes=list()
numberOfTrainingSamples = len(trainInput)
for z in range(0,numberOfTrainingSamples):
if (np.any(losses[z]>badScoreAbove)):
difficultPosesIndexes.append(z)
del losses
return difficultPosesIndexes,mean,std
def onlineHardExampleMiningTraining(tensorboardLabel,mocapNETNetwork,numberOfEpochs,numberOfHardEpochs,numberOfNormalEpochsAfterHard,batchSize,earlyStoppingPatience,trainInput,trainOutput,testInput,testOutput,minD,modelIsTrivial=False,haveTestSet=False,useHalfFloats=False):
#First do a regular training..
halfEpochs=int(numberOfEpochs/2)
if (numberOfEpochs==1):
halfEpochs=numberOfEpochs
print(" Online Hard Example Mining Training session .. ")
metrics = dict()
if (not modelIsTrivial):
metrics["train_rsquared_start"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
dtypeSelected=np.float32
if (useHalfFloats):
dtypeSelected=np.float16
totalHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,halfEpochs,batchSize,earlyStoppingPatience,trainInput,trainOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats)
if (numberOfEpochs==1):
print(" Trivial output will not mine etc. ")
return totalHistory
bestTrainingMAE=0.0
successfulUpdates=0
REGULAR_EPOCHS_AFTER_HARD=numberOfNormalEpochsAfterHard
HARD_EPOCHS=numberOfHardEpochs
miningEpochs = int(halfEpochs/2)
print("Getting initial state of network")
difficultPosesIndexes,mean,std = getLossManually(mocapNETNetwork,trainInput,trainOutput)
print("Backing up model with mae ",mean)
mocapNETNetwork.save_weights("modelBackup.h5")
bestTrainingMAE=mean
for i in range(0,miningEpochs):
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
numberOfTrainingSamples = len(trainInput)
inputSize = len (trainInput[1])
outputSize = len (trainOutput[1])
ratioOfDatasetThatIsDifficult = float ( len(difficultPosesIndexes) / numberOfTrainingSamples )
#If more than 10% of the dataset is difficult
if (ratioOfDatasetThatIsDifficult>0.5):
print(bcolors.FAIL," More than half of the dataset is hard (%u samples) so we train on all samples as hard %u/%u" % (len(difficultPosesIndexes),i,miningEpochs),bcolors.ENDC)
regularHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,HARD_EPOCHS,batchSize,5,trainInput,trainOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats) #difficultInput,difficultOutput
totalHistory = appendHistory(totalHistory,regularHistory)
elif (ratioOfDatasetThatIsDifficult>0.1):
difficultInput = np.full([len(difficultPosesIndexes),inputSize],fill_value=0,dtype=dtypeSelected,order='C')
difficultOutput = np.full([len(difficultPosesIndexes),outputSize],fill_value=0,dtype=dtypeSelected,order='C')
for z in range(0,len(difficultPosesIndexes)):
for field in range(0,inputSize):
difficultInput[z,field]=trainInput[difficultPosesIndexes[z],field]
for field in range(0,outputSize):
difficultOutput[z,field]=trainOutput[difficultPosesIndexes[z],field]
print(bcolors.OKBLUE," Will now train on %u difficult samples %u/%u" % (len(difficultPosesIndexes),i,miningEpochs),bcolors.ENDC)
newHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,HARD_EPOCHS,batchSize,5,difficultInput,difficultOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats)
totalHistory = appendHistory(totalHistory,newHistory)
del difficultInput
del difficultOutput
if (mean<bestTrainingMAE):
print(bcolors.OKGREEN,"Inter-success... beat previous model with mae ",bestTrainingMAE," with this model that has ",mean," mae",bcolors.ENDC)
successfulUpdates=successfulUpdates+1
mocapNETNetwork.save_weights("modelBackup.h5")
bestTrainingMAE=mean
print(" Will now train on all samples not to forget them" )
regularHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,REGULAR_EPOCHS_AFTER_HARD,batchSize,earlyStoppingPatience,trainInput,trainOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats)
totalHistory = appendHistory(totalHistory,regularHistory)
else:
print(bcolors.OKGREEN,"The training has gone pretty well for all samples..",bcolors.ENDC)
regularHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,1,batchSize,1,trainInput,trainOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats)
totalHistory = appendHistory(totalHistory,regularHistory)
break
#Tensorflow leaves the existing models on GPU, as a result we run out of memory,
#try to collect garbage now..
gc.collect()
#Check what happened..
difficultPosesIndexes,mean,std = getLossManually(mocapNETNetwork,trainInput,trainOutput)
#-----------------------
if (mean<bestTrainingMAE):
print(bcolors.OKGREEN,"We beat previous model with mae ",bestTrainingMAE," with this model that has ",mean," mae",bcolors.ENDC)
successfulUpdates=successfulUpdates+1
mocapNETNetwork.save_weights("modelBackup.h5")
bestTrainingMAE=mean
else:
print(bcolors.FAIL,"We scored worse than mae ",bestTrainingMAE,", current score was ",mean," mae",bcolors.ENDC)
#-----------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
if (successfulUpdates==0):
print(bcolors.FAIL,"This OHME code was a waste of time",bcolors.ENDC)
print("Using the best model that had a mae of %0.2f after %u updates"%(bestTrainingMAE,successfulUpdates))
mocapNETNetwork.load_weights("modelBackup.h5")
if (not modelIsTrivial):
metrics["train_rsquared_end"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
del difficultPosesIndexes
return totalHistory,mocapNETNetwork,metrics
#-------------------------------------------------------------------------------------------------------------------------------------------------
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import numpy as np
from enum import Enum
from NSDM import getCompositeLabel,getCompositePoint,getJoint2DDistancePoints
def EDMLabels(rules):
result=list()
numberOfNSDMRules=len(rules['NSDM'])
print("Rules Number ",numberOfNSDMRules)
for i in range(0,numberOfNSDMRules):
#-----------------------------------------------------------------
labelI = getCompositeLabel(
rules['NSDM'][i]['joint'],
rules['NSDM'][i]['halfWayFromThisAnd'],
rules['NSDM'][i]['xOffset'],
rules['NSDM'][i]['yOffset'],
rules['NSDM'][i]['isVirtual']
)
#-----------------------------------------------------------------
for j in range(0,numberOfNSDMRules):
if (i>j):
#-----------------------------------------------------------------
labelJ = getCompositeLabel(
rules['NSDM'][j]['joint'],
rules['NSDM'][j]['halfWayFromThisAnd'],
rules['NSDM'][j]['xOffset'],
rules['NSDM'][j]['yOffset'],
rules['NSDM'][j]['isVirtual']
)
#-----------------------------------------------------------------
result.append("EDM-%sY-%sY-Distance"%(labelI,labelJ))
#print("EDM matrix will look like this ",result)
return result;
def createEDMUsingRules(rules,thisInput):
result=list()
#-----------------------------------------------------------------------------------------------------
if (len(thisInput)==0):
print("createNSDMUsingRules called with no input")
return result
if (not rules['inputJointMap'].checkJointListDimensions(thisInput)):
print("createNSDMUsingRules called with incorrect input size ")
return thisInput
#-----------------------------------------------------------------------------------------------------
numberOfNSDMRules=len(rules['NSDM'])
for i in range(0,numberOfNSDMRules):
iX,iY,iVisibility,iInvalidPoint = getCompositePoint(rules,i,thisInput)
for j in range(0,numberOfNSDMRules):
if (i>j):
# Ensure that each distance is computed only once since the EDM is a symmetric matrix.
#---------------------------------------------------------------------------
jX,jY,jVisibility,jInvalidPoint = getCompositePoint(rules,j,thisInput)
if (iInvalidPoint or jInvalidPoint): #Changed to or 17/5/23 <- Why was this AND and not OR ? also C++ EDM.h code
result.append(np.float32(0.0))
else:
result.append(getJoint2DDistancePoints(iX,iY,jX,jY))
#---------------------------------------------------------------------------
return result
if __name__ == '__main__':
print("EDM.py is a library it cannot be run standalone")
+68
View File
@@ -0,0 +1,68 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import math
import sys
from enum import Enum
from NSDM import getCompositeLabel,getCompositePoint,getJoint2DDistancePoints
def EigenPoseLabels(rules):
result=list()
if ('eigenPoseData' in rules) and ('eigenPoses' in rules) and (int(rules['eigenPoses'])==1):
numberOfEigenPoseRules=len(rules['eigenPoseData']['in'])
print("EigenPoses Rules Number ",numberOfEigenPoseRules)
for i in range(0,numberOfEigenPoseRules):
#-----------------------------------------------------------------
result.append("EigenPose-%u"%(i))
#-----------------------------------------------------------------
return result;
def computeVectorSimilarity_SAD(vec1,vec2):
loss=float(0.0)
if (len(vec1)==len(vec2)):
#If we are here the vectors have the same size
for i in range(0,len(vec1)):
loss = loss + abs(vec1[i]-vec2[i])
return loss
def computeVectorSimilarity_MAD(vec1,vec2):
loss=float(0.0)
if (len(vec1)==len(vec2)):
#If we are here the vectors have the same size
for i in range(0,len(vec1)):
loss = loss + abs(vec1[i]-vec2[i])
return loss/len(vec1)
def computeVectorSimilarity(vec1,vec2,mode="MAD"):
if (len(vec1)!=len(vec2)):
print("EigenPoses.py: Asked for similarity on Vectors with Lengths",len(vec1)," vs ",len(vec2))
sys.exit(0)
return float("nan")
#If we are here the vectors have the same size
if (mode=="SAD"):
return computeVectorSimilarity_SAD(vec1,vec2)
if (mode=="MAD"):
return computeVectorSimilarity_MAD(vec1,vec2)
def createEigenPosesUsingRules(rules,thisInput):
result=list()
if ('eigenPoseData' in rules) and ('eigenPoses' in rules) and (int(rules['eigenPoses'])==1):
numberOfEigenPoseRules=len(rules['eigenPoseData']['in'])
for i in range(0,numberOfEigenPoseRules):
result.append(computeVectorSimilarity(thisInput,rules['eigenPoseData']['in'][i]))
return result
if __name__ == '__main__':
print("EigenPoses.py is a library it cannot be run standalone")
File diff suppressed because it is too large Load Diff
+469
View File
@@ -0,0 +1,469 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import onnxruntime as ort
import onnx
import os
import sys
import time
#-------------------------------------------------------------------------------------------
from readCSV import parseConfiguration,parseConfigurationInputJointMap,transformNetworkInput,initializeDecompositionForExecutionEngine,readGroundTruthFile,readCSVFile,parseOutputNormalization
from NSDM import NSDMLabels,createNSDMUsingRules,inputIsEnoughToCreateNSDM,performNSRMAlignment
from EDM import EDMLabels,createEDMUsingRules
from tools import bcolors,eprint,checkIfFileExists,readListFromFile,convertListToLowerCase,secondsToHz,capitalizeCoordinateTags,getEntryIndexInList,parseSerialNumberFromSummary
#-------------------------------------------------------------------------------------------
from BVH.bvhConverter import BVH
#-------------------------------------------------------------------------------------------
#from Smooth.smoothing import Smooth
#-------------------------------------------------------------------------------------------
from principleComponentAnalysis import PCA
#-------------------------------------------------------------------------------------------
import numpy as np
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETONNXSubProblem():
def __init__(self,
context,
configPath:str,
modelPath:str,
partName:str,
completelyDisablePCACode = 0
):
#self.options = context.sess_options
self.options = ort.SessionOptions()
#-------------------------------------------------------------------------------
self.useOutputLimits = True #Careful, this should always be on!
self.partName = partName
self.configPath = configPath
self.configuration = parseConfiguration(configPath)
self.part = self.configuration["OutputDirectory"]
self.inputName = "input_all"
self.modelPath = modelPath
self.modelDirectory = os.path.dirname(self.modelPath)
self.frameNumber = 0
#-------------------------------------------------------------------------------
onnxModelForCheck = onnx.load(modelPath)
onnx.checker.check_model(onnxModelForCheck)
print("ONNX devices available : ", ort.get_device())
providers = ['CPUExecutionProvider']
#providers = ['CUDAExecutionProvider']
self.model = ort.InferenceSession(modelPath, providers=providers, sess_options=self.options)
for i in range(0,len(self.model.get_inputs())):
print("ONNX INPUTS ",self.model.get_inputs()[i].name)
self.inputName = self.model.get_inputs()[i].name
self.model_input_name = self.model.get_inputs()
#-------------------------------------------------------------------------------
self.inputsWithNSRM = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkInputs.list"))
self.inputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkJoints.list"))
self.outputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkOutputs.list"))
self.configuration = parseConfigurationInputJointMap(self.configuration,self.inputs)
self.serial = parseSerialNumberFromSummary(self.modelDirectory+"/summary.html")
#-------------------------------------------------------------------------------
self.inputReadyForTF = np.empty([2, 1])
self.NSRM = np.empty([2, 2])
#-------------------------------------------------------------------------------
self.emptyList = [0.0] * len(self.inputsWithNSRM)
self.emptyInput = np.asarray([self.emptyList],dtype=np.float32)
self.emptyList = [0.0] * len(self.outputs)
self.emptyOutput = np.asarray([self.emptyList],dtype=np.float32)
#-------------------------------------------------------------------------------
self.outputScalars = [1.0] * len(self.outputs)
self.outputOffsets = [0.0] * len(self.outputs)
self.outputMinima = [-6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
self.outputMaxima = [6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
#-------------------------------------------------------------------------------
self.outputOffsets = parseOutputNormalization(self.modelDirectory,"/outputOffsets.csv",self.outputs,self.outputOffsets)
self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalarsFraction.csv",self.outputs,self.outputScalars)
self.outputMinima = parseOutputNormalization(self.modelDirectory,"/outputMinima.csv",self.outputs,self.outputMinima)
self.outputMaxima = parseOutputNormalization(self.modelDirectory,"/outputMaxima.csv",self.outputs,self.outputMaxima)
#-------------------------------------------------------------------------------
if (self.outputs[0]=="depth"):
self.outputs[0]="hip_zposition"
#-------------------------------------------------------------------------------
print("Output Mapping :")
for jointID in range(0,len(self.outputs)):
#self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
#print(" - Output ",self.outputs[jointID]," limits [",self.outputMinima[jointID],",",self.outputMaxima[jointID],"] scalar ",self.outputScalars[jointID]," offset ",self.outputOffsets[jointID])
print("Out %s|Min %0.2f|Max %0.2f|Scalar %0.2f|Offset %0.2f"%(self.outputs[jointID],self.outputMinima[jointID],self.outputMaxima[jointID],self.outputScalars[jointID],self.outputOffsets[jointID]))
#-------------------------------------------------------------------------------
self.incompleteInput = 1
#-------------------------------------------------------------------------------
self.simulated = False
#-------------------------------------------------------------------------------
self.output = dict()
self.outputMinimumValue = dict()
self.outputMaximumValue = dict()
#-------------------------------------------------------------------------------
self.disablePCACode = completelyDisablePCACode
if (not self.disablePCACode):
self.decompositionEngine = initializeDecompositionForExecutionEngine(self.configuration,self.modelDirectory,self.partName,disablePCACode=self.disablePCACode)
#-------------------------------------------------------------------------------
#The default compatibility setting is the BMVC2019 2channel NSDM, however nowadays we use NSRM
numberOfChannelsPerNSDMElement=2
if (self.configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
#-------------------------------------------------------------------------------
if ("eigenPoses" in self.configuration):
if (self.configuration['eigenPoses']==1):
self.configuration['eigenPoseData'] = readGroundTruthFile(
self.configuration,
"Eigenposes",
"%s/2d_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.partName),
"%s/%s_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.configuration['outputMode'],self.partName), #configuration['outputMode'] is either bvh or 3d
1.0,
numberOfChannelsPerNSDMElement,
int(self.configuration['useRadians']),#useRadians,
0,#useHalfFloats
externalDecomposition=self.decompositionEngine
)
#-------------------------------------------------------------------------------
print("\n\n")
print("Inputs :",self.inputs)
print("Outputs :",self.outputs)
#-------------------------------------------------------------------------------
def getModel(self):
return self.model
def getModelFlops(self):
print("ONNX has no flops calculator")
return 0
def getModelParameters(self):
print("ONNX has no model parameters calculator")
return 0
def test(self):
#-------------------------------------------
thisInputONNX = { self.inputName : self.emptyInput}
output_names_onnx = [otp.name for otp in self.model.get_outputs()]
predictions = self.model.run(output_names_onnx,thisInputONNX)[0][0]
#-------------------------------------------
return 1
def prepareInput(self,input2D :dict,configuration : dict):
from readCSV import prepareInputG
thisFullInput, self.NSRM, thisInput, angleToRotate, missingRatio = prepareInputG(input2D,configuration,self.inputs,self.inputsWithNSRM,self.part,self.decompositionEngine,self.disablePCACode)
#appendCSVToFile(self.inputName+".csv",thisFullInput,fID=self.frameNumber) # <-----------------
inputReadyForTF = np.asarray([thisFullInput],dtype=np.float32)
return inputReadyForTF,missingRatio
def logProbabilisticOutput(self,outputFromNN,resolution=60,increment=6.0,numberOfJoints=30):
xs=list()
#----------------------------------
value = -180.0
inc = increment
for r in range(0,resolution):
xs.append(value)
value=value+inc
#----------------------------------
ys=list()
#----------------------------------
for j in range(0,numberOfJoints):
rs=list()
for r in range(0,resolution):
rs.append(outputFromNN[(j*resolution) + r])
ys.append(rs)
#----------------------------------
# Importing packages
import matplotlib.pyplot as plt
#plt.figure(figsize=(80,80))
plt.clf()
plt.title("Output Distributions %s "%(self.partName))
# Define data values
#print("Should plot %u lines"%numberOfJoints)
for j in range(0,numberOfJoints):
plt.plot(xs, ys[j], label='%s (#%u)' %(self.outputs[j],j))
#print("Plot %u"%j)
plt.legend()
#plt.show() #<-This blocks
plt.draw()
plt.pause(0.01)
"""
Convert a dictionary of 2D inputs to MocapNET output
(Whatever that may be [it is listed in self.inputs and self.outputs])
"""
def castProbabilisticOutputToDiscreteOutput(self, outputFromNN):
if ('probabilisticOutput' in self.configuration) and (self.configuration['probabilisticOutput']==1):
print(bcolors.OKGREEN,"DOING PROBABILISTIC OUTPUT",bcolors.ENDC)
#Resolution incrementation
inc = 10.0
#-------------------------
minV = -180.0
maxV = 180.0
resolution = 0 #<- gets automatically calculated as a function of inc..
#-------------------------
i = minV
while(i<maxV):
resolution = resolution + 1
i=i+inc
#-------------------------
numberOfJoints = int(len(outputFromNN) / resolution)
#Draw plot!
self.logProbabilisticOutput(outputFromNN,resolution=resolution,increment=inc,numberOfJoints=numberOfJoints)
pickedOutput = list()
for j in range(0,numberOfJoints):
bestChoice = 0
bestValue = 0
value = minV
for r in range(0,resolution):
if (outputFromNN[(j*resolution) + r]>bestValue):
bestValue = outputFromNN[(j*resolution + r)]
bestChoice = value
value=value+inc
pickedOutput.append(bestChoice)
#pickedOutput[0] = 0
#pickedOutput[1] = 0
pickedOutput[2] = -160
pickedOutput[3] = 0
pickedOutput[4] = 0
pickedOutput[5] = 0
return pickedOutput
return outputFromNN
"""
Convert a dictionary of 2D inputs to MocapNET output
(Whatever that maybe [it is listed in self.inputs and self.outputs])
"""
def predict(self, input2D:dict):
#print("Predict ",self.partName)
self.inputReadyForTF,missingRatio = self.prepareInput(input2D,self.configuration)
if (missingRatio>0.3):
eprint("Not running ",self.partName," due to missing joints ")#,input2D)
return self.output
#Turns out on some decompositions like FastICA there are a lot of zeros!
#-----------------------------------------------
#Save cycles by not executing an empty data blob
#-----------------------------------------------
self.incompleteInput = 0 #<- This needs to be set to 0 to mark input is received..!
#Cast and then run input through MocapNET
thisInputONNX = { self.inputName : self.inputReadyForTF }
output_names_onnx = [otp.name for otp in self.model.get_outputs()]
predictions = self.model.run(output_names_onnx,thisInputONNX)[0][0]
#predictions = self.model(self.inputReadyForTF,training=False)
#PROBABILISTIC MODE
if ('probabilisticOutput' in self.configuration) and (self.configuration['probabilisticOutput']==1):
predictions = self.castProbabilisticOutputToDiscreteOutput(predictions)
self.output = dict()
if (len(predictions)!=len(self.outputs)):
print(bcolors.FAIL,"Something bad happened.. the network regressed a different number of parameters (",len(predictions),") than what we expected (",len(self.outputs),") ",bcolors.ENDC)
raise IOError
#Go on with it
return self.output
#Values to list..
outputValueList = list()
for i in range (len(self.outputs)):
outputValueList.append(float(predictions[i]))
#==============================================================================================================
# THIS SHOULD BE COMMON IN TENSORFLOW/TF-LITE/ONNX
#==============================================================================================================
#Gather our numpy array output in the form of a labeled dictionary
if (self.useOutputLimits):
#Take into account output offsets/scaling
for i in range (len(self.outputs)):
#This should be the exact oposite of the operation in readCSV.py line 550
recoveredValue = (float(outputValueList[i]) * float(self.outputScalars[i])) + float(self.outputOffsets[i])
#---------------------------------------------------------------
if (recoveredValue > self.outputMaxima[i]):
recoveredValue = self.outputMaxima[i]
if (recoveredValue < self.outputMinima[i]):
recoveredValue = self.outputMinima[i]
#---------------------------------------------------------------
element = self.outputs[i]
self.output[element] = recoveredValue
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#---------------------------------------------------------------
else:
#Not using limits
for i in range (len(self.outputs)):
element = self.outputs[i]
self.output[element] = float(outputValueList[i])
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#==============================================================================================================
#==============================================================================================================
self.frameNumber = self.frameNumber + 1
return self.output
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class PoseNETONNX():
def __init__(
self,
modelPath:str="movenet/model.onnx",
targetWidth = 192,
targetHeight = 192,
trainingWidth = 1920,
trainingHeight = 1080,
):
#Tensorflow attempt to be reasonable
#------------------------------------------
from holisticPartNames import getPoseNETBodyNameList
self.jointNames = getPoseNETBodyNameList()
#------------------------------------------
import onnxruntime as ort
import onnx
onnxModelForCheck = onnx.load(modelPath)
onnx.checker.check_model(onnxModelForCheck)
print("ONNX devices available : ", ort.get_device())
providers = ['CPUExecutionProvider']
#providers = ['CUDAExecutionProvider']
self.options = ort.SessionOptions()
self.model = ort.InferenceSession(modelPath, providers=providers, sess_options=self.options)
for i in range(0,len(self.model.get_inputs())):
print("ONNX INPUTS ",self.model.get_inputs()[i].name)
self.inputName = self.model.get_inputs()[i].name
self.model_input_name = self.model.get_inputs()
#------------------------------------------
self.output = dict()
self.hz = 0.0
self.targetWidth = targetWidth
self.targetHeight = targetHeight
self.trainingWidth = trainingWidth
self.trainingHeight = trainingHeight
#------------------------------------------
def get2DOutput(self):
return self.output
def convertImageToMocapNETInput(self,image,doFlipX=False,threshold=0.05):
import tensorflow as tf
import numpy as np
import time
import cv2
sourceWidth = image.shape[1]
sourceHeight = image.shape[0]
currentAspectRatio=self.targetWidth/self.targetHeight
trainedAspectRatio=self.trainingWidth/self.trainingHeight
#Do resize on OpenCV end
#----------------------------------------------------------------
from tools import img_resizeWithCrop,normalizedCoordinatesAdaptForVerticalImage,normalizedCoordinatesAdaptToResizedCrop
imageTransformed = img_resizeWithCrop(image,self.targetWidth,self.targetHeight)
#imageTransformed = img_resizeWithPadding(image,self.targetWidth,self.targetHeight)
imageTransformed = cv2.cvtColor(imageTransformed,cv2.COLOR_BGR2RGB)
#----------------------------------------------------------------
#Hand image to Tensorflow
#----------------------------------------------------------------
imageONNX = np.expand_dims(imageTransformed, axis=0)
#-------------------------------------------------------------------
start = time.time()
#-------------------------------------------------------------------
#-------------------------------------------------------------------
thisInputONNX = { self.inputName : imageONNX.astype('int32')}
#Run input through MocapNET
output_names_onnx = [otp.name for otp in self.model.get_outputs()]
keypoints_with_scores = self.model.run(output_names_onnx,thisInputONNX)[0][0]
predictions = keypoints_with_scores[0]
#-------------------------------------------------------------------
#-------------------------------------------------------------------
seconds = time.time() - start
self.hz = 1 / (seconds+0.0001)
#print("MoveNET ONNX Framerate : ",round(self.hz,2)," fps ")
currentAspectRatio=sourceWidth/sourceHeight #We "change" aspect ratio by restoring points
for pointID in range(0,len(predictions)):
#Joints have y,x,acc order
nX,nY = normalizedCoordinatesAdaptToResizedCrop(sourceWidth,sourceHeight,self.targetWidth,self.targetHeight,predictions[pointID][1],predictions[pointID][0])
nX,nY = normalizedCoordinatesAdaptForVerticalImage(sourceWidth,sourceHeight,self.trainingWidth,self.trainingHeight,nX,nY)
predictions[pointID][1]=nX
predictions[pointID][0]=nY
from holisticPartNames import processPoseNETLandmarks
self.output = processPoseNETLandmarks(self.jointNames,predictions,currentAspectRatio,trainedAspectRatio,threshold=threshold,doFlipX=doFlipX)
#----------------------------------------------------------------
from MocapNETVisualization import drawPoseNETLandmarks
self.image = drawPoseNETLandmarks(predictions,image,threshold=threshold,jointLabels=self.jointNames)
#----------------------------------------------------------------
return self.output,image
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETONNX():
def __init__(self ):
print("""
██████╗ ███╗ ██╗███╗ ██╗██╗ ██╗
██╔═══██╗████╗ ██║████╗ ██║╚██╗██╔╝
██║ ██║██╔██╗ ██║██╔██╗ ██║ ╚███╔╝
██║ ██║██║╚██╗██║██║╚██╗██║ ██╔██╗
╚██████╔╝██║ ╚████║██║ ╚████║██╔╝ ██╗
╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═══╝╚═╝ ╚═╝""")
self.sess_options = ort.SessionOptions()
self.sess_options.log_severity_level = 3 #<- log_level
self.sess_options.intra_op_num_threads = 4
#self.sess_options.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL
self.sess_options.execution_mode = ort.ExecutionMode.ORT_PARALLEL
self.sess_options.inter_op_num_threads = 4
self.sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
mnet = MocapNETONNX()
print("Survived Test!")
#-------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,419 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import tensorflow as tf
import os
import sys
import time
#-------------------------------------------------------------------------------------------
from readCSV import parseConfiguration,parseConfigurationInputJointMap,transformNetworkInput,initializeDecompositionForExecutionEngine,readGroundTruthFile,readCSVFile,parseOutputNormalization
from NSDM import NSDMLabels,createNSDMUsingRules,inputIsEnoughToCreateNSDM,performNSRMAlignment
from EDM import EDMLabels,createEDMUsingRules
from tools import bcolors,checkIfFileExists,readListFromFile,convertListToLowerCase,secondsToHz,getEntryIndexInList,parseSerialNumberFromSummary
#-------------------------------------------------------------------------------------------
from BVH.bvhConverter import BVH
#-------------------------------------------------------------------------------------------
#from Smooth.smoothing import Smooth
#-------------------------------------------------------------------------------------------
from principleComponentAnalysis import PCA
#-------------------------------------------------------------------------------------------
import numpy as np
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETTFLiteSubProblem():
def __init__(self,
context,
configPath:str,
modelPath:str,
partName:str,
numberOfThreads = 4,
completelyDisablePCACode = 0
):
#-------------------------------------------------------------------------------
self.useOutputLimits = True #Careful, this should always be on!
self.partName = partName
self.configPath = configPath
self.configuration = parseConfiguration(configPath)
self.part = self.configuration["OutputDirectory"]
self.inputName = "input_all"
self.modelPath = modelPath
self.modelDirectory= os.path.dirname(self.modelPath)
self.frameNumber = 0
#-------------------------------------------------------------------------------
#The default compatibility setting is the BMVC2019 2channel NSDM, however nowadays we use NSRM
numberOfChannelsPerNSDMElement=2
if (self.configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
if ("eigenPoses" in self.configuration):
if (self.configuration['eigenPoses']==1):
self.configuration['eigenPoseData'] = readGroundTruthFile(
self.configuration,
"Eigenposes",
"%s/2d_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.partName ),
"%s/%s_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.configuration['outputMode'],self.partName), #configuration['outputMode'] is either bvh or 3d
1.0,
numberOfChannelsPerNSDMElement,
0,#useRadians,
0,#useHalfFloats
externalDecomposition=self.decompositionEngine
)
#-------------------------------------------------------------------------------
self.model = tf.lite.Interpreter(
model_path=self.modelPath,
num_threads=numberOfThreads
)
self.model.allocate_tensors()
self.input_details = self.model.get_input_details()
self.output_details = self.model.get_output_details()
# check the type of the input tensor
self.floating_model = self.input_details[0]['dtype'] == np.float32
#-------------------------------------------------------------------------------
self.inputsWithNSRM = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkInputs.list"))
self.inputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkJoints.list"))
self.outputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkOutputs.list"))
self.configuration = parseConfigurationInputJointMap(self.configuration,self.inputs)
self.serial = parseSerialNumberFromSummary(self.modelDirectory+"/summary.html")
#-------------------------------------------------------------------------------
self.inputReadyForTF = np.empty([2, 1])
self.NSRM = np.empty([2, 2])
#-------------------------------------------------------------------------------
self.outputScalars = [1.0] * len(self.outputs)
self.outputOffsets = [0.0] * len(self.outputs)
self.outputMinima = [-6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
self.outputMaxima = [6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
#-------------------------------------------------------------------------------
self.outputOffsets = parseOutputNormalization(self.modelDirectory,"/outputOffsets.csv",self.outputs,self.outputOffsets)
#self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalars.csv",self.outputs,self.outputScalars)
#for jointID in range(0,len(self.outputs)):
# self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalarsFraction.csv",self.outputs,self.outputScalars)
self.outputMinima = parseOutputNormalization(self.modelDirectory,"/outputMinima.csv",self.outputs,self.outputMinima)
self.outputMaxima = parseOutputNormalization(self.modelDirectory,"/outputMaxima.csv",self.outputs,self.outputMaxima)
#-------------------------------------------------------------------------------
if (self.outputs[0]=="depth"):
self.outputs[0]="hip_zposition"
#-------------------------------------------------------------------------------
print("Output Mapping :")
for jointID in range(0,len(self.outputs)):
#self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
#print("Output ",self.outputs[jointID]," min ",self.outputMinima[jointID]," max ",self.outputMaxima[jointID]," scalar ",self.outputScalars[jointID]," offset ",self.outputOffsets[jointID])
print("Out %s|Min %0.2f|Max %0.2f|Scalar %0.2f|Offset %0.2f"%(self.outputs[jointID],self.outputMinima[jointID],self.outputMaxima[jointID],self.outputScalars[jointID],self.outputOffsets[jointID]))
#-------------------------------------------------------------------------------
self.incompleteInput = 1
#-------------------------------------------------------------------------------
self.simulated = False
#-------------------------------------------------------------------------------
self.output = dict()
self.outputMinimumValue = dict()
self.outputMaximumValue = dict()
#-------------------------------------------------------------------------------
self.disablePCACode = completelyDisablePCACode
if (not self.disablePCACode):
self.decompositionEngine = initializeDecompositionForExecutionEngine(self.configuration,self.modelDirectory,self.partName,disablePCACode=self.disablePCACode)
#-------------------------------------------------------------------------------
print("\n\n")
print("Model Dir :",self.modelDirectory)
print("Inputs :",self.inputs)
print("Outputs :",self.outputs)
#-------------------------------------------------------------------------------
def getModel(self):
return self.model
def getModelFlops(self):
print("TF-Lite has no flops calculator")
return 0
def getModelParameters(self):
model = self.model
#concrete_func = model.signatures["serving_default"]
#print( concrete_func.inputs[0] )
#print( concrete_func.inputs[0].shape )
#inputShape = str(concrete_func.inputs[0].shape)
#inputShape = inputShape.strip("() ")
#inputShape = inputShape.replace(",", "x")
#inputShape = inputShape.replace("None", "1")
#inputShape = inputShape.strip(' ')
#print("Input Shape is : ",inputShape)
#------------------------------------------
totalParameters = 0
try:
trainableParams = np.sum([np.prod(v.get_shape()) for v in model.trainable_weights])
totalParameters = int(totalParameters + nonTrainableParams)
except:
print("Could not get model trainable parameters for TF-Lite model..!")
try:
nonTrainableParams = np.sum([np.prod(v.get_shape()) for v in model.non_trainable_weights])
totalParameters = int(totalParameters + nonTrainableParams)
except:
print("Could not get model non-trainable parameters for TF-Lite model..!")
return totalParameters
def test(self):
#-------------------------------------------
emptyList = [0.0] * len(self.inputsWithNSRM)
emptyInput =np.asarray([emptyList],dtype=np.float32)
#-------------------------------------------
#print("Running zeros ")
self.model.set_tensor(self.input_details[0]['index'],emptyInput)
self.model.invoke()
predictions = self.model.get_tensor(self.output_details[0]['index'])
#-------------------------------------------
return 1
def prepareInput(self,input2D :dict,configuration : dict):
from readCSV import prepareInputG
thisFullInput, self.NSRM, thisInput, angleToRotate, missingRatio = prepareInputG(input2D,configuration,self.inputs,self.inputsWithNSRM,self.part,self.decompositionEngine,self.disablePCACode)
inputReadyForTF = np.asarray([thisFullInput],dtype=np.float32)
return inputReadyForTF,missingRatio
"""
Convert a dictionary of 2D inputs to MocapNET output
(Whatever that maybe [it is listed in self.inputs and self.outputs])
"""
def predict(self,input2D :dict):
self.inputReadyForTF,missingRatio = self.prepareInput(input2D,self.configuration)
if (missingRatio>0.3):
print("Not running ",self.partName," due to missing joints ")
return self.output
#Turns out on some decompositions like FastICA there are a lot of zeros!
#-----------------------------------------------
#Save cycles by not executing an empty data blob
#-----------------------------------------------
self.incompleteInput = 0 #<- This needs to be set to 0 to mark input is received..!
#totalData = 1
#zeroData = 0
#for element in self.inputReadyForTF[0].tolist():
# #print("ELEMENT ",element)
# totalData = totalData + 1
# if ( (element<0.005) and (element>-0.005) ):
# zeroData=zeroData + 1
#missingRatio = zeroData/totalData
#print("Missing Ratio : ",missingRatio)
#if (missingRatio>0.4):
# print(bcolors.FAIL,"Not executing NN with empty data ",bcolors.ENDC)
# #Reset armature..!
# for k in self.output.keys():
# self.output[k]=0.0
# self.incompleteInput = 1
# return self.output
#-----------------------------------------------
self.model.set_tensor(self.input_details[0]['index'],self.inputReadyForTF)
self.model.invoke()
predictions = self.model.get_tensor(self.output_details[0]['index'])
self.output = dict()
if (len(predictions[0])!=len(self.outputs)):
print(bcolors.FAIL,"Something bad happened.. the ",self.partName," network regressed a different number of parameters (",len(predictions[0]),") than what we expected (",len(self.outputs),") ",bcolors.ENDC)
raise IOError
return self.output
#Values to list..
outputValueList = list()
for i in range (len(self.outputs)):
outputValueList.append(float(predictions[0][i]))
#==============================================================================================================
# THIS SHOULD BE COMMON IN TENSORFLOW/TF-LITE/ONNX
#==============================================================================================================
#Gather our numpy array output in the form of a labeled dictionary
if (self.useOutputLimits):
#Take into account output offsets/scaling
for i in range (len(self.outputs)):
#This should be the exact oposite of the operation in readCSV.py line 550
recoveredValue = (float(outputValueList[i]) * float(self.outputScalars[i])) + float(self.outputOffsets[i])
#---------------------------------------------------------------
if (recoveredValue > self.outputMaxima[i]):
recoveredValue = self.outputMaxima[i]
if (recoveredValue < self.outputMinima[i]):
recoveredValue = self.outputMinima[i]
#---------------------------------------------------------------
element = self.outputs[i]
self.output[element] = recoveredValue
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#---------------------------------------------------------------
else:
#Not using limits
for i in range (len(self.outputs)):
element = self.outputs[i]
self.output[element] = float(outputValueList[i])
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#==============================================================================================================
#==============================================================================================================
self.frameNumber = self.frameNumber + 1
return self.output
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class PoseNETTFLite():
def __init__(
self,
modelPath:str="movenet/lite-model_movenet_singlepose_lightning_tflite_int8_4.tflite",
targetWidth = 192,
targetHeight = 192,
numberOfThreads = 4,
trainingWidth = 1920,
trainingHeight = 1080,
):
#Tensorflow attempt to be reasonable
#------------------------------------------
from holisticPartNames import getPoseNETBodyNameList
self.jointNames = getPoseNETBodyNameList()
#------------------------------------------
import tensorflow as tf
# Initialize the TFLite interpreter
self.interpreter = tf.lite.Interpreter(model_path=modelPath,num_threads=numberOfThreads)
self.interpreter.allocate_tensors()
#------------------------------------------
self.output = dict()
self.hz = 0.0
self.targetWidth = targetWidth
self.targetHeight = targetHeight
self.trainingWidth = trainingWidth
self.trainingHeight = trainingHeight
#------------------------------------------
def get2DOutput(self):
return self.output
def convertImageToMocapNETInput(self,image,doFlipX=False,threshold=0.05):
import tensorflow as tf
import numpy as np
import time
import cv2
sourceWidth = image.shape[1]
sourceHeight = image.shape[0]
currentAspectRatio=self.targetWidth/self.targetHeight
trainedAspectRatio=self.trainingWidth/self.trainingHeight
#Do resize on OpenCV end
#----------------------------------------------------------------
from tools import img_resizeWithCrop,normalizedCoordinatesAdaptForVerticalImage,normalizedCoordinatesAdaptToResizedCrop
imageTransformed = img_resizeWithCrop(image,self.targetWidth,self.targetHeight)
#imageTransformed = img_resizeWithPadding(image,self.targetWidth,self.targetHeight)
imageTransformed = cv2.cvtColor(imageTransformed,cv2.COLOR_BGR2RGB)
#----------------------------------------------------------------
#Prepare image for Tensorflow
#----------------------------------------------------------------
imageTF = np.expand_dims(imageTransformed, axis=0).astype('int32')
#----------------------------------------------------------------
# TF Lite format expects tensor type of float32.
input_image = tf.cast(imageTF, dtype=tf.uint8) # tf.float32
input_details = self.interpreter.get_input_details()
output_details = self.interpreter.get_output_details()
#-------------------------------------------------------------------
start = time.time()
#-------------------------------------------------------------------
#-------------------------------------------------------------------
self.interpreter.set_tensor(input_details[0]['index'], input_image.numpy())
self.interpreter.invoke()
keypoints_with_scores = self.interpreter.get_tensor(output_details[0]['index']) # Output is a [1, 1, 17, 3] numpy array.
predictions = keypoints_with_scores[0][0]
#-------------------------------------------------------------------
#-------------------------------------------------------------------
seconds = time.time() - start
self.hz = 1 / (seconds+0.0001)
#print("MoveNET TFLite Framerate : ",round(self.hz,2)," fps ")
currentAspectRatio=sourceWidth/sourceHeight #We "change" aspect ratio by restoring points
for pointID in range(0,len(predictions)):
#Joints have y,x,acc order
nX,nY = normalizedCoordinatesAdaptToResizedCrop(sourceWidth,sourceHeight,self.targetWidth,self.targetHeight,predictions[pointID][1],predictions[pointID][0])
nX,nY = normalizedCoordinatesAdaptForVerticalImage(sourceWidth,sourceHeight,self.trainingWidth,self.trainingHeight,nX,nY)
predictions[pointID][1]=nX
predictions[pointID][0]=nY
from holisticPartNames import processPoseNETLandmarks
self.output = processPoseNETLandmarks(self.jointNames,predictions,currentAspectRatio,trainedAspectRatio,threshold=threshold,doFlipX=doFlipX)
#------------------------------------------------
from MocapNETVisualization import drawPoseNETLandmarks
self.image = drawPoseNETLandmarks(predictions,image,threshold=threshold,jointLabels=self.jointNames)
#------------------------------------------------
return self.output,image
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETTFLite():
def __init__(self,):
print("""
████████╗███████╗ ██╗ ██╗████████╗███████╗
╚══██╔══╝██╔════╝ ██║ ██║╚══██╔══╝██╔════╝
██║ █████╗█████╗██║ ██║ ██║ █████╗
██║ ██╔══╝╚════╝██║ ██║ ██║ ██╔══╝
██║ ██║ ███████╗██║ ██║ ███████╗
╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚══════╝""")
#-------------------------------------------------------------------------------
#do nothing :P
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
mnet = MocapNETTFLite()
print("Survived Test!")
#-------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,530 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
#-------------------------------------------------------------------------------------------
from readCSV import parseConfiguration,parseConfigurationInputJointMap,transformNetworkInput,initializeDecompositionForExecutionEngine,readGroundTruthFile,readCSVFile,parseOutputNormalization
from NSDM import NSDMLabels,createNSDMUsingRules,inputIsEnoughToCreateNSDM,performNSRMAlignment
from EDM import EDMLabels,createEDMUsingRules
from tools import bcolors,checkIfFileExists,readListFromFile,convertListToLowerCase,secondsToHz,getEntryIndexInList,parseSerialNumberFromSummary
#-------------------------------------------------------------------------------------------
from BVH.bvhConverter import BVH
#-------------------------------------------------------------------------------------------
#from Smooth.smoothing import Smooth
#-------------------------------------------------------------------------------------------
from principleComponentAnalysis import PCA
#-------------------------------------------------------------------------------------------
import time
import os
import numpy as np
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETTensorflowSubProblem():
def __init__(self,
context,
configPath:str,
modelPath:str,
partName:str,
device:str="/device:GPU:0",
doPerformanceProfiling = False,
tensorboard = 0,
completelyDisablePCACode = 0
):
#-------------------------------------------------------------------------------
self.useOutputLimits = True #Careful, this should always be on!
self.partName = partName
self.configPath = configPath
from readCSV import parseConfiguration
self.configuration = parseConfiguration(configPath)
self.part = partName#self.configuration["OutputDirectory"]
self.modelPath = modelPath
self.modelDirectory= os.path.dirname(self.modelPath)
from DNNModel import loadNewModel
self.model = loadNewModel(modelPath)
self.device = device
self.frameNumber = 0
#-------------------------------------------------------------------------------
#The default compatibility setting is the BMVC2019 2channel NSDM, however nowadays we use NSRM
numberOfChannelsPerNSDMElement=2
if (self.configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
if ("eigenPoses" in self.configuration):
if (self.configuration['eigenPoses']==1):
self.configuration['eigenPoseData'] = readGroundTruthFile(
self.configuration,
"Eigenposes",
"%s/2d_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.partName ),
"%s/%s_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.configuration['outputMode'],self.partName), #configuration['outputMode'] is either bvh or 3d
1.0,
numberOfChannelsPerNSDMElement,
0,#useRadians,
0,#useHalfFloats
externalDecomposition=self.decompositionEngine
)
#-------------------------------------------------------------------------------
import tensorflow as tf
rmsprop=tf.keras.optimizers.RMSprop(learning_rate=0.002, rho=0.9, epsilon=tf.keras.backend.epsilon())
self.model.compile(
optimizer=rmsprop,
loss='mse',
metrics=['mae', 'acc'],
jit_compile=True #<- this may cause trouble on non-XLA builds?
)
self.modelKeras = self.model
#print("MocapNET Model for ",partName," has the following signatures ",self.model.signatures)
self.model = self.model.signatures['serving_default']
self.profile = doPerformanceProfiling
self.tensorboard = tensorboard
#-------------------------------------------------------------------------------
self.inputsWithNSRM = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkInputs.list"))
self.inputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkJoints.list"))
self.outputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkOutputs.list"))
self.configuration = parseConfigurationInputJointMap(self.configuration,self.inputs)
self.serial = parseSerialNumberFromSummary(self.modelDirectory+"/summary.html")
#-------------------------------------------------------------------------------
self.inputReadyForTF = np.empty([2, 1])
self.NSRM = np.empty([2, 2])
#-------------------------------------------------------------------------------
self.outputScalars = [1.0] * len(self.outputs)
self.outputOffsets = [0.0] * len(self.outputs)
self.outputMinima = [-6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
self.outputMaxima = [6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
#-------------------------------------------------------------------------------
self.outputOffsets = parseOutputNormalization(self.modelDirectory,"/outputOffsets.csv",self.outputs,self.outputOffsets)
#self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalars.csv",self.outputs,self.outputScalars)
#for jointID in range(0,len(self.outputs)):
# self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalarsFraction.csv",self.outputs,self.outputScalars)
self.outputMinima = parseOutputNormalization(self.modelDirectory,"/outputMinima.csv",self.outputs,self.outputMinima)
self.outputMaxima = parseOutputNormalization(self.modelDirectory,"/outputMaxima.csv",self.outputs,self.outputMaxima)
#-------------------------------------------------------------------------------
if (self.outputs[0]=="depth"):
self.outputs[0]="hip_zposition"
#-------------------------------------------------------------------------------
print("Output Mapping :")
for jointID in range(0,len(self.outputs)):
#self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
#print("Output ",self.outputs[jointID]," min ",self.outputMinima[jointID]," max ",self.outputMaxima[jointID]," scalar ",self.outputScalars[jointID]," offset ",self.outputOffsets[jointID])
print("Out %s|Min %0.2f|Max %0.2f|Scalar %0.2f|Offset %0.2f"%(self.outputs[jointID],self.outputMinima[jointID],self.outputMaxima[jointID],self.outputScalars[jointID],self.outputOffsets[jointID]))
#-------------------------------------------------------------------------------
self.networkInputList = [0.0] * len(self.inputsWithNSRM)
self.networkInput = np.asarray([self.networkInputList],dtype=np.float32)
#-------------------------------------------------------------------------------
self.incompleteInput = 1
#-------------------------------------------------------------------------------
self.simulated = False
#-------------------------------------------------------------------------------
self.output = dict()
self.outputMinimumValue = dict()
self.outputMaximumValue = dict()
#-------------------------------------------------------------------------------
self.disablePCACode = completelyDisablePCACode
if (not self.disablePCACode):
self.decompositionEngine = initializeDecompositionForExecutionEngine(self.configuration,self.modelDirectory,self.partName,disablePCACode=self.disablePCACode)
#-------------------------------------------------------------------------------
print("\n\n")
print("Inputs :",self.inputs)
print("Outputs :",self.outputs)
#-------------------------------------------------------------------------------
def getModel(self):
return self.modelKeras
def getModelFlops(self):
import tensorflow as tf
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2_as_graph
model = self.modelKeras
concrete = tf.function(lambda inputs: model(inputs))
concrete_func = concrete.get_concrete_function(
[tf.TensorSpec([1, *inputs.shape[1:]]) for inputs in model.inputs])
frozen_func, graph_def = convert_variables_to_constants_v2_as_graph(concrete_func)
with tf.Graph().as_default() as graph:
tf.graph_util.import_graph_def(graph_def, name='')
run_meta = tf.compat.v1.RunMetadata()
opts = tf.compat.v1.profiler.ProfileOptionBuilder.float_operation()
flops = tf.compat.v1.profiler.profile(graph=graph, run_meta=run_meta, cmd="op", options=opts)
totalFLOPS = int(flops.total_float_ops)
return totalFLOPS
return 0
def getModelParameters(self):
model = self.modelKeras
#------------------------------------------------------------------------------------------
trainableParams = np.sum([np.prod(v.get_shape()) for v in model.trainable_weights])
nonTrainableParams = np.sum([np.prod(v.get_shape()) for v in model.non_trainable_weights])
totalParameters = int(trainableParams + nonTrainableParams)
return totalParameters
def test(self):
#-------------------------------------------
emptyList = [0.0] * len(self.inputsWithNSRM)
emptyInput =np.asarray([emptyList],dtype=np.float32)
#-------------------------------------------
#print(bcolors.FAIL,"Running zeros ",bcolors.ENDC)
import tensorflow as tf
outputs = self.model(tf.cast(emptyInput,dtype=tf.float32)) #,training=False
#print("Outputs : ",outputs)
#print("Output Keys", outputs.keys())
outKey = list(outputs.keys())[0]
outputsRaw = outputs[outKey]
predictions = outputsRaw
#predictions = self.model(emptyInput,training=False)
#print("MocapNET result = ",predictions)
#-------------------------------------------
return 1
def prepareInput(self,input2D :dict,configuration : dict):
from readCSV import prepareInputG
thisFullInput, self.NSRM, thisInput, angleToRotate, missingRatio = prepareInputG(input2D,configuration,self.inputs,self.inputsWithNSRM,self.part,self.decompositionEngine,self.disablePCACode)
#i=0
#for value in thisFullInput:
# self.networkInput[i]=value
# i=i+1
#import tensorflow as tf
#self.networkInput = tf.convert_to_tensor(self.networkInputNumpy)
self.networkInput = np.asarray([thisFullInput],dtype=np.float32)
return self.networkInput,missingRatio
#-----------------------------
#inputReadyForTF = np.asarray([thisFullInput],dtype=np.float32)
#return inputReadyForTF
"""
Convert a dictionary of 2D inputs to MocapNET output
(Whatever that maybe [it is listed in self.inputs and self.outputs])
"""
def predict(self,input2D :dict):
#This call works @ 400Hz
#--------------------------------------------------------------------------------------
self.inputReadyForTF,missingRatio = self.prepareInput(input2D,self.configuration)
if (missingRatio>0.3):
print("Not running ",self.partName," due to missing joints ")
return self.output
#Turns out on some decompositions like FastICA there are a lot of zeros!
#-----------------------------------------------
#Save cycles by not executing an empty data blob
#-----------------------------------------------
self.incompleteInput = 0 #<- This needs to be set to 0 to mark input is received..!
#totalData = 1
#zeroData = 0
#for element in self.inputReadyForTF[0].tolist():
# #print("ELEMENT ",element)
# totalData = totalData + 1
# if ( (element<0.005) and (element>-0.005) ):
# zeroData=zeroData + 1
#missingRatio = zeroData/totalData
#print("Missing Ratio : ",missingRatio)
#if (missingRatio>0.4):
# print(bcolors.FAIL,"Not executing NN with empty data ",bcolors.ENDC)
# #Reset armature..!
# for k in self.output.keys():
# self.output[k]=0.0
#
# self.incompleteInput = 1
# return self.output
#--------------------------------------------------------------------------------------
predictions = list()
self.output = dict()
#--------------------------------------------------------------------------------------
if (self.profile):
#Run input through MocapNET and Profile code (slower)
print(bcolors.WARNING,"WARNING: Profiling NN enabled, execution will be slower",bcolors.ENDC)
predictions = self.modelKeras.predict(self.inputReadyForTF,callbacks = [self.tensorboard])
else:
#As stated in https://github.com/keras-team/keras/blob/v2.8.0/keras/engine/training.py#L1825-L2012 :
# and https://keras.io/getting_started/faq/#whats-the-difference-between-model-methods-predict-and-call
import tensorflow as tf
with tf.device(self.device):
#with tf.device('/device:CPU:0'):
inferenceOutputs = self.model(tf.cast(self.inputReadyForTF,dtype=tf.float32)) # ,training=False We shouldn't run predict to get as fast results as possible
#print("Outputs : ",outputs)
#print("Output Keys", outputs.keys())
outKey = list(inferenceOutputs.keys())[0]
outputsRaw = inferenceOutputs[outKey]
#outputsRaw = outputs['result_all']
predictions = outputsRaw
#--------------------------------------------------------------------------------------
if (len(predictions)>0):
if(len(predictions[0])!=len(self.outputs)):
print(bcolors.FAIL,"Something bad happened.. the network regressed a different number of parameters than what we expected",bcolors.ENDC)
raise IOError
return self.output
#Values to list..
outputValueList = list()
for i in range (len(self.outputs)):
outputValueList.append(float(predictions[0][i]))
#==============================================================================================================
# THIS SHOULD BE COMMON IN TENSORFLOW/TF-LITE/ONNX
#==============================================================================================================
#Gather our numpy array output in the form of a labeled dictionary
if (self.useOutputLimits):
#Take into account output offsets/scaling
for i in range (len(self.outputs)):
#This should be the exact oposite of the operation in readCSV.py line 550
recoveredValue = (float(outputValueList[i]) * float(self.outputScalars[i])) + float(self.outputOffsets[i])
#---------------------------------------------------------------
if (recoveredValue > self.outputMaxima[i]):
recoveredValue = self.outputMaxima[i]
if (recoveredValue < self.outputMinima[i]):
recoveredValue = self.outputMinima[i]
#---------------------------------------------------------------
element = self.outputs[i]
self.output[element] = recoveredValue
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#---------------------------------------------------------------
else:
#Not using limits
for i in range (len(self.outputs)):
element = self.outputs[i]
self.output[element] = float(outputValueList[i])
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#==============================================================================================================
#==============================================================================================================
self.frameNumber = self.frameNumber + 1
return self.output
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class PoseNET():
def __init__(
self,
modelPath:str="movenet/",
targetWidth = 192,
targetHeight = 192,
trainingWidth = 1920,
trainingHeight = 1080,
):
#Tensorflow attempt to be reasonable
#------------------------------------------
from holisticPartNames import getPoseNETBodyNameList
self.jointNames = getPoseNETBodyNameList()
import tensorflow as tf
self.model = tf.saved_model.load(modelPath)
self.movenet = self.model.signatures['serving_default']
#------------------------------------------
self.output = dict()
self.hz = 0.0
self.targetWidth = targetWidth
self.targetHeight = targetHeight
self.trainingWidth = trainingWidth
self.trainingHeight = trainingHeight
#------------------------------------------
def get2DOutput(self):
return self.output
def convertImageToMocapNETInput(self,image,doFlipX=False,threshold=0.05):
import tensorflow as tf
import numpy as np
import time
import cv2
sourceWidth = image.shape[1]
sourceHeight = image.shape[0]
currentAspectRatio=self.targetWidth/self.targetHeight
trainedAspectRatio=self.trainingWidth/self.trainingHeight
#Do resize on OpenCV end
#----------------------------------------------------------------
from tools import img_resizeWithCrop,normalizedCoordinatesAdaptForVerticalImage,normalizedCoordinatesAdaptToResizedCrop
imageTransformed = img_resizeWithCrop(image,self.targetWidth,self.targetHeight)
#imageTransformed = img_resizeWithPadding(image,self.targetWidth,self.targetHeight)
imageTransformed = cv2.cvtColor(imageTransformed,cv2.COLOR_BGR2RGB)
#----------------------------------------------------------------
#Prepare image for Tensorflow
#----------------------------------------------------------------
imageTF = np.expand_dims(imageTransformed, axis=0).astype('int32')
#----------------------------------------------------------------
start = time.time()
# TF Lite format expects tensor type of float32.
#-------------------------------------------------------------------
#-------------------------------------------------------------------
outputs = self.movenet(tf.cast(imageTF, dtype=tf.int32))
keypoints_with_scores = outputs['output_0']
predictionsRaw = keypoints_with_scores[0][0]
#-------------------------------------------------------------------
#-------------------------------------------------------------------
seconds = time.time() - start
self.hz = 1 / (seconds+0.0001)
#print("MoveNET Framerate : ",round(self.hz,2)," fps ")
currentAspectRatio=sourceWidth/sourceHeight #We "change" aspect ratio by restoring points
predictions=list()
for pointID in range(0,len(predictionsRaw)):
#Joints have y,x,acc order
thisPoint = list()
thisPoint.append(float(predictionsRaw[pointID][0])) #y
thisPoint.append(float(predictionsRaw[pointID][1])) #x
thisPoint.append(float(predictionsRaw[pointID][2])) #score
nX,nY = normalizedCoordinatesAdaptToResizedCrop(sourceWidth,sourceHeight,self.targetWidth,self.targetHeight,thisPoint[1],thisPoint[0])
nX,nY = normalizedCoordinatesAdaptForVerticalImage(sourceWidth,sourceHeight,self.trainingWidth,self.trainingHeight,nX,nY)
thisPoint[0]= nY #Just update coords
thisPoint[1]= nX #Just update coords
predictions.append(thisPoint)
#-------------------------------------------------------------------
from holisticPartNames import processPoseNETLandmarks
self.output = processPoseNETLandmarks(self.jointNames,predictions,currentAspectRatio,trainedAspectRatio,threshold=threshold,doFlipX=doFlipX)
from MocapNETVisualization import drawPoseNETLandmarks
self.image = drawPoseNETLandmarks(predictions,image,threshold=threshold,jointLabels=self.jointNames)
#------------------------------------------------
return self.output,image
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
def get_available_devices():
from tensorflow.python.client import device_lib
local_device_protos = device_lib.list_local_devices()
return [x.name for x in local_device_protos if x.device_type == 'GPU' or x.device_type == 'CPU']
class MocapNETTensorflow():
def __init__(self,
doPerformanceProfiling = False,
):
print("""
████████╗███████╗███╗ ██╗███████╗ ██████╗ ██████╗ ███████╗██╗ ██████╗ ██╗ ██╗
╚══██╔══╝██╔════╝████╗ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝██║ ██╔═══██╗██║ ██║
██║ █████╗ ██╔██╗ ██║███████╗██║ ██║██████╔╝█████╗ ██║ ██║ ██║██║ █╗ ██║
██║ ██╔══╝ ██║╚██╗██║╚════██║██║ ██║██╔══██╗██╔══╝ ██║ ██║ ██║██║███╗██║
██║ ███████╗██║ ╚████║███████║╚██████╔╝██║ ██║██║ ███████╗╚██████╔╝╚███╔███╔╝
╚═╝ ╚══════╝╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚══════╝ ╚═════╝ ╚══╝╚══╝""")
self.doPerformanceProfiling = doPerformanceProfiling
#Tensorflow attempt to be reasonable
#------------------------------------------
import gc
gc.collect() #Do garbage collection before allocating TF stuff
import os
os.environ['TF_ENABLE_GPU_GARBAGE_COLLECTION']='false'
#Make sure CUDA cache is not disabled!
os.environ['CUDA_CACHE_DISABLE'] = '0'
#Try to presist cudnn
os.environ['TF_USE_CUDNN_BATCHNORM_SPATIAL_PERSISTENT'] = '1'
#Try to allocate as little memory as possible
os.environ['TF_FORCE_GPU_ALLOW_GROWTH'] = 'true'
#Use seperate threads so execution is not throttled by CPU
os.environ['TF_GPU_THREAD_MODE'] = 'gpu_private'
#0 = all messages are logged (default behavior)
#1 = INFO messages are not printed
#2 = INFO and WARNING messages are not printed
#3 = INFO, WARNING, and ERROR messages are not printed
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '0'
#improve the stability of the auto-tuning process used to select the fastest convolution algorithms
os.environ['TF_AUTOTUNE_THRESHOLD'] = '1'
#------------------------------------------
import tensorflow as tf
devices = get_available_devices()
print("Available Tensorflow devices are : ",devices)
self.device = '/device:CPU:0'
for device in devices:
if (device.find("GPU")!=-1):
self.device = device
print("Selecting device : ",self.device)
#If enabled, an op will be placed on CPU if any of the following are true
#1 - there's no GPU implementation for the OP
#2 - no GPU devices are known or registered
#3 - need to co-locate with reftype input(s) which are from CPU
tf.config.set_soft_device_placement(True)
#Only give the warning when not profiling otherwise we will get an error!
if (not doPerformanceProfiling):
tf.config.experimental.set_device_policy('explicit')
try:
tf.config.run_functions_eagerly(True)
tf.config.experimental.set_synchronous_execution(False)
except:
#Invalid device or cannot modify virtual devices once initialized.
pass
try:
physical_devices = tf.config.list_physical_devices('CPU')
tf.config.experimental.set_memory_growth(physical_devices[0], True)
physical_devices = tf.config.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(physical_devices[0], True)
except:
#Invalid device or cannot modify virtual devices once initialized.
pass
try:
tf.config.threading.set_intra_op_parallelism_threads(8)
tf.config.threading.set_inter_op_parallelism_threads(8)
except:
#Most probably : RuntimeError: Intra op parallelism cannot be modified after initialization
pass
if (doPerformanceProfiling):
import tensorflow as tf
self.tensorboard = tf.keras.callbacks.TensorBoard(log_dir = "profiling",histogram_freq = 1)
#tensorboard --bind_all --logdir profiling
from DNNModel import startProfiling
startProfiling()
else:
self.tensorboard=0
def __del__(self):
if (self.doPerformanceProfiling):
from DNNModel import stopProfiling
stopProfiling()
print("To see profile results \nUse :\n tensorboard --logdir profiling ")
print('TFLite stopped.')
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
mnet = MocapNETTensorflow()
print("Survived Test!")
#-------------------------------------------------------------------------------------------------------------------------------------------------------
File diff suppressed because it is too large Load Diff
+521
View File
@@ -0,0 +1,521 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import numpy as np
from enum import Enum
goFromDegreesToRad=np.float32(np.pi/180.0)
goFromRadToDegrees=np.float32(180.0/np.pi)
def getJoint2DDistancePoints(aX,aY,bX,bY):
xDistance=np.float32(bX-aX)
yDistance=np.float32(bY-aY)
return np.float32(np.sqrt( (xDistance*xDistance) + (yDistance*yDistance) ))
def getNumberOfSquaredCompressedSquaredJoints():
countList=len(getBodyNoHandsList())
numberOfSquaredCompressedJoints=countList*countList*2
return numberOfSquaredCompressedJoints
def getAngleToAlignToZero(iX,iY,jX,jY,NSRMNormalizeAngles=0):
#---------------------------------------------
if ( (iX==jX) and (iY==jY) ):
return np.float32(0.0)
#---------------------------------------------
#We have points a, b and c and we want to calculate angle b
aX= iX*100
aY= iY*100
#---------------------------------------------
bX= jX*100
bY= jY*100
#---------------------------------------------
lengthBetweenAAndB = getJoint2DDistancePoints(aX,aY,bX,bY)
#---------------------------------------------
cX= bX
cY= bY - lengthBetweenAAndB
#---------------------------------------------
#fprintf(stderr,"We want to align A(%0.2f,%0.2f) to C(%0.2f,%0.2f) with pivot B(%0.2f,%0.2f)\n",aX,aY,cX,cY,bX,bY)
#fprintf(stderr,"length AB = %0.2f\n",lengthBetweenAAndB);
#fprintf(stderr,"bY = %0.2f\n",bY);
#fprintf(stderr,"cY = %0.2f = %0.2f - %0.2f\n",cY,bY,lengthBetweenAAndB);
#Calulate vector a->b
abX = bX - aX
abY = bY - aY
#calculate vector c->b
cbX = bX - cX
cbY = bY - cY
#---------------------------------------------
dot = np.float32( (abX * cbX) + (abY * cbY) ) # dot product
cross = np.float32( (abX * cbY) - (abY * cbX) ) # cross product
#---------------------------------------------
alpha = np.arctan2(cross,dot) #arctan2 returns a value in the range [-pi, pi]
#---------------------------------------------
#fprintf(stderr,"Angle is %0.2f rad or %0.2f degrees \n",alpha,alpha*goFromRadToDegrees);
if (NSRMNormalizeAngles==2):
return np.float32( (2.0*alpha) / np.pi) # Normalize output in range [-1..1]
if (NSRMNormalizeAngles==1):
#This should actually be (2*alpha) / np.pi
#arctan(R) -> [ -pi/2 , pi/2]
return np.float32(alpha / np.pi) # Normalize output in range [-1/2..1/2]
else:
return np.float32(alpha) # Output in range [-pi..pi]
"""
This is the new function to make resolving 2D coordinates on a vector easier and safer (but slower :P)
"""
def getJoint2DXYV(rules,positions,jointName):
#------------------------------------------------------------------------------------------
x = np.float32(0.0)
y = np.float32(0.0)
visibility = np.float32(0.0)
#------------------------------------------------------------------------------------------
positionDataLength = len(positions)
if (positionDataLength==0):
print("getJoint2DXYV cannot resolve positions for joint ",jointName," with no vector data")
return x,y,visibility
if (not rules['inputJointMap'].checkJointListDimensions(positions)):
print("getJoint2DXYV cannot resolve positions for joint ",jointName," input joint map has a different dimension size..")
return x,y,visibility
#Get correct indexes for jointName
#--------------------------------------------------------
jID_X = rules['inputJointMap'].getJointID_2DX(jointName)
jID_Y = rules['inputJointMap'].getJointID_2DY(jointName)
jID_Vis = rules['inputJointMap'].getJointID_Visibility(jointName)
#--------------------------------------------------------
if ( (positionDataLength<=jID_X) or (positionDataLength<=jID_Y) or (positionDataLength<=jID_Vis) ):
print("getJoint2DXYV cannot get positions for joint ",jointName," with a vector data of only ",positionDataLength)
return x,y,visibility
#--------------------------------------------------------
if ( (jID_X==-1) or (jID_Y==-1) or (jID_Vis==-1) ):
print("getJoint2DXYV could not resolve joint ",jointName," with vector data of ",positionDataLength)
return x,y,visibility
#--------------------------------------------------------
#print("getJoint2DXYV(%s->%u/%u/%u) length %u"%(jointName,jID_X,jID_Y,jID_Vis,positionDataLength))
#Pedantic behavior on missing data
if (positions[jID_X]==0.0) or (positions[jID_Y]==0.0) or (positions[jID_Vis]==0.0):
return x,y,visibility
#------------------------------------
x = np.float32(positions[jID_X])
y = np.float32(positions[jID_Y])
visibility = np.float32(positions[jID_Vis])
#------------------------------------
return x,y,visibility
def rotate2DPointsTest(cx,cy,jX,jY,angleToRotateInRadians):
#-----------------------------------------------
s = np.float32( np.sin(angleToRotateInRadians) )
c = np.float32( np.cos(angleToRotateInRadians) )
#-----------------------------------------------
jX = np.float32(jX - cx)
jY = np.float32(jY - cy)
#-----------------------------------------------
xnew = np.float32( (jX * c) - (jY * s) )
ynew = np.float32( (jX * s) + (jY * c) )
#-----------------------------------------------
return xnew + cx , ynew + cy
def rotate2DPointsBasedOnJointAsCenter(rules,positions,angleToRotateInRadians,jointNameCenter):
if (len(positions)==0):
print("rotate2DPointsBasedOnJointAsCenter cannot work without input.. \n")
return positions
s = np.float32( np.sin(angleToRotateInRadians) )
c = np.float32( np.cos(angleToRotateInRadians) )
#--------------------------------------------------------
cx,cy,cVisibility = getJoint2DXYV(rules,positions,jointNameCenter)
#--------------------------------------------------------
if (cVisibility==0.0):
print("rotate2DPointsBasedOnJointAsCenter: cannot work without pivot joint .. \n")
return positions
result = positions
for jID in range(0,int(len(rules['NSDM'])) ):
#--------------------------------------------------------
jointName=rules['NSDM'][jID]['joint']
jX,jY,jVisibility = getJoint2DXYV(rules,positions,jointName)
#--------------------------------------------------------
#printf("Rotating point %0.2f,%0.2f using pivot %0.2f,%0.2f by %0.2f deg -> "%(jX,jY,cx,cy,angle))
#Translate point back to origin:
jX = np.float32(jX - cx)
jY = np.float32(jY - cy)
#Rotate point
xnew = np.float32( (jX * c) - (jY * s) )
ynew = np.float32( (jX * s) + (jY * c) )
#Translate point back:
jID_X = rules['inputJointMap'].getJointID_2DX(jointName)
jID_Y = rules['inputJointMap'].getJointID_2DY(jointName)
jID_Vis = rules['inputJointMap'].getJointID_Visibility(jointName)
#----------------------------------------------------------------
result[jID_X] = np.float32(xnew + cx)
result[jID_Y] = np.float32(ynew + cy)
result[jID_Vis] = np.float32(jVisibility)
#printf("%0.2f,%0.2f\n"%(result[jID*3+0],result[jID*3+1]));
return result
def performNSRMAlignment(thisInput,configuration):
angleToRotateInRadians = 0.0
NSRMUseAlignmentToPivot = configuration['eNSRM']
NSRMNormalizeAngles = 0
if ("NSRMNormalizeAngles" in configuration) and (configuration["NSRMNormalizeAngles"]==1):
NSRMNormalizeAngles = 1
if (NSRMUseAlignmentToPivot==1):
pivotPoint = configuration['Alignment'][0]['jointStart']
referencePoint = configuration['Alignment'][0]['jointEnd']
#-----------------------------------------------------------------------------------------------
if (pivotPoint!=referencePoint):
pivotX,pivotY,pivotVisibility = getJoint2DXYV(configuration,thisInput,pivotPoint)
#--------------------------------------------------------------------------------------------
referenceX,referenceY,referenceVisibility = getJoint2DXYV(configuration,thisInput,referencePoint)
#--------------------------------------------------------------------------------------------
if ((pivotVisibility!=0) and (referenceVisibility!=0)):
angleToRotateInRadians = getAngleToAlignToZero(pivotX,pivotY,referenceX,referenceY,NSRMNormalizeAngles)
rotatedInput = rotate2DPointsBasedOnJointAsCenter(configuration,thisInput,angleToRotateInRadians,pivotPoint)
return angleToRotateInRadians,rotatedInput
else:
print("Pivot Point ",pivotPoint," and Reference Point ",referencePoint," are the same\n")
#-----------------------------------------------------------------------------------------------
return angleToRotateInRadians,thisInput
def getCompositeLabel(jointA,jointB,xOffset,yOffset,virtualPointType):
labelI=jointA
labelIX=""
labelIY=""
if (virtualPointType==1):
if (xOffset<0):
labelIX="minus"
elif (xOffset>0):
labelIX="plus"
#----------------------------------
if (yOffset<0):
labelIY="minus"
elif (yOffset>0):
labelIY="plus"
#----------------------------------
labelI="virtual_"+jointA+"_x_"+labelIX+str(xOffset).replace('.','_').replace('-','_')+"_y_"+labelIY+str(yOffset).replace('.','_').replace('-','_')
elif (virtualPointType==2):
#----------------------------------
labelI="halfway_"+jointA+"_and_"+jointB
return labelI
def NSDMLabels(rules):
result=list()
useXY=1
useAngles=0
if (rules['NSDMAlsoUseAlignmentAngles']==1):
useXY=0
useAngles=1
numberOfNSDMRules=len(rules['NSDM'])
print("Rules Number ",numberOfNSDMRules)
for i in range(0,numberOfNSDMRules):
for j in range(0,numberOfNSDMRules):
if (i==j):
if (i==0):
result.append("NSRM-angleUsedFor2DRotation_%u"%(i))
else:
result.append("NSRM-scaleBetween_"+rules['NSDM'][i]['joint']+"_and_"+rules['NSDM'][i]['joint'])
else:
#-----------------------------------------------------------------
labelI = getCompositeLabel(
rules['NSDM'][i]['joint'],
rules['NSDM'][i]['halfWayFromThisAnd'],
rules['NSDM'][i]['xOffset'],
rules['NSDM'][i]['yOffset'],
rules['NSDM'][i]['isVirtual']
)
#-----------------------------------------------------------------
labelJ = getCompositeLabel(
rules['NSDM'][j]['joint'],
rules['NSDM'][j]['halfWayFromThisAnd'],
rules['NSDM'][j]['xOffset'],
rules['NSDM'][j]['yOffset'],
rules['NSDM'][j]['isVirtual']
)
#-----------------------------------------------------------------
if (useXY):
result.append("NSDM-%sX-%sX"%(labelI,labelJ))
result.append("NSDM-%sY-%sY"%(labelI,labelJ))
if (useAngles):
result.append("NSRM-%sY-%sY-Angle"%(labelI,labelJ))
#-----------------------------------------------------------------
#print("NSDM matrix will look like this ",result)
return result;
def inputIsEnoughToCreateNSDM(rules,thisInput):
numberOfNSDMRules=len(rules['NSDM'])
numberOfJointIDs =len(thisInput)
for i in range(0,numberOfNSDMRules):
jointName=rules['NSDM'][i]['joint']
if (not rules['inputJointMap'].getJointID_Exists(jointName)):
return False
return True
def getListOfMissingNSRMJoints(rules,thisInput):
missingList=list()
numberOfNSDMRules=len(rules['NSDM'])
numberOfJointIDs =len(thisInput)
for i in range(0,numberOfNSDMRules):
jointName=rules['NSDM'][i]['joint']
if (not rules['inputJointMap'].getJointID_Exists(jointName)):
missingList.append(jointName)
else:
iX,iY,iVisibility = getJoint2DXYV(rules,thisInput,jointName)
if (iVisibility==0.0):
missingList.append(jointName)
return missingList
def getCompositePoint(rules,i,thisInput):
#-----------------------------------------------------------
if (len(thisInput)==0):
print("getCompositePoint called with no input for element ",i)
return np.float32(0.0),np.float32(0.0),np.float32(0.0),1
#--------------------------------------------------------
invalidPoint = 0
jointName = rules['NSDM'][i]['joint']
#-----------------------------------------------------------
iX,iY,iVisibility = getJoint2DXYV(rules,thisInput,jointName)
#-----------------------------------------------------------
if ( iX!=0.0 and iY!=0.0 and iVisibility!=0.0 ):
#---------------------------------------------------------------------------
# Synthetic Points
#---------------------------------------------------------------------------
if (rules['NSDM'][i]['isVirtual']==1):
iX=iX+rules['NSDM'][i]['xOffset']
iY=iY+rules['NSDM'][i]['yOffset']
elif (rules['NSDM'][i]['isVirtual']==2):
secondTargetJointName=rules['NSDM'][i]['halfWayFromThisAnd']
secondTargetX,secondTargetY,secondTargetVisibility = getJoint2DXYV(rules,thisInput,secondTargetJointName)
if ((secondTargetX!=0.0) or (secondTargetY!=0.0)):
iX=np.float32((iX+secondTargetX)/2)
iY=np.float32((iY+secondTargetY)/2)
else:
invalidPoint = 1
iX = np.float32(0.0)
iY = np.float32(0.0)
iVisibility = np.float32(0.0)
#---------------------------------------------------------------------------
else:
#Added : Fixed bug! 11/5/2023
#If either of X,Y is zero we treat the point as completely invisible
invalidPoint = 1
iX = np.float32(0.0)
iY = np.float32(0.0)
iVisibility = np.float32(0.0)
#-----------------------------------------------------------
return iX,iY,iVisibility,invalidPoint
def createNSDMUsingRules(rules,thisInput,angleUsedToRotateInput):
result=list()
#-----------------------------------------------------------------------------------------------------
if (len(thisInput)==0):
print("createNSDMUsingRules called with no input")
return result
if (not rules['inputJointMap'].checkJointListDimensions(thisInput)):
print("createNSDMUsingRules called with incorrect input size ")
return thisInput
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
NSRMNormalizeAngles = 0
if ("NSRMNormalizeAngles" in rules) and (rules["NSRMNormalizeAngles"]==1):
NSRMNormalizeAngles = 1
doNormalization = (rules['NSDMNormalizationMasterSwitch']==1)
useXY = True
useAngles = False
if (rules['eNSRM']==1) or (rules['NSDMAlsoUseAlignmentAngles']==1):
useXY = False
useAngles = True
doNormalization = False
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
# ..Main NSRM parameters ..
#-----------------------------------------------------------------------------------------------------
numberOfNSDMRules=len(rules['NSDM'])
for i in range(0,numberOfNSDMRules):
#---------------------------------------------------------------------------
iX,iY,iVisibility,iInvalidPoint = getCompositePoint(rules,i,thisInput)
#---------------------------------------------------------------------------
for j in range(0,numberOfNSDMRules):
#---------------------------------------------------------------------------
jX,jY,jVisibility,jInvalidPoint = getCompositePoint(rules,j,thisInput)
#---------------------------------------------------------------------------
if (iInvalidPoint or jInvalidPoint):
#If any of the two joints is invalid, invalidate all output
if (useXY):
result.append(np.float32(0.0))
result.append(np.float32(0.0))
if (useAngles):
result.append(np.float32(0.0))
else:
if (useXY):
result.append(np.float32(iX-jX))
result.append(np.float32(iY-jY))
if (useAngles):
result.append(getAngleToAlignToZero(iX,iY,jX,jY,NSRMNormalizeAngles))
#---------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
# ..New eNSRM diagonal parameters ..
#-----------------------------------------------------------------------------------------------------
if (rules['eNSRM']==1):
elementID=0
#------------------------------------------------------------
iJointName=rules['NSDM'][0]['joint'] #Pivot point
iX,iY,iVisibility = getJoint2DXYV(rules,thisInput,iJointName)
#------------------------------------------------------------
for j in range(0,numberOfNSDMRules):
elementID = j * numberOfNSDMRules + j # Calculate diagonal elementID based on j
#---------------------------------------------------------------
jJointName = rules['NSDM'][j]['joint']
jX,jY,jVisibility = getJoint2DXYV(rules,thisInput,jJointName)
#---------------------------------------------------------------
if (jVisibility!=0.0) and (iVisibility!=0.0):
#Populate diagonal elements with distance from our pivot point
result[elementID] = getJoint2DDistancePoints(iX,iY,jX,jY)
else:
result[elementID] = np.float32(0.0)
#---------------------------------------------------------------
#Overwrite first (null) element of NSRM matrix with the angle used to rotate the input
result[0]=np.float32(angleUsedToRotateInput);
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
if (doNormalization):
#normalization is made for NSDM not xNSRM
#Normalizing results.. ---------------------------------------
numberOfNSDMScalingRules=len(rules['NormalizeNSDMBasedOn'])
if (numberOfNSDMScalingRules>0):
numberOfDistanceSamples=0
sumOfDistanceSamples=0.0
for i in range(0,numberOfNSDMScalingRules):
#------------------------------------------------------------------------
iJointName=rules['NormalizeNSDMBasedOn'][i]['jointStart']
iX,iY,iVisibility = getJoint2DXYV(rules,thisInput,iJointName)
#------------------------------------------------------------------------
jJointName=rules['NormalizeNSDMBasedOn'][i]['jointEnd']
jX,jY,jVisibility = getJoint2DXYV(rules,thisInput,jJointName)
#------------------------------------------------------------------------
if (iJointName==jJointName):
print("Error: Normalization Rule ",i," points to same start/end joint ",iJointID," == ",jJointID)
distance = getJoint2DDistancePoints(iX,iY,jX,jY)
if (distance>0.0):
numberOfDistanceSamples=numberOfDistanceSamples+1
sumOfDistanceSamples=sumOfDistanceSamples+distance
#-------------------------------------------------------------------------------------------------
scaleDistance=1.0
#-------------------------------------------------------------------------------------------------
if (numberOfDistanceSamples>0):
scaleDistance=sumOfDistanceSamples/numberOfDistanceSamples
#-------------------------------------------------------------------------------------------------
#print("NSDM Scale = ",scaleDistance," \n")
if (scaleDistance!=1.0):
for i in range(0,len(result)):
result[i]=np.float32(result[i]/scaleDistance)
#-------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
if (useXY):
for i in range(0,len(result)):
if (result[i]!=0.0):
result[i]=np.float32(0.5+result[i])
#-------------------------------------------------------------------------------------------------
#print(result)
#print("Result has ", len(result), " elements " )
#print("Result should have ", int( 2 * len(bodyWithoutHands) * len(bodyWithoutHands) ), " elements " )
return result;
if __name__ == '__main__':
print("NSDM.py is a library it cannot be run standalone")
sign = 1.0 #This is positive +1.0
iX=0.5; iY=0.5; jX=1.0; jY=1.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=0.5; jY=1.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=0.0; jY=1.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=1.0; jY=0.5
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=1.0; jY=0.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=0.0; jY=0.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
+455
View File
@@ -0,0 +1,455 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import os
from tools import secondsToHz,eprint
#https://tfhub.dev/google/movenet/singlepose/lightning/4
#https://tfhub.dev/google/lite-model/movenet/singlepose/lightning/tflite/int8/4
#wget -q -O lite-model_movenet_singlepose_lightning_tflite_int8_4.tflite https://storage.googleapis.com/tfhub-lite-models/google/lite-model/movenet/singlepose/lightning/tflite/int8/4.tflite
#zip movenet.zip movenet/* movenet/*/*
trainingWidth = 1920
trainingHeight = 1080
def getCaptureDeviceFromPath(videoFilePath,videoWidth,videoHeight):
import cv2
#------------------------------------------
if (videoFilePath=="esp"):
from espStream import ESP32CamStreamer
cap = ESP32CamStreamer()
elif (videoFilePath=="webcam"):
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
elif (videoFilePath=="/dev/video0"):
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
elif (videoFilePath=="/dev/video1"):
cap = cv2.VideoCapture(1)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
elif (videoFilePath=="/dev/video2"):
cap = cv2.VideoCapture(2)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
else:
from tools import checkIfPathIsDirectory
if (checkIfPathIsDirectory(videoFilePath) and (not "/dev/" in videoFilePath) ):
from folderStream import FolderStreamer
cap = FolderStreamer(path=videoFilePath,width=videoWidth,height=videoHeight)
mnet.bvh.configureRendererFromFile("%s/color.calib"%videoFilePath)
else:
cap = cv2.VideoCapture(videoFilePath)
return cap
def runPoseNETSerial():
#Parse command line arguments
#-----------------------------------------
import sys
import cv2
import time
headless = False
economicVisualization= False
saveVideo = False
videoFilePath = "webcam"
videoWidth = 1280
videoHeight = 720
doProfiling = False
doFlipX = False
engine = "onnx"
doNNEveryNFrames = 1 # 3
bvhScale = 1.0
doHCDPostProcessing = 1
hcdLearningRate = 0.001
hcdEpochs = 15
hcdIterations = 30
smoothingSampling = 30.0
smoothingCutoff = 5.0
threshold = 0.05
calibrationFile = ""
plotBVHChannels = False
bvhAnglesForPlotting = list()
bvhAllAnglesForPlotting = list()
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--save"):
saveVideo=True
if (sys.argv[i]=="--nnsubsample"):
doNNEveryNFrames = int(sys.argv[i+1])
if (sys.argv[i]=="--headless"):
headless = True
if (sys.argv[i]=="--flipx"):
doFlipX = True
if (sys.argv[i]=="--plot"):
plotBVHChannels=True
if (sys.argv[i]=="--nonn"):
doNNEveryNFrames = 1000
if (sys.argv[i]=="--calib"):
calibrationFile = sys.argv[i+1]
if (sys.argv[i]=="--ik"):
hcdLearningRate = float(sys.argv[i+1])
hcdEpochs = int(sys.argv[i+2])
hcdIterations = int(sys.argv[i+3])
if (sys.argv[i]=="--smooth"):
smoothingSampling = float(sys.argv[i+1])
smoothingCutoff = float(sys.argv[i+2])
if (sys.argv[i]=="--noik"):
doHCDPostProcessing = 0
doNNEveryNFrames = 1
if (sys.argv[i]=="--scale"):
bvhScale=float(sys.argv[i+1])
if (sys.argv[i]=="--from"):
videoFilePath=sys.argv[i+1]
if (sys.argv[i]=="--engine"):
engine=sys.argv[i+1]
if (sys.argv[i]=="--plot"):
plotBVHChannels=True
# For webcam input:
frameNumber = 0
#------------------------------------------
cap = getCaptureDeviceFromPath(videoFilePath,videoWidth,videoHeight)
#-----------------------------------------
#python3 -m tf2onnx.convert --saved-model movenet --opset 14 --output movenet/model.onnx
#zip movenet.zip movenet/* movenet/*/*
#-----------------------------------------
bvhAnglesForPlotting = list()
# Initialize the PoseNET
if (engine=="tensorflow"):
from MocapNETTensorflow import PoseNET
poseNET = PoseNET(modelPath="movenet/",trainingWidth=trainingWidth,trainingHeight=trainingHeight)
elif (engine=="onnx"):
from MocapNETONNX import PoseNETONNX
poseNET = PoseNETONNX(modelPath="movenet/model.onnx",trainingWidth=trainingWidth,trainingHeight=trainingHeight)
elif (engine=="tflite"):
from MocapNETTFLite import PoseNETTFLite
poseNET = PoseNETTFLite(trainingWidth=trainingWidth,trainingHeight=trainingHeight)
else:
print("Unknown engine (",engine,") for MoveNET")
sys.exit(1)
#Select a MocapNET class from tensorflow/tensorrt/onnx/tf-lite engines
from MocapNET import easyMocapNETConstructor
mnet = easyMocapNETConstructor(
engine,
doProfiling = doProfiling,
doBody = False, #<- override whole body
doUpperbody = True,
doLowerbody = True,
doHCDPostProcessing = doHCDPostProcessing,
hcdLearningRate = hcdLearningRate,
hcdEpochs = hcdEpochs,
hcdIterations = hcdIterations,
smoothingSampling = smoothingSampling,
smoothingCutoff = smoothingCutoff,
doFace = False,
doREye = False,
doMouth = False,
doHands = False,
bvhScale=bvhScale
)
if (calibrationFile!=""):
print("Enforcing Calibration file : ",calibrationFile)
mnet.bvh.configureRendererFromFile(calibrationFile)
mnet.test()
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
print("\n\n\n\nStarting MocapNET in Singlethreaded mode using BlazePose 2D Input")
print("Please wait until input processing finishes!")
while cap.isOpened():
success, annotated_image = cap.read()
if not success:
print("Ignoring empty camera frame.")
break
# If loading a video, use 'break' instead of 'continue'.
#continue
#print(image.type)
start = time.time()
#Our 2D Joint Estimation
#------------------------------------------------------------------------------------
mocapNETInput,annotated_image = poseNET.convertImageToMocapNETInput(annotated_image,doFlipX=doFlipX,threshold=threshold)
#------------------------------------------------------------------------------------
end = time.time() # Time elapsed
mnet.hz_2DEst = secondsToHz(end - start)
mnet.history_hz_2DEst.append(mnet.hz_2DEst)
if (len(mnet.history_hz_2DEst)>mnet.perfHistorySize):
mnet.history_hz_2DEst.pop(0) #Keep mnet history on limits
#Our 3D Joint Estimation
#------------------------------------------------------------------------------------
doNN = (frameNumber%doNNEveryNFrames)==0
mocapNET3DOutput = mnet.predict3DJoints(mocapNETInput,runNN=doNN,runHCD=True)
mocapNETBVHOutput = mnet.outputBVH
bvhAnglesForPlotting.append(mocapNETBVHOutput)
bvhAllAnglesForPlotting.append(mocapNETBVHOutput)
if (len(bvhAnglesForPlotting)>100):
bvhAnglesForPlotting.pop(0)
#------------------------------------------------------------------------------------
from MocapNETVisualization import visualizeMocapNETEnsemble
image,plotImage = visualizeMocapNETEnsemble(mnet,annotated_image,plotBVHChannels=plotBVHChannels,bvhAnglesForPlotting=bvhAnglesForPlotting,economic=economicVisualization)
#------------------------------------------------------------------------------------
seconds = time.time() - start
fps = 1 / (seconds+0.0001)
#print("\r PoseNET+MocepNET aggregate Framerate : ",round(fps,2)," fps \r", end="", flush=True)
#print("\n", end="", flush=True)
font = cv2.FONT_HERSHEY_SIMPLEX
org = (50, 50)
fontScale = 1
color = (0,0,0)
thickness = 2
message = 'MNET4+ ST/%s/NN:%u/%0.2f fps (2DNN %0.2f/3DNN %0.2f/3DHCD %0.2f)' % (engine,doNN,fps,poseNET.hz,mnet.hz_NN,mnet.hz_HCD)
annotated_image = cv2.putText(annotated_image, message , org, font, fontScale, color, thickness, cv2.LINE_AA)
org = (52, 52)
color = (255,255,255)
annotated_image = cv2.putText(annotated_image, message , org, font, fontScale, color, thickness, cv2.LINE_AA)
#cv2.imwrite('mediapipe_%05u.jpg'%frameNumber, annotated_image)
frameNumber = frameNumber + 1
if (saveVideo):
cv2.imwrite('colorFrame_0_%05u.jpg'%(frameNumber), annotated_image)
if (plotBVHChannels):
cv2.imwrite('plotFrame_0_%05u.jpg'%(frameNumber), plotImage)
if not headless:
cv2.imshow('MocapNET 4 using PoseNET Holistic 2D Joints', annotated_image)
if (plotBVHChannels):
cv2.imshow('MocapNET 4 using PoseNET Holistic Motion History',plotImage)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
if (saveVideo): # 1280x720 by default
os.system("ffmpeg -framerate 30 -i colorFrame_0_%%05d.jpg -s %ux%u -y -r 30 -pix_fmt yuv420p -threads 8 livelastRun3DHiRes.mp4 && rm colorFrame_0_*.jpg " % (videoWidth,videoHeight)) #
if (plotBVHChannels):
os.system("ffmpeg -framerate 30 -i plotFrame_0_%05d.jpg -s 1200x720 -y -r 30 -pix_fmt yuv420p -threads 8 livelastPlot3DHiRes.mp4 && rm plotFrame_0_*.jpg")
def runPoseNETParallel():
#Parse command line arguments
#-----------------------------------------
import sys
import cv2
import time
import threading
headless = False
videoFilePath = "webcam"
videoWidth = 1280
videoHeight = 720
saveVideo = False
plotBVHChannels = False
doProfiling = False
doFlipX = False
engine = "onnx"
doNNEveryNFrames = 1
bvhScale = 1.0
threshold = 0.05
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--headless"):
headless = True
if (sys.argv[i]=="--flipx"):
doFlipX = True
if (sys.argv[i]=="--plot"):
plotBVHChannels=True
if (sys.argv[i]=="--scale"):
bvhScale=float(sys.argv[i+1])
if (sys.argv[i]=="--noplot"):
plotBVHChannels=0
if (sys.argv[i]=="--from"):
videoFilePath=sys.argv[i+1]
if (sys.argv[i]=="--engine"):
engine=sys.argv[i+1]
if (sys.argv[i]=="--dump"):
global doFrameDumpingForTiles
doFrameDumpingForTiles=1
# For webcam input:
#-----------------------------------------
frameNumber = 0
cap = getCaptureDeviceFromPath(videoFilePath,videoWidth,videoHeight)
#-----------------------------------------
#python3 -m tf2onnx.convert --saved-model movenet --opset 14 --output movenet/model.onnx
#zip movenet.zip movenet/* movenet/*/*
#-----------------------------------------
from MocapNETVisualization import drawMocapNETOutput,drawMocapNETAllPlots,drawMissingInput
#It is important for MocapNET to be the first to be initialized!
#So the tensorflow configuration will be set by it ( if tensorflow engine is selected )
#Select a MocapNET class from tensorflow/tensorrt/onnx/tf-lite engines
from MocapNET import easyMocapNETConstructor
mnet = easyMocapNETConstructor(engine,doProfiling=doProfiling,bvhScale=bvhScale)
mnet.test()
bvhAnglesForPlotting = list()
# Initialize the PoseNET
if (engine=="tensorflow"):
from MocapNETTensorflow import PoseNET
poseNET = PoseNET(modelPath="movenet/",trainingWidth=trainingWidth,trainingHeight=trainingHeight)
elif (engine=="onnx"):
from MocapNETONNX import PoseNETONNX
poseNET = PoseNETONNX(modelPath="movenet/model.onnx",trainingWidth=trainingWidth,trainingHeight=trainingHeight)
elif (engine=="tflite"):
from MocapNETTFLite import PoseNETTFLite
poseNET = PoseNETTFLite(trainingWidth=trainingWidth,trainingHeight=trainingHeight)
else:
print("Unknown engine (",engine,") for MoveNET")
sys.exit(1)
if cap.isOpened():
success, previous_image = cap.read()
if not success:
print("Could not grab first frame!.")
sys.exit(0)
mocapNETInput,previous_image = poseNET.convertImageToMocapNETInput(previous_image,doFlipX=doFlipX,threshold=threshold)
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
print("Starting MocapNET in Multithreaded mode using BlazePose 2D Input")
while cap.isOpened():
success, next_image = cap.read()
if not success:
print("Ignoring empty camera frame.")
break
# If loading a video, use 'break' instead of 'continue'.
#continue
#print(image.type)
start = time.time()
#Our 2D Joint Estimation AND 3D Joint Estimation happening in parallel
#------------------------------------------------------------------------------------
doNN = (frameNumber%doNNEveryNFrames)==0
t1 = threading.Thread(name='predict3DJoints', target=mnet.predict3DJoints, args=(mocapNETInput,),kwargs={'runNN': doNN , 'runHCD' : True})
t2 = threading.Thread(name='convertImageToMocapNETInput', target=poseNET.convertImageToMocapNETInput, args=(next_image,))
#------------------------------------------------------------------------------------
t1.start()
t2.start()
# All threads running in parallel, now we wait
# ...
t1.join()
t2.join()
#------------------------------------------------------------------------------------
mocapNET3DOutput = mnet.output3D
mocapNETBVHOutput = mnet.outputBVH
bvhAnglesForPlotting.append(mocapNETBVHOutput)
if (len(bvhAnglesForPlotting)>100):
bvhAnglesForPlotting.pop(0)
#------------------------------------------------------------------------------------
from MocapNETVisualization import visualizeMocapNETEnsemble
image,plotImage = visualizeMocapNETEnsemble(mnet,previous_image,plotBVHChannels=plotBVHChannels,bvhAnglesForPlotting=bvhAnglesForPlotting,economic=True)
#------------------------------------------------------------------------------------
mocapNETInput = poseNET.output
next_image = poseNET.image
#------------------------------------------------------------------------------------
seconds = time.time() - start
fps = 1 / (seconds+0.0001)
#print("\r MoveNET+MocepNET MT aggregate Framerate : ",round(fps,2)," fps \r", end="", flush=True)
#print("\n", end="", flush=True)
frameNumber = frameNumber + 1
#drawMocapNETOutput(mnet,previous_image)
font = cv2.FONT_HERSHEY_SIMPLEX
org = (50, 50)
fontScale = 1
color = (0,0,0)
thickness = 2
message = 'MNET4+ MT/%s/NN:%u/%0.2f fps (2DNN %0.2f/3DNN %0.2f/3DHCD %0.2f)' % (engine,doNN,fps,poseNET.hz,mnet.hz_NN,mnet.hz_HCD)
previous_image = cv2.putText(previous_image, message , org, font, fontScale, color, thickness, cv2.LINE_AA)
org = (52, 52)
color = (255,255,255)
previous_image = cv2.putText(previous_image, message , org, font, fontScale, color, thickness, cv2.LINE_AA)
#------------------------------------------------------------------------------------------------------------
if (saveVideo):
cv2.imwrite('colorFrame_0_%05u.jpg'%(frameNumber), annotated_image)
if (plotBVHChannels):
cv2.imwrite('plotFrame_0_%05u.jpg'%(frameNumber), plotImage)
if not headless:
cv2.imshow('MocapNET 4 using MoveNET Holistic 2D Joints', previous_image)
if (plotBVHChannels):
cv2.imshow('MocapNET 4 using MoveNET Holistic Motion History',plotImage)
if cv2.waitKey(1) & 0xFF == 27:
break
previous_image = next_image
cap.release()
if (saveVideo): #
# 1280x720 by default
os.system("ffmpeg -framerate 30 -i colorFrame_0_%%05d.jpg -s %ux%u -y -r 30 -pix_fmt yuv420p -threads 8 livelastRun3DHiRes.mp4 && rm colorFrame_0_*.jpg " % (videoWidth,videoHeight)) #
if (plotBVHChannels):
os.system("ffmpeg -framerate 30 -i plotFrame_0_%05d.jpg -s 1200x720 -y -r 30 -pix_fmt yuv420p -threads 8 livelastPlot3DHiRes.mp4 && rm plotFrame_0_*.jpg")
if __name__ == '__main__':
doSerialRun = True
import sys
if (len(sys.argv)>1):
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--mt"):
doSerialRun = False
runPoseNETParallel()
if (doSerialRun):
runPoseNETSerial()
@@ -0,0 +1,232 @@
import argparse
import asyncio
import json
import logging
import os
import ssl
import uuid
import cv2
from aiohttp import web
from av import VideoFrame
from aiortc import MediaStreamTrack, RTCPeerConnection, RTCSessionDescription
from aiortc.contrib.media import MediaBlackhole, MediaPlayer, MediaRecorder, MediaRelay
ROOT = os.path.dirname(__file__)
logger = logging.getLogger("pc")
pcs = set()
relay = MediaRelay()
requests = 0
# Initialize the PoseNET
from PoseNET import PoseNET,PoseNETONNX
#poseNET = PoseNET(modelPath="movenet/")
poseNET = PoseNETONNX(modelPath="movenet/model.onnx")
from MocapNETVisualization import drawMocapNETOutput,drawMocapNETAllPlots,drawMissingInput
#Select a MocapNET class from tensorflow/tensorrt/onnx/tf-lite engines
doProfiling = False
engine = "onnx"
from MocapNET import easyMocapNETConstructor
mnet = easyMocapNETConstructor(engine,doProfiling=doProfiling)
mnet.test()
class VideoTransformTrack(MediaStreamTrack):
"""
A video stream track that transforms frames from an another track.
"""
kind = "video"
def __init__(self, track, transform):
super().__init__() # don't forget this!
self.track = track
self.transform = transform
async def recv(self):
frame = await self.track.recv()
if self.transform == "cartoon":
img = frame.to_ndarray(format="bgr24")
# prepare color
img_color = cv2.pyrDown(cv2.pyrDown(img))
for _ in range(6):
img_color = cv2.bilateralFilter(img_color, 9, 9, 7)
img_color = cv2.pyrUp(cv2.pyrUp(img_color))
# prepare edges
img_edges = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
img_edges = cv2.adaptiveThreshold(
cv2.medianBlur(img_edges, 7),
255,
cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY,
9,
2,
)
img_edges = cv2.cvtColor(img_edges, cv2.COLOR_GRAY2RGB)
# combine color and edges
img = cv2.bitwise_and(img_color, img_edges)
# rebuild a VideoFrame, preserving timing information
new_frame = VideoFrame.from_ndarray(img, format="bgr24")
new_frame.pts = frame.pts
new_frame.time_base = frame.time_base
return new_frame
elif self.transform == "edges":
# perform edge detection
img = frame.to_ndarray(format="bgr24")
img = cv2.cvtColor(cv2.Canny(img, 100, 200), cv2.COLOR_GRAY2BGR)
# rebuild a VideoFrame, preserving timing information
new_frame = VideoFrame.from_ndarray(img, format="bgr24")
new_frame.pts = frame.pts
new_frame.time_base = frame.time_base
return new_frame
elif self.transform == "mocapnet":
# rotate image
img = frame.to_ndarray(format="bgr24")
mocapNETInput,annotated_image = poseNET.convertImageToMocapNETInput(img)
mocapNET3DOutput = mnet.predict3DJoints(mocapNETInput,runNN=1,runHCD=True)
drawMocapNETOutput(mnet,annotated_image)
# rebuild a VideoFrame, preserving timing information
new_frame = VideoFrame.from_ndarray(annotated_image, format="bgr24")
new_frame.pts = frame.pts
new_frame.time_base = frame.time_base
return new_frame
else:
return frame
async def index(request):
content = open(os.path.join(ROOT, "PoseNETServer.html"), "r").read()
return web.Response(content_type="text/html", text=content)
async def javascript(request):
content = open(os.path.join(ROOT, "client.js"), "r").read()
return web.Response(content_type="application/javascript", text=content)
async def offer(request):
global requests
requests = requests + 1
params = await request.json()
offer = RTCSessionDescription(sdp=params["sdp"], type=params["type"])
pc = RTCPeerConnection()
pc_id = "PeerConnection(%s)" % uuid.uuid4()
pcs.add(pc)
def log_info(msg, *args):
logger.info(pc_id + " " + msg, *args)
log_info("Created for %s", request.remote)
# prepare local media
player = MediaPlayer(os.path.join(ROOT, "demo-instruct.wav"))
if args.record_to:
recorder = MediaRecorder("%s_%u.mp4"%(args.record_to,requests))
else:
recorder = MediaBlackhole()
@pc.on("datachannel")
def on_datachannel(channel):
@channel.on("message")
def on_message(message):
if isinstance(message, str) and message.startswith("ping"):
channel.send("pong" + message[4:])
@pc.on("connectionstatechange")
async def on_connectionstatechange():
log_info("Connection state is %s", pc.connectionState)
if pc.connectionState == "failed":
await pc.close()
pcs.discard(pc)
@pc.on("track")
def on_track(track):
log_info("Track %s received", track.kind)
if track.kind == "audio":
pc.addTrack(player.audio)
recorder.addTrack(track)
elif track.kind == "video":
pc.addTrack(
VideoTransformTrack(
relay.subscribe(track), transform=params["video_transform"]
)
)
if args.record_to:
recorder.addTrack(relay.subscribe(track))
@track.on("ended")
async def on_ended():
log_info("Track %s ended", track.kind)
await recorder.stop()
# handle offer
await pc.setRemoteDescription(offer)
await recorder.start()
# send answer
answer = await pc.createAnswer()
await pc.setLocalDescription(answer)
return web.Response(
content_type="application/json",
text=json.dumps(
{"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}
),
)
async def on_shutdown(app):
# close peer connections
coros = [pc.close() for pc in pcs]
await asyncio.gather(*coros)
pcs.clear()
if __name__ == "__main__":
#openssl req --new --newkey rsa:4096 -x509 -sha256 --nodes --keyout apache.key --out apache-certificate.crt
parser = argparse.ArgumentParser(description="WebRTC audio / video / data-channels demo")
parser.add_argument("--cert-file", help="SSL certificate file (for HTTPS)")
parser.add_argument("--key-file", help="SSL key file (for HTTPS)")
parser.add_argument("--host", default="0.0.0.0", help="Host for HTTP server (default: 0.0.0.0)")
parser.add_argument("--port", type=int, default=8080, help="Port for HTTP server (default: 8080)")
parser.add_argument("--record-to", help="Write received media to a file."),
parser.add_argument("--verbose", "-v", action="count")
args = parser.parse_args()
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)
ssl_context = ssl.SSLContext()
ssl_context.load_cert_chain("apache-certificate.crt","apache.key")
#if args.cert_file:
# ssl_context = ssl.SSLContext()
# ssl_context.load_cert_chain(args.cert_file, args.key_file)
#else:
# ssl_context = None
app = web.Application()
app.on_shutdown.append(on_shutdown)
app.router.add_get("/", index)
app.router.add_get("/client.js", javascript)
app.router.add_post("/offer", offer)
web.run_app(app, access_log=None, host=args.host, port=args.port, ssl_context=ssl_context)
@@ -0,0 +1,119 @@
#!/usr/bin/env python3
import h5py
import numpy as np
import csv
import os
import sys
from scipy.spatial import procrustes
from scipy.linalg import orthogonal_procrustes
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
#Taken from https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/procrustes.py
def compute_similarity_transform(X, Y, compute_optimal_scale=False):
"""
A port of MATLAB's `procrustes` function to Numpy.
Adapted from http://stackoverflow.com/a/18927641/1884420
Args
X: array NxM of targets, with N number of points and M point dimensionality
Y: array NxM of inputs
compute_optimal_scale: whether we compute optimal scale or force it to be 1
Returns:
d: squared error after transformation
Z: transformed Y
T: computed rotation
b: scaling
c: translation
"""
muX = X.mean(0)
muY = Y.mean(0)
X0 = X - muX
Y0 = Y - muY
ssX = (X0**2.).sum()
ssY = (Y0**2.).sum()
# centred Frobenius norm
normX = np.sqrt(ssX)
normY = np.sqrt(ssY)
# scale to equal (unit) norm
X0 = X0 / normX
Y0 = Y0 / normY
# optimum rotation matrix of Y
A = np.dot(X0.T, Y0)
U,s,Vt = np.linalg.svd(A,full_matrices=False)
V = Vt.T
T = np.dot(V, U.T)
# Make sure we have a rotation
detT = np.linalg.det(T)
V[:,-1] *= np.sign( detT )
s[-1] *= np.sign( detT )
T = np.dot(V, U.T)
traceTA = s.sum()
if compute_optimal_scale: # Compute optimum scaling of Y.
b = traceTA * normX / normY
d = 1 - traceTA**2
Z = normX*traceTA*np.dot(Y0, T) + muX
else: # If no scaling allowed
b = 1
d = 1 + ssY/ssX - 2 * traceTA * normY / normX
Z = normY*np.dot(Y0, T) + muX
c = muX - b*np.dot(muY, T)
return d, Z, T, b, c
def pointListReturnXYZListForScatterPlot(A):
numberOfPoints=A.shape[0]
xs=list()
ys=list()
zs=list()
for i in range(0,numberOfPoints):
xs.append(A[i][0])
ys.append(A[i][1])
zs.append(A[i][2])
return xs,ys,zs
def pointListsReturnAvgDistance(A,B):
numberOfPoints=A.shape[0]
if (A.shape[0]!=B.shape[0]):
print("Error comparing point lists of different length")
return inf
distance=0
for i in range(0,numberOfPoints):
#---------
xA=A[i][0]
yA=A[i][1]
zA=A[i][2]
#---------
xB=B[i][0]
yB=B[i][1]
zB=B[i][2]
#---------
xAB=xA-xB
yAB=yA-yB
zAB=zA-zB
#Pythagorean theorem for 3 dimensions
#distance = squareRoot( xAB^2 + yAB^2 + zAB^2 )
distance+=np.sqrt(xAB*xAB+yAB*yAB+zAB*zAB)
return distance/numberOfPoints
@@ -0,0 +1,280 @@
#!/usr/bin/env python3
#Written by Ammar Qammaz a.k.a AmmarkoV - 2020
import h5py
import numpy as np
import csv
import os
import sys
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
#Taken from https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/procrustes.py
def compute_similarity_transform(X, Y, compute_optimal_scale=False):
"""
A port of MATLAB's `procrustes` function to Numpy.
Adapted from http://stackoverflow.com/a/18927641/1884420
Args
X: array NxM of targets, with N number of points and M point dimensionality
Y: array NxM of inputs
compute_optimal_scale: whether we compute optimal scale or force it to be 1
Returns:
d: squared error after transformation
Z: transformed Y
T: computed rotation
b: scaling
c: translation
"""
#We create a normalized version of X and Y called X0,Y0
#that is centered on 0
muX = X.mean(0)
muY = Y.mean(0)
X0 = X - muX
Y0 = Y - muY
ssX = (X0**2.).sum()
ssY = (Y0**2.).sum()
# centred Frobenius norm
normX = np.sqrt(ssX)
normY = np.sqrt(ssY)
# scale to equal (unit) norm
X0 = X0 / normX
Y0 = Y0 / normY
#For reference this is the SciPy version :
#https://github.com/scipy/scipy/blob/v1.9.3/scipy/spatial/_procrustes.py#L15-L130
#https://github.com/scipy/scipy/blob/v1.9.3/scipy/linalg/_procrustes.py#L12-L89
# optimum rotation matrix of Y
A = np.dot(X0.T, Y0)
#full_matrices => bool, optional
#If True (default), u and vh have the shapes (..., M, M) and (..., N, N), respectively.
#Otherwise, the shapes are (..., M, K) and (..., K, N), respectively, where K = min(M, N).
U,s,Vt = np.linalg.svd(A,full_matrices=False)
V = Vt.T
T = np.dot(V, U.T)
# Make sure we have a rotation
detT = np.linalg.det(T)
V[:,-1] *= np.sign( detT )
s[-1] *= np.sign( detT )
T = np.dot(V, U.T)
#-------------------------
traceTA = s.sum()
#-------------------------
if compute_optimal_scale: # Compute optimum scaling of Y.
b = traceTA * normX / normY
d = 1 - traceTA**2
Z = normX*traceTA*np.dot(Y0, T) + muX
else: # If no scaling allowed
b = 1
d = 1 + ssY/ssX - 2 * traceTA * normY / normX
Z = normY*np.dot(Y0, T) + muX
#-------------------------
c = muX - b*np.dot(muY, T)
#-------------------------
return d, Z, T, b, c
"""
Calculate Area Under Curve (AUC)
"""
def AUC(values,minValue,maxValue):
underCurve=0
samples=len(values)
for value in values:
if ((minValue<=value) and (value<=maxValue) ):
underCurve=underCurve+1
return 100*(underCurve/samples)
"""
Pythagorean theorem, get the 3D distance between two 3D points given their X,Y,Z coordinates
"""
def get3DDistance(jX,jY,jZ,pX,pY,pZ):
return np.sqrt( ((jX-pX)*(jX-pX)) + ((jY-pY)*(jY-pY)) + ((jZ-pZ)*(jZ-pZ)) )
"""
Given two lists of 3D points A,B calculate their average distance
"""
def calculateAverageDistanceOf3DPoints(A,B):
numberOfPoints=A.shape[0]
if (numberOfPoints==0):
print(bcolors.FAIL,"calculateAverageDistanceOf3DPoints(A,B), A has no points!",bcolors.ENDC)
return np.inf
elif (A.shape[0]!=B.shape[0]):
print(bcolors.FAIL,"Error comparing point lists of different length",bcolors.ENDC)
return np.inf
distance=0.0
for i in range(0,numberOfPoints):
#---------
xA=A[i][0]
yA=A[i][1]
zA=A[i][2]
#---------
xB=B[i][0]
yB=B[i][1]
zB=B[i][2]
#----------------------------------------------
distance += get3DDistance(xA,yA,zA,xB,yB,zB)
#----------------------------------------------
return distance/numberOfPoints
"""
Return the jointID of a jointName in a list of labels without being case sensitive
"""
def findJointID(jointName,labels):
jointNameStreamlined=jointName.lower().strip()
for i in range(0,len(labels)):
labelStreamlined=labels[i].lower().strip()
if (jointNameStreamlined==labelStreamlined):
return i
print(bcolors.FAIL,"Cannot find joint `%s` between %u labels !"%(jointNameStreamlined,len(labels)),bcolors.ENDC)
#print(labels)
return -1
def compareGroundTruthToPrediction(configuration,groundTruth,prediction,doProcrustes=1,allowProcrustesToChangeScale=1,jointsToCompare=list(),useSciKitImplementation=False):
#print("GroundTruth : ",groundTruth)
#print("Prediction : ",prediction)
#Automatically fill joints to compare if it is empty with whatever currently
#exists in configuration
numberOfJoints = len(configuration["hierarchy"])
if (len(jointsToCompare)==0):
for jID in range (0,numberOfJoints):
jointsToCompare.append(configuration["hierarchy"][jID]["joint"].lower())
else:
numberOfJoints = len(jointsToCompare)
#--------------------------------------------------------------------------
#Initialize our variables
#-------------------------------
comparedJoints = list()
groundTruth3DPoints = list()
mnet3DPoints = list()
#-------------------------------
scale = 1.0
outputScale = 10.0 # We go from Centimeters to Millimeters!
numberOfJointsToCompare = 0
#-------------------------------
for jointName in jointsToCompare:
jointName = jointName.lower() #Make double sure if supplied as argument
labelX = '3DX_%s' % jointName
labelY = '3DY_%s' % jointName
labelZ = '3DZ_%s' % jointName
if (
( labelX in groundTruth ) and
( labelY in groundTruth ) and
( labelZ in groundTruth ) and
( labelX in prediction ) and
( labelY in prediction ) and
( labelZ in prediction )
):
comparedJoints.append(jointName)
numberOfJointsToCompare = numberOfJointsToCompare + 1
#--------------------------------------------
# Grab ground truth for point
#--------------------------------------------
x3DGT=scale*groundTruth[labelX]
y3DGT=scale*groundTruth[labelY]
z3DGT=scale*groundTruth[labelZ]
#--------------------------------------------
groundTruth3DPoints.append([x3DGT,y3DGT,z3DGT])
#--------------------------------------------
#--------------------------------------------
# Grab MocapNET point
#--------------------------------------------
x3DMNET=scale*prediction[labelX]
y3DMNET=scale*prediction[labelY]
z3DMNET=scale*prediction[labelZ]
#--------------------------------------------
mnet3DPoints.append([x3DMNET,y3DMNET,z3DMNET])
#--------------------------------------------
else:
print(bcolors.WARNING,"Joint ",jointName," was not found this will influence results ")
if (numberOfJointsToCompare==0):
print(bcolors.FAIL,"No joints where found ..",bcolors.ENDC)
#We package our lists in numpy to be able to easily manipulate them
#------------------------------------------------------------------
np_GTPointCloud = np.asarray(groundTruth3DPoints,dtype=np.float32)
np_OURPointCloud = np.asarray(mnet3DPoints,dtype=np.float32)
#------------------------------------------------------------------
#This is the main comparison after using procrustes and transforming the pointcloud
#to align it or when just doing plain old euclidean distance
#--------------------------------------------------------------------------------
if (useSciKitImplementation):
from scipy.spatial import procrustes
mtx1, mtx2, disparity = procrustes(np_GTPointCloud,np_OURPointCloud)
np_GTPointCloud=mtx1
np_OURPointCloud=mtx2
elif (doProcrustes):
d, Z, T, b, c = compute_similarity_transform(np_GTPointCloud,np_OURPointCloud,compute_optimal_scale=allowProcrustesToChangeScale)
#disparity=np.sqrt(d) #d: squared error after transformation
#print("compute_similarity_transform : ",disparity)
#Our point cloud is brought to the same translation and rotation as h36 point cloud
np_OURPointCloud = (b*np_OURPointCloud.dot(T))+c
disparity = outputScale * calculateAverageDistanceOf3DPoints(np_OURPointCloud,np_GTPointCloud)
else:
disparity = outputScale * calculateAverageDistanceOf3DPoints(np_OURPointCloud,np_GTPointCloud)
#--------------------------------------------------------------------------------
#Here for each element in ground truth we want to get the same point from prediction..
#We want to calculate Mean Per Joint Position Error (MPJPE)
#to do so we have to calculate the position error of each of the joints in our point cloud
#sum it up and then divide it through the number of samples
totalError = 0.0
totalSamples = 0
#alljointDistances = list()
jointDistance = dict()
for jID in range(0,numberOfJointsToCompare):
#------------------------------------------------------------------
#We use the np_ourPointCloud and np_h36PointCloud so that if procrustes analysis is enabled it will be used..
perJointDisparity= outputScale * get3DDistance(
np_OURPointCloud[jID][0],np_OURPointCloud[jID][1],np_OURPointCloud[jID][2],
np_GTPointCloud[jID][0] ,np_GTPointCloud[jID][1] ,np_GTPointCloud[jID][2]
)
totalError+=perJointDisparity
totalSamples+=1
#We also keep every sample on a list to do an analysis in the end
#alljointDistances.append(perJointDisparity)
jointDistance[comparedJoints[jID]]=perJointDisparity
#------------------------------------------------------------------
jointDistance["meanAverageError"] = disparity
#print("Frame %u / Disparity %f " % (frameID,disparity))
return jointDistance
@@ -0,0 +1,104 @@
#
# based on: https://colab.research.google.com/notebooks/snippets/advanced_outputs.ipynb#scrollTo=2viqYx97hPMi
#
from IPython.display import display, Javascript
from google.colab.output import eval_js
from base64 import b64decode, b64encode
import numpy as np
import cv2
def init_camera():
"""Create objects and functions in HTML/JavaScript to access local web camera"""
js = Javascript('''
// global variables to use in both functions
var div = null;
var video = null; // <video> to display stream from local webcam
var stream = null; // stream from local webcam
var canvas = null; // <canvas> for single frame from <video> and convert frame to JPG
var img = null; // <img> to display JPG after processing with cv2
async function initCamera() {
// place for video (and eventually buttons)
div = document.createElement('div');
document.body.appendChild(div);
// <video> to display video
video = document.createElement('video');
video.style.display = 'block';
div.appendChild(video);
// get webcam stream and assing to <video>
stream = await navigator.mediaDevices.getUserMedia({video: true});
video.srcObject = stream;
// start playing stream from webcam in <video>
await video.play();
// Resize the output to fit the video element.
google.colab.output.setIframeHeight(document.documentElement.scrollHeight, true);
// <canvas> for frame from <video>
canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
//div.appendChild(input_canvas); // there is no need to display to get image (but you can display it for test)
// <img> for image after processing with cv2
img = document.createElement('img');
img.width = video.videoWidth;
img.height = video.videoHeight;
div.appendChild(img);
}
async function takeImage(quality) {
// draw frame from <video> on <canvas>
canvas.getContext('2d').drawImage(video, 0, 0);
// stop webcam stream
//stream.getVideoTracks()[0].stop();
// get data from <canvas> as JPG image decoded base64 and with header "data:image/jpg;base64,"
return canvas.toDataURL('image/jpeg', quality);
//return canvas.toDataURL('image/png', quality);
}
async function showImage(image) {
// it needs string "data:image/jpg;base64,JPG-DATA-ENCODED-BASE64"
// it will replace previous image in <img src="">
img.src = image;
// TODO: create <img> if doesn't exists,
// TODO: use id to use different <img> for different image - like name in cv2.imshow(name, image)
}
''')
display(js)
eval_js('initCamera()')
def take_frame(quality=0.8):
"""Get frame from web camera"""
data = eval_js('takeImage({})'.format(quality)) # run JavaScript code to get image (JPG as string base64) from <canvas>
header, data = data.split(',') # split header ("data:image/jpg;base64,") and base64 data (JPG)
data = b64decode(data) # decode base64
data = np.frombuffer(data, dtype=np.uint8) # create numpy array with JPG data
img = cv2.imdecode(data, cv2.IMREAD_UNCHANGED) # uncompress JPG data to array of pixels
return img
def show_frame(img, quality=0.8):
"""Put frame as <img src="data:image/jpg;base64,...."> """
ret, data = cv2.imencode('.jpg', img) # compress array of pixels to JPG data
data = b64encode(data) # encode base64
data = data.decode() # convert bytes to string
data = 'data:image/jpg;base64,' + data # join header ("data:image/jpg;base64,") and base64 data (JPG)
eval_js('showImage("{}")'.format(data)) # run JavaScript code to put image (JPG as string base64) in <img>
# argument in showImage needs " "
@@ -0,0 +1,112 @@
import numpy as np
import sys
import os
from readCSV import readCSVFile,writeCSVFile,splitNumpyArray
def functionThatFiltersOutColumnsWithStandardDeviation0(dataIn):
body = dataIn['body']
std_deviations = np.std(body, axis=0)
columns_to_keep = np.where(std_deviations != 0)[0]
filtered_body = body[:, columns_to_keep]
filtered_labels = [dataIn['label'][i] for i in columns_to_keep]
filtered_label_lookup = {label: i for i, label in enumerate(filtered_labels)}
return {
'label': filtered_labels,
'labelLookup': filtered_label_lookup,
'body': filtered_body
}
def functionThatAppendsZeroColumnsByLabels(dataIn, labelsToAppendZeroColumns, preFixPadding=0, postFixPadding=0):
body = dataIn['body']
num_samples, num_columns = body.shape
new_num_columns = num_columns + len(labelsToAppendZeroColumns) + preFixPadding + postFixPadding
new_labels = []
paddingNumber = 0
# Create the new zero-filled data array
new_body = np.zeros((num_samples, new_num_columns), dtype=body.dtype)
#==========================================================================================
for prefixedColumns in range(preFixPadding):
print("Add prefixed padding ",paddingNumber)
new_labels.append("padding_%u"%paddingNumber)
new_body[:, targetColumnIndex] = 0.0 # Fill with zeros
targetColumnIndex += 1 # Move to the next column
paddingNumber += 1
#==========================================================================================
# Fill the new array with data from the original array
targetColumnIndex = 0
for originalColumnIndex in range(num_columns):
if dataIn['label'][originalColumnIndex] in labelsToAppendZeroColumns:
print("Add padding ",paddingNumber)
new_labels.append("padding_%u"%paddingNumber)
new_body[:, targetColumnIndex] = 0.0 # Fill with zeros
targetColumnIndex += 1 # Move to the next column
paddingNumber += 1
print("Processing #",originalColumnIndex," -> ",dataIn['label'][originalColumnIndex])
new_labels.append(dataIn['label'][originalColumnIndex])
new_body[:,targetColumnIndex] = body[:,originalColumnIndex]
targetColumnIndex += 1
#==========================================================================================
for postfixedColumns in range(postFixPadding):
print("Add postfixed padding ",paddingNumber)
new_labels.append("padding_%u"%paddingNumber)
new_body[:, targetColumnIndex] = 0.0 # Fill with zeros
targetColumnIndex += 1 # Move to the next column
paddingNumber += 1
#==========================================================================================
labelDict = dict()
for i in range(0,len(new_labels)):
labelDict[new_labels[i]]=i
return {
'label': new_labels,
'labelLookup': labelDict,
'body': new_body
}
if __name__== "__main__":
fileInput = sys.argv[1]
data = readCSVFile(fileInput,1.0,0)
data = functionThatFiltersOutColumnsWithStandardDeviation0(data)
# Append zero columns at specific labels
print("Disabled Paddings, to test all outputs trained together!")
#if ("lhand" in fileInput):
# labels_to_append_zero_columns = ['lhand_Wrotation', 'lthumb_Zrotation', 'finger1-2.l_Zrotation', 'finger1-3.l_Zrotation', 'finger1-3.l_Xrotation']
# data = functionThatAppendsZeroColumnsByLabels(data, labels_to_append_zero_columns, postFixPadding = 1)
column = 0
for label in data['label']:
thisColumnData = splitNumpyArray(data['body'],column,1,0)
minimum = np.min(thisColumnData)
maximum = np.max(thisColumnData)
median = np.median(thisColumnData)
mean = np.mean(thisColumnData)
std = np.std(thisColumnData)
var = np.var(thisColumnData)
title_string="%s : Min/Max=%0.2f/%0.2f,Median=%0.2f,Mean=%0.2f,Std=%0.2f,Var=%0.2f" % (label,minimum,maximum,median,mean,std,var)
print(title_string)
column = column + 1
print("Writing New CSV file to : compressed.csv")
writeCSVFile("compressed.csv",data)
#-----------------------------------------------------------
os.system("mv %s %s.uncompressed" % (fileInput,fileInput) )
os.system("mv compressed.csv %s" % (fileInput) )
print("Moved Old CSV file to : %s.uncompressed "%fileInput)
print("Moved New CSV file to : %s "%fileInput)
#-----------------------------------------------------------
+483
View File
@@ -0,0 +1,483 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
#pip install mediapipe pandas pillow matplotlib opencv-python
import cv2
import numpy as np
import time
import sys
import os
from readCSV import parseConfiguration,zeroOutXYJointsThatAreInvisible,performNSRMAlignment,splitNumpyArray
from NSDM import NSDMLabels,createNSDMUsingRules
from MocapNET import MocapNET,flipHorizontalInput
from tools import getDirectoryFromPath, checkIfFileExists, secondsToHz, eprint
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
class csvNET():
def __init__(self,
datasetDirectory = "dataset/generated",
dataFile = "face",
filenamePostfix = "_all",
fromCSV = "",
mem = 1.0,
outputMode = "bvh",
height = 1080,
width = 1920
):
#------------------------------------------
from readCSV import readCSVFile
if (fromCSV!=""):
self.data2D = readCSVFile("%s" % (fromCSV),mem,0)
self.dataBVH = dict()
else:
self.data2D = readCSVFile("%s/2d_%s%s.csv" % (datasetDirectory,dataFile,filenamePostfix),mem,0)
self.dataBVH = readCSVFile("%s/%s_%s%s.csv" % (datasetDirectory,outputMode,dataFile,filenamePostfix),mem,0)
#------------------------------------------
self.height = height
self.width = width
self.output = dict()
#------------------------------------------
self.error = dict()
self.error["body"] = list()
#------------------------------------------
self.rSquared = dict()
self.rSquared["body"] = list()
#------------------------------------------
self.responsesNN = dict()
self.responsesNN["body"] = list()
#------------------------------------------
def getNumberOfSamples(self):
numberOfSamples = self.data2D["body"].shape[0]
#numberOfOutputs = data["out"].shape[1]
return numberOfSamples
def get2DOutput(self):
return self.output
def registerNNResponse(self,outputToCompare,mocapNETResponse):
self.responsesNN["label"]=outputToCompare
thisRow = list()
for label in outputToCompare:
label = label.lower() # <- make it lowercase
thisRow.append(mocapNETResponse[label])
self.responsesNN["body"].append(thisRow)
def registerError(self,outputToCompare,mocapNETDifference):
self.error["label"]=outputToCompare
thisRow = list()
for label in outputToCompare:
label = label.lower() # <- make it lowercase
thisRow.append(mocapNETDifference[label])
self.error["body"].append(thisRow)
def saveCSVDataAsCSVFile(self,labelprefix,data,filename):
if (data) and ("label" in data) and ("body" in data):
print("Writting encountered error at ",filename)
f = open(filename, 'w')
#Write header
recordsWritten=0
for item in data["label"]:
if (recordsWritten>0):
f.write(',')
f.write("%s_%s" % (labelprefix,item)) #We prepend loss to make sure this is not used the wrong way..
recordsWritten=recordsWritten+1
f.write('\n')
#--------------------------------------------------------------------------------------------------
#Write body
for sample in range(0,len(data["body"])):
recordsWritten=0
for value in range(0,len(data["body"][sample])):
if (recordsWritten>0):
f.write(',')
f.write("%f" % (data["body"][sample][value]))
recordsWritten=recordsWritten+1
f.write('\n')
f.close()
print("Done writting ",filename)
#--------------------------------------------------------------------------------------------------
def saveErrorAsCSV(self,filename):
self.saveCSVDataAsCSVFile("loss",self.error,filename)
def saveResponseAsCSV(self,filename):
self.saveCSVDataAsCSVFile("NNOutput",self.responsesNN,filename)
def saveRSquared(self,filename):
if (self.dataBVH):
self.rSquared["label"] = self.dataBVH["label"]
thisResult = list()
column = 0
for columnName in self.dataBVH["label"]:
#We cut a single dimension as a 1 dim numpy array to make things easier..
singleOutputDimensionGroundTruth = splitNumpyArray(self.dataBVH["body"],column,1,0)
meanGroundTruth = np.mean(singleOutputDimensionGroundTruth)
#print(columnName," -> mean ",meanGroundTruth)
totalSumOfSquaresProportionalToTheVarianceOfData = 0.0
for sample in range(0,singleOutputDimensionGroundTruth.shape[0]):
totalSumOfSquaresProportionalToTheVarianceOfData = totalSumOfSquaresProportionalToTheVarianceOfData + ((singleOutputDimensionGroundTruth[sample][0] - meanGroundTruth) ** 2)
#print("Total Sum of Squares = ",totalSumOfSquaresProportionalToTheVarianceOfData," samples = ",singleOutputDimensionGroundTruth.shape[0])
sumOfSquaresOfResiduals = 0.0
for sample in range(0,len(self.error["body"])):
sumOfSquaresOfResiduals = sumOfSquaresOfResiduals + (self.error["body"][sample][column] ** 2)
#print("Sum of Squares of residuals = ",sumOfSquresOfResiduals," samples = ",len(self.error["body"]))
if (totalSumOfSquaresProportionalToTheVarianceOfData!=0.0):
rsquared = float( 1.0 - sumOfSquaresOfResiduals/totalSumOfSquaresProportionalToTheVarianceOfData )
print("R² for %s = %0.2f "%(columnName,rsquared))
thisResult.append(rsquared)
else:
print("R² for %s = NaN "%(columnName))
thisResult.append(float('nan'))
column = column + 1
results = list()
results.append(thisResult)
self.rSquared["body"] = results
self.saveCSVDataAsCSVFile("RSquared",self.rSquared,filename)
def compareToGroundTruth(self,fID,outputToCompare):
if (self.dataBVH):
count = 0
mocapNETOutput = dict()
mocapNETDifference = dict()
#--------------------------------------------------------------------------------------------------
for label in self.dataBVH["label"]:
label = label.lower() # <- make it lowercase
if (label in outputToCompare):
mocapNETOutput[label] = outputToCompare[label]
mocapNETDifference[label] = abs(self.dataBVH["body"][fID][count] - outputToCompare[label])
#print("For ",label," we regressed ",outputToCompare[label]," gt was ",self.dataBVH["body"][fID][count]," | loss -> ",mocapNETDifference[label] )
else:
print("Output ",label," missing")
mocapNETDifference[label] = abs(self.dataBVH["body"][fID][count])
count = count + 1
#-------- Automatically register error ----------------
self.registerError(outputToCompare,mocapNETDifference)
self.registerNNResponse(outputToCompare,mocapNETOutput)
#------------------------------------------------------
return mocapNETDifference
#--------------------------------------------------------------------------------------------------
else:
return float("nan")
def getMocapNETInputForFrameID(self,fID,img):
count = 0
mocapNETInput = dict()
for label in self.data2D["label"]:
label = label.lower() # <- make it lowercase
mocapNETInput[label] = self.data2D["body"][fID][count]
count = count + 1
#--------------------------------------------------------------------------------------------------
#annotated_image = np.zeros((self.height,self.width,3), np.uint8) #<- this is now provided to this function
#from MocapNETVisualization import drawMocapNETInput
#drawMocapNETInput(mocapNETInput,annotated_image)
#--------------------------------------------------------------------------------------------------
#print("Frame : ",fID," -> ",mocapNETInput)
from holisticPartNames import guessLandmarks
mocapNETInput = guessLandmarks(mocapNETInput)
#--------------------------------------------------------------------------------------------
self.output = mocapNETInput
#--------------------------------------------------------------------------------------------
return mocapNETInput,img
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
def calculate_relative_magnitudes(edm, n):
row_magnitudes = []
column_magnitudes = []
for i in range(n):
row_magnitude = sum(edm[i*n:(i+1)*n])
row_magnitudes.append(row_magnitude)
column_magnitude = sum(edm[i::n])
column_magnitudes.append(column_magnitude)
central_element = edm[n*n // 2]
row_magnitudes_sum = sum(row_magnitudes) - central_element
column_magnitudes_sum = sum(column_magnitudes) - central_element
max_magnitude = max(row_magnitudes_sum, column_magnitudes_sum)
relative_row_magnitudes = [m / max_magnitude for m in row_magnitudes]
relative_column_magnitudes = [m / max_magnitude for m in column_magnitudes]
return relative_row_magnitudes, relative_column_magnitudes
def getNSRMInterest(mnet,part=""):
from tools import appendCSVToFile
if part in mnet.ensemble:
NSRM = mnet.ensemble[part].NSRM
appendCSVToFile("study.csv",NSRM,fID=mnet.framesProcessed-1)
#row,column = calculate_relative_magnitudes(NSRM,int(np.sqrt(len(NSRM))))
#print("ROW ",row," COLUMN ",column)
#appendCSVToFile("study.csv",row,fID=mnet.framesProcessed-1)
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
def streamPosesFromCameraToMocapNET():
engine = "onnx"
headless = False
dataFile = "face"
whiteBkg = False
doProfiling = False
doMnetVisualization = True
doVisualization = True
csvFilePath = ""
saveVideo = False
flipHorizontal = False
doBody = True
doUpperbody = False, #<- These get auto activated if doBody=True
doLowerbody = False, #<- These get auto activated if doBody=True
doFace = False
doREye = False
doMouth = False
doHands = False
addNoise = 0.0
aspectCorrection = 1.0
scale = 1.0
mem = 1.0
windowDelay = 1
doHCDPostProcessing = 1
hcdLearningRate = 0.001
hcdEpochs = 30
hcdIterations = 15
plotBVHChannels = False
bvhAnglesForPlotting = list()
bvhAllAnglesForPlotting = list()
study = ""
calibrationFile = ""
keepColorImage = " && rm colorFrame_0_*.jpg "
keepPlotImage = " && rm plotFrame_0_*.jpg "
#python3 mediapipeHolisticWebcamMocapNET.py --from damien.avi --face --nobody --plot --save
#python3 -m csvNET --from ammarFaceFar.csv --study face --face --nobody
# python3 -m csvNET --from ammarFaceFar.csv --mouth --reye --nobody --plot --save
#Visually inspect validation set :
#python3 -m csvNET --from dataset/generated/2d_body_all_test.csv --noik
#python3 -m csvNET --from dataset/generated/2d_body_all_test.csv
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--headless"):
headless = True
if (sys.argv[i]=="--nomnetvisualization"):
doMnetVisualization = False
if (sys.argv[i]=="--novisualization"):
doVisualization = False
if (sys.argv[i]=="--ik"):
hcdLearningRate = float(sys.argv[i+1])
hcdEpochs = int(sys.argv[i+2])
hcdIterations = int(sys.argv[i+3])
if (sys.argv[i]=="--noik"):
doHCDPostProcessing = 0
if (sys.argv[i]=="--aspectCorrection"):
aspectCorrection=float(sys.argv[i+1])
if (sys.argv[i]=="--noise"):
addNoise=float(sys.argv[i+1])
if (sys.argv[i]=="--scale"):
scale=float(sys.argv[i+1])
if (sys.argv[i]=="--calib"):
calibrationFile = sys.argv[i+1]
if (sys.argv[i]=="--study"):
study = sys.argv[i+1]
if (sys.argv[i]=="--flipHorizontal"):
flipHorizontal = True
if (sys.argv[i]=="--plot"):
plotBVHChannels=True
if (sys.argv[i]=="--all"):
doBody=True
doREye=True
doMouth=True
doHands=True
if (sys.argv[i]=="--nobody"):
doBody = False
doUpperbody = False
doLowerbody = False
if (sys.argv[i]=="--upperbody"):
doBody = False
doUpperbody = True
if (sys.argv[i]=="--lowerbody"):
doBody = False
doLowerbody = True
if (sys.argv[i]=="--face"):
doFace=True
dataFile="face" #Use 2d_face_all.csv as input if not --from is activated
if (sys.argv[i]=="--reye"):
doREye=True
dataFile="reye" #Use 2d_reye_all.csv as input if not --from is activated
if (sys.argv[i]=="--mouth"):
doMouth=True
dataFile="mouth" #Use 2d_mouth_all.csv as input if not --from is activated
if (sys.argv[i]=="--hands"):
doHands=True
if (sys.argv[i]=="--white"):
whiteBkg = True
if (sys.argv[i]=="--keep"):
keepColorImage = " "
keepPlotImage = " "
if (sys.argv[i]=="--save"):
saveVideo=True
if (sys.argv[i]=="--engine"):
engine=sys.argv[i+1]
print("Selecting engine : ",engine)
if (sys.argv[i]=="--from"):
csvFilePath=sys.argv[i+1]
if (sys.argv[i]=="--profile"):
doProfiling=True
if (sys.argv[i]=="--mem"):
mem=int(sys.argv[i+1])
if (sys.argv[i]=="--delay"):
windowDelay=int(sys.argv[i+1])
from MocapNETVisualization import drawMocapNETOutput,drawDescriptor,drawNSRM,drawMAE2DError,drawMocapNETAllPlots
#Select a MocapNET class from tensorflow/tensorrt/onnx/tf-lite engines
from MocapNET import easyMocapNETConstructor
mnet = easyMocapNETConstructor(
engine,
doProfiling=doProfiling,
doHCDPostProcessing=doHCDPostProcessing,
hcdLearningRate=hcdLearningRate,
hcdEpochs = hcdEpochs,
hcdIterations = hcdIterations,
bvhScale=scale,
doBody=doBody,
doUpperbody=doUpperbody,
doLowerbody=doLowerbody,
doFace=doFace,
doREye=doREye,
doMouth=doMouth,
doHands=doHands,
addNoise=addNoise
)
mnet.test()
mnet.recordBVH(True)
#Body only
mp = csvNET(mem=mem,dataFile=dataFile,fromCSV=csvFilePath)
from folderStream import FolderStreamer
baseNameForFolderThatMayContainImages = getDirectoryFromPath(csvFilePath)
print("baseNameForFolderThatMayContainImages = ",baseNameForFolderThatMayContainImages)
imageStream = FolderStreamer(path=baseNameForFolderThatMayContainImages)
if (checkIfFileExists("%s/color.calib" % baseNameForFolderThatMayContainImages)):
mnet.bvh.configureRendererFromFile("%s/color.calib"%baseNameForFolderThatMayContainImages)
if (calibrationFile!=""):
print("Enforcing Calibration file : ",calibrationFile)
mnet.bvh.configureRendererFromFile(calibrationFile)
from MocapNETVisualization import visualizeMocapNETEnsemble
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
print("\n\n\n\nStarting MocapNET using CSV 2D Input")
print("Please wait until input processing finishes!")
for frameNumber in range(0, mp.getNumberOfSamples() ):
#attempt to visualize (!)
#--------------------------------------------------------------------------------------------------------------
success,img = imageStream.read()
if (not success):
if (whiteBkg):
annotated_image = np.full((mp.height,mp.width,3), 255, dtype=np.uint8)
else:
annotated_image = np.zeros((mp.height,mp.width,3), np.uint8)
else:
annotated_image = img
#--------------------------------------------------------------------------------------------------------------
start = time.time() # Time elapsed
mocapNETInput,annotated_image = mp.getMocapNETInputForFrameID(frameNumber,annotated_image)
#--------------------------------------------------------------------------------------------------------------
if (flipHorizontal):
mocapNETInput = flipHorizontalInput(mocapNETInput)
#--------------------------------------------------------------------------------------------------------------
mocapNET3DOutput = mnet.predict3DJoints(mocapNETInput)
mocapNETBVHOutput = mnet.outputBVH
getNSRMInterest(mnet,part=study)
difference = mp.compareToGroundTruth(frameNumber,mocapNETBVHOutput)
#print("Frame ",frameNumber," difference ~=> ",difference)
#print("Frame ",frameNumber,"/",mp.getNumberOfSamples())
bvhAnglesForPlotting.append(mocapNETBVHOutput)
bvhAllAnglesForPlotting.append(mocapNETBVHOutput)
if (len(bvhAnglesForPlotting)>100):
bvhAnglesForPlotting.pop(0)
if (doVisualization):
#--------------------------------------------------------------------------------------------------------------
annotated_image,plotImage = visualizeMocapNETEnsemble(mnet,annotated_image,plotBVHChannels=plotBVHChannels,bvhAnglesForPlotting=bvhAnglesForPlotting,drawOutput=doMnetVisualization)
#--------------------------------------------------------------------------------------------------------------
mnet.printStatus()
if (saveVideo):
cv2.imwrite('colorFrame_0_%05u.jpg'%(frameNumber), annotated_image)
if (plotBVHChannels):
cv2.imwrite('plotFrame_0_%05u.jpg'%(frameNumber), plotImage)
#--------------------------------------------------------------------------------------------------------------
if not headless:
cv2.imshow('MocapNET 4 using CSV Data Holistic 2D Joints', annotated_image)
if (plotBVHChannels):
cv2.imshow('MocapNET 4 using CSV Data Holistic Motion History',plotImage)
if cv2.waitKey(1) & 0xFF == 27:
break
#--------------------------------------------------------------------------------------------------------------
if (csvFilePath == ""):
#This uses MATPLOTLIB and is very slow
#only emmit this when working with ground truth and not an ad hoc CSV file
from MocapNETVisualization import drawMocapNETFrequencyPlots
drawMocapNETFrequencyPlots(bvhAllAnglesForPlotting)
#--------------------------------------------------------------------------------------------------------------
#Finished
#==========================
mp.saveErrorAsCSV("loss.csv")
mp.saveResponseAsCSV("freq.csv")
mp.saveRSquared("rSquared.csv")
if (doVisualization) and (saveVideo):
os.system("ffmpeg -framerate 30 -i colorFrame_0_%%05d.jpg -s 1200x720 -y -r 30 -pix_fmt yuv420p -threads 8 livelastRun3DHiRes.mp4 %s" % keepColorImage)
if (plotBVHChannels):
os.system("ffmpeg -framerate 30 -i plotFrame_0_%%05d.jpg -s 1200x720 -y -r 30 -pix_fmt yuv420p -threads 8 livelastPlot3DHiRes.mp4 %s" % keepPlotImage)
del mnet #So that the out.bvh file gets created..
if (csvFilePath != ""):
os.system("rm 2d_out.csv 3d_out.csv bvh_out.csv map_out.csv")
os.system("./GroundTruthDumper --from out.bvh --setPositionRotation -2.6 0 2000 0 0 0 --csv ./ out.csv 2d+3d+bvh ") # Remove noise offsetPositionRotation
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
#TEST
#python3 -m csvNET --nobody --face
if __name__ == '__main__':
streamPosesFromCameraToMocapNET()
@@ -0,0 +1,783 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import sys
import os
import numpy as np
#python3 principleComponentAnalysisTester.py --config dataset/body_configuration.json --mem 1000 --highlight 4 --mode 3
#python3 principleComponentAnalysisTool.py --config dataset/body_configuration.json --all body --mem 1000 --show --type sparsepca
#python3 principleComponentAnalysisTool.py --config dataset/upperbody_configuration.json --all upperbody --mem 1000 --show --type factoranalysis
class EmptyDecomposition:
def __init__(self,):
self.decompositionType = ""
def ok(self):
return True
def fit(self,data):
pass
def transform(self,data,selectedPCADimensions=0):
return data
def save(self,filename):
return True
def load(self,filename):
return True
#------------------------------------------------------------------
#------------------------------------------------------------------
#------------------------------------------------------------------
def getSKPCA_Decomposer(numberOfDimensions=20):
from sklearn.decomposition import PCA
engine = PCA(n_components=numberOfDimensions)
return engine
def getTruncatedSVD_Decomposer(numberOfDimensions=20):
from sklearn.decomposition import TruncatedSVD
engine = TruncatedSVD(n_components=numberOfDimensions)
return engine
def getLatentDirichletAllocation_Decomposer(numberOfDimensions=20):
from sklearn.decomposition import LatentDirichletAllocation
engine = LatentDirichletAllocation(n_components=numberOfDimensions)
return engine
def getFactorAnalysis_Decomposer(numberOfDimensions=20):
from sklearn.decomposition import FactorAnalysis
engine = FactorAnalysis(n_components=numberOfDimensions)
return engine
def getDictionaryLearning_Decomposer(numberOfDimensions=20):
from sklearn.decomposition import DictionaryLearning
engine = DictionaryLearning(n_components=numberOfDimensions)
return engine
def getFastICA_Decomposer(numberOfDimensions=20):
from sklearn.decomposition import FastICA
engine = FastICA(n_components=numberOfDimensions)
return engine
def getNMF_Decomposer(numberOfDimensions=20):
from sklearn.decomposition import NMF
engine = NMF(n_components=numberOfDimensions)
return engine
def getIncrementalPCA_Decomposer(numberOfDimensions=20):
from sklearn.decomposition import IncrementalPCA
engine = IncrementalPCA(n_components=numberOfDimensions)
return engine
def getSparsePCA_Decomposer(numberOfDimensions=20):
from sklearn.decomposition import SparsePCA
engine = SparsePCA(n_components=numberOfDimensions)
return engine
def getTSNE_Decomposer(numberOfDimensions=20):
from sklearn.manifold import TSNE
engine = TSNE(n_components=numberOfDimensions,perplexity=100, learning_rate=100, verbose=2, n_iter=350)
return engine
#------------------------------------------------------------------
#------------------------------------------------------------------
#------------------------------------------------------------------
class Decomposition():
def __init__(self,
inputData:np.array=np.array([]),
savedFile:str="",
decompositionType:str="pca",
selectedPCADimensions:int=0
):
self.disabledDecomposition = False
self.numberOfSamplesFittedOn = 0
self.decompositionType = decompositionType
self.noTransformFunction = 0 #Some methods dont have a transform function
self.trackedFiles = list() #<- all needed files should be tracked here
if (selectedPCADimensions==0):
self.numberOfSamplesFittedOn = inputData.shape[0]
else:
self.numberOfSamplesFittedOn = selectedPCADimensions
import sklearn
print("Decomposition code using Sk-Learn : ",sklearn.__version__)
print("Will try to perform : ",self.decompositionType)
#self.engine = getSKPCA_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
from sklearn.preprocessing import StandardScaler
self.scaler = StandardScaler()
if (self.decompositionType==""):
print("Not Performing any decomposition")
self.disabledDecomposition = True
return;
elif (self.decompositionType=="skpca"):
self.engine = getSKPCA_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
elif (self.decompositionType=="sparsepca"):
self.engine = getSparsePCA_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
elif (self.decompositionType=="incrementalpca"):
self.engine = getIncrementalPCA_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
elif (self.decompositionType=="fastica"):
self.engine = getFastICA_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
elif (self.decompositionType=="nmf"):
self.engine = getNMF_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
elif (self.decompositionType=="dictionary"):
self.engine = getDictionaryLearning_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
elif (self.decompositionType=="factoranalysis"):
self.engine = getFactorAnalysis_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
elif (self.decompositionType=="dirichlet"):
self.engine = getLatentDirichletAllocation_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
elif (self.decompositionType=="svd"):
self.engine = getTruncatedSVD_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
elif (self.decompositionType=="tsne"):
self.engine = getTSNE_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
self.noTransformFunction = 1
elif (self.decompositionType!="pca"):
print("Could not understand decomposition Type ",self.decompositionType)
sys.exit(1)
else:
print("Using SK code for decomposition Type ",self.decompositionType)
self.engine = getSKPCA_Decomposer(numberOfDimensions=self.numberOfSamplesFittedOn)
if (savedFile!=""):
print("Loading existing fitted decomposition from ",savedFile,"..!")
self.load(savedFile)
elif (inputData.size!=0):
print("Generating new fit..!")
self.fit(inputData)
else:
print("No Decomposition input given..!")
def ok(self):
return self.numberOfSamplesFittedOn!=0
def getNumberOfExpectedSamples(self):
return self.numberOfSamplesFittedOn
def fit(self,data):
import time
startAt = time.time()
#----------------------------------------------------------------------------------------
self.numberOfSamplesFittedOn = data.shape[0]
self.scaler.fit(data)
dataTransformed = self.scaler.transform(data)
outputData = self.engine.fit_transform(dataTransformed)
#----------------------------------------------------------------------------------------
endAt = time.time()
print("Time required to fit ",self.decompositionType," was ",(endAt-startAt)/60," mins")
return outputData
def transform(self,data,selectedPCADimensions=0):
if (self.disabledDecomposition):
return data
#if (selectedPCADimensions!=self.numberOfSamplesFittedOn):
# print("INCONSISTENT TRANSFORM")
if (selectedPCADimensions==0):
if (self.noTransformFunction):
dataTransformed = self.scaler.fit_transform(data)
return self.engine.fit_transform(dataTransformed)
else:
dataTransformed = self.scaler.transform(data)
return self.engine.transform(dataTransformed)
else:
if (self.noTransformFunction):
dataTransformed = self.scaler.fit_transform(data)
return self.engine.fit_transform(dataTransformed)[:,:selectedPCADimensions] # ,n_components=selectedPCADimensions
else:
dataTransformed = self.scaler.transform(data)
return self.engine.transform(dataTransformed)[:,:selectedPCADimensions] # ,n_components=selectedPCADimensions
def save(self,filename):
print("Saving Decomposition to ",filename)
OKGREEN = '\033[92m'
FAIL = '\033[91m'
ENDC = '\033[0m'
import pickle
self.trackedFiles = list()
successfulSaves = 0
#---------------------------------------------------------------
pathToEngine = "%s.%s" % (filename,self.decompositionType)
with open(pathToEngine,'wb') as engineFile:
self.trackedFiles.append(pathToEngine)
print(OKGREEN,"Saving Decomposition Engine to ",pathToEngine,ENDC)
pickle.dump(self.engine,engineFile)
successfulSaves = successfulSaves + 1
#---------------------------------------------------------------
pathToScaler = "%s.scaler.%s" % (filename,self.decompositionType)
with open(pathToScaler,'wb') as scalerFile:
self.trackedFiles.append(pathToScaler)
print(OKGREEN,"Saving Decomposition Scaler to ",pathToScaler,ENDC)
pickle.dump(self.scaler,scalerFile)
successfulSaves = successfulSaves + 1
#---------------------------------------------------------------
return (successfulSaves==2)
def load(self,filename):
print("Loading Decomposition from ",filename)
OKGREEN = '\033[92m'
FAIL = '\033[91m'
ENDC = '\033[0m'
import pickle
self.trackedFiles = list()
successfulLoads = 0
#---------------------------------------------------------------
pathToEngine = "%s.%s" % (filename,self.decompositionType)
if (os.path.isfile(pathToEngine)):
self.trackedFiles.append(pathToEngine)
unpickleEngine = open(pathToEngine, 'rb')
print(OKGREEN,"Loaded Decomposition Engine from ",pathToEngine,ENDC)
self.engine = pickle.load(unpickleEngine) #, encoding='bytes'
successfulLoads = successfulLoads + 1
else:
print(FAIL,"Failed Loading Decomposition Engine from ",pathToEngine,ENDC)
#---------------------------------------------------------------
pathToScaler = "%s.scaler.%s" % (filename,self.decompositionType)
if (os.path.isfile(pathToEngine)):
self.trackedFiles.append(pathToScaler)
unpickleScaler = open(pathToScaler, 'rb')
print(OKGREEN,"Loading Decomposition Scaler from ",pathToScaler,ENDC)
self.scaler = pickle.load(unpickleScaler) #, encoding='bytes'
successfulLoads = successfulLoads + 1
else:
print(FAIL,"Failed Loading Decomposition Scaler from ",pathToScaler,ENDC)
#---------------------------------------------------------------
return (successfulLoads==2)
def visualize(self,data,saveToFile="",onlyScreePlotNDimensions=0,label="PCA",colors=list(),colorLabel="Highlighting PC-4",viewAzimuth=45,viewElevation=45,showScree=0):
import matplotlib
import matplotlib.pyplot as plt
font = {'family' : 'normal',
'weight' : 'bold',
'size' : 28 }
plt.rc('font', **font)
plt.rc('xtick', labelsize=15)
plt.rc('ytick', labelsize=15)
# === Plot =========================================================================
fig = plt.figure()
fig.set_size_inches(19.2, 10.8, forward=True)
ax1 = fig.add_subplot(1, 1, 1,projection='3d')
#===================================================================================
#Number of PCA components to plot on first plot (our plot is 3D so max is 4 if we dont have a color ..! )
keepNDimensions = 3
if (len(colors)==0):
keepNDimensions = 4
#Do transform of our input using the PCA dimensions as new basis
#===================================================================================
transformedData = self.transform(data,selectedPCADimensions=keepNDimensions).real
#print("TRANSFORMED DATA : ",transformedData)
print("TRANSFORMED DATA")
print("Number of Samples : ",transformedData.shape[0])
print("Number of Dimensions : ",transformedData.shape[1])
#===================================================================================
if (len(colors)==0):
if (transformedData.shape[1]<4):
print("Not enough dimensions to plot color")
keepNDimensions = 3
else:
colors = transformedData[:,3]
colorLabel = "highlighting PC-4"
else:
print("Using provided set of colorValues")
keepNDimensions = 3
ax1.view_init(viewAzimuth,viewElevation)
#===================================================================================
if (len(colors)==0):
ax1.scatter(transformedData[:,0],transformedData[:,1],transformedData[:,2],c='red')
else:
scatter = ax1.scatter(transformedData[:,0],transformedData[:,1],transformedData[:,2],c=colors,label=colors)
ax1.legend(*scatter.legend_elements(num=5),loc="upper right", title="Values", fontsize="x-small", framealpha=0.4)
#===================================================================================
# Adding title, xlabel and ylabel
ax1.set_title('%s %s %s '%(self.decompositionType,label,colorLabel)) # Title of the plot
ax1.set_xlabel('PC-1',labelpad=30) # X-Label
ax1.set_ylabel('PC-2',labelpad=30) # Y-Label
ax1.set_zlabel('PC-3',labelpad=30) # Z-Label
#ax1.tick_params(axis='x', pad=5) #fine tune numbers of plot
plt.subplots_adjust(left=0.05, right=0.95, top=0.95, bottom=0.08)
if (saveToFile!=""):
print("Saving Figure to output file %s" % saveToFile)
fig.savefig(saveToFile)
else:
plt.show()
if __name__ == '__main__':
print("principleComponentAnalysis.py is a library")
decomp = Decomposition(savedFile='dataset/combinedModel/mocapnet4/mode1/1.0/step1_upperbody_all/upperbody_all.pca',decompositionType='pca')
sample = list()
sample.append(0.470052) #0
sample.append(0.452315) #1
sample.append(1.000000) #2
sample.append(0.479688) #3
sample.append(0.239352) #4
sample.append(1.000000) #5
sample.append(0.520312) #6
sample.append(0.185185) #7
sample.append(1.000000) #8
sample.append(0.519271) #9
sample.append(0.173148) #10
sample.append(1.000000) #11
sample.append(0.000000) #12
sample.append(0.000000) #13
sample.append(0.000000) #14
sample.append(0.450000) #15
sample.append(0.238889) #16
sample.append(1.000000) #17
sample.append(0.422917) #18
sample.append(0.337037) #19
sample.append(1.000000) #20
sample.append(0.000000) #21
sample.append(0.000000) #22
sample.append(0.000000) #23
sample.append(0.509375) #24
sample.append(0.239815) #25
sample.append(1.000000) #26
sample.append(0.500000) #27
sample.append(0.362963) #28
sample.append(1.000000) #29
sample.append(0.000000) #30
sample.append(0.000000) #31
sample.append(0.000000) #32
sample.append(0.652332) #33
sample.append(0.283472) #34
sample.append(0.547378) #35
sample.append(0.213181) #36
sample.append(0.536087) #37
sample.append(0.077135) #38
sample.append(0.214366) #39
sample.append(0.509478) #40
sample.append(0.095500) #41
sample.append(0.029691) #42
sample.append(0.167750) #43
sample.append(0.522894) #44
sample.append(0.141564) #45
sample.append(0.065052) #46
sample.append(0.050908) #47
sample.append(0.124542) #48
sample.append(0.540789) #49
sample.append(0.190115) #50
sample.append(0.112984) #51
sample.append(0.101816) #52
sample.append(0.050908) #53
sample.append(0.383942) #54
sample.append(0.270394) #55
sample.append(0.307847) #56
sample.append(0.277424) #57
sample.append(0.248705) #58
sample.append(0.254739) #59
sample.append(0.270394) #60
sample.append(0.652332) #61
sample.append(0.000000) #62
sample.append(0.547378) #63
sample.append(0.536087) #64
sample.append(0.509478) #65
sample.append(0.522894) #66
sample.append(0.540789) #67
sample.append(0.270394) #68
sample.append(0.212132) #69
sample.append(0.440391) #70
sample.append(0.248585) #71
sample.append(0.182055) #72
sample.append(0.155387) #73
sample.append(0.126341) #74
sample.append(0.113851) #75
sample.append(0.174184) #76
sample.append(0.440391) #77
sample.append(0.212132) #78
sample.append(0.678899) #79
sample.append(0.152507) #80
sample.append(0.143071) #81
sample.append(0.171002) #82
sample.append(0.175392) #83
sample.append(0.193561) #84
sample.append(0.419609) #85
sample.append(0.678899) #86
sample.append(0.300000) #87
sample.append(0.216108) #88
sample.append(0.563004) #89
sample.append(0.067397) #90
sample.append(0.029691) #91
sample.append(0.059382) #92
sample.append(0.087379) #93
sample.append(0.130105) #94
sample.append(0.306329) #95
sample.append(0.563004) #96
sample.append(0.209537) #97
sample.append(0.116016) #98
sample.append(0.154849) #99
sample.append(0.587831) #100
sample.append(0.129067) #101
sample.append(0.066885) #102
sample.append(0.083048) #103
sample.append(0.069538) #104
sample.append(0.089203) #105
sample.append(0.321928) #106
sample.append(0.587831) #107
sample.append(0.192741) #108
sample.append(0.107269) #109
sample.append(0.061752) #110
sample.append(0.094237) #111
sample.append(0.617853) #112
sample.append(0.190791) #113
sample.append(0.125269) #114
sample.append(0.133770) #115
sample.append(0.098298) #116
sample.append(0.081326) #117
sample.append(0.347944) #118
sample.append(0.617853) #119
sample.append(0.194984) #120
sample.append(0.131074) #121
sample.append(0.123504) #122
sample.append(0.061752) #123
sample.append(0.348961) #124
sample.append(0.308926) #125
sample.append(0.269400) #126
sample.append(0.236866) #127
sample.append(0.208076) #128
sample.append(0.214721) #129
sample.append(0.232589) #130
sample.append(0.040663) #131
sample.append(0.308926) #132
sample.append(0.143338) #133
sample.append(0.378955) #134
sample.append(0.265854) #135
sample.append(0.281502) #136
sample.append(0.308926) #137
sample.append(0.652332) #138
sample.append(0.000000) #139
sample.append(0.547378) #140
sample.append(0.536087) #141
sample.append(0.509478) #142
sample.append(0.522894) #143
sample.append(0.540789) #144
sample.append(0.270394) #145
sample.append(0.000000) #146
sample.append(0.440391) #147
sample.append(0.678899) #148
sample.append(0.563004) #149
sample.append(0.587831) #150
sample.append(0.617853) #151
sample.append(0.308926) #152
sample.append(0.106590) #153
sample.append(0.587454) #154
sample.append(0.178302) #155
sample.append(0.106590) #156
sample.append(0.109798) #157
sample.append(0.069458) #158
sample.append(0.052693) #159
sample.append(0.317531) #160
sample.append(0.587454) #161
sample.append(0.166465) #162
sample.append(0.146195) #163
sample.append(0.111492) #164
sample.append(0.053520) #165
sample.append(0.030413) #166
sample.append(0.278528) #167
sample.append(0.587454) #168
sample.append(3.096379) #169
sample.append(0.651328) #170
sample.append(5.955375) #171
sample.append(6.084674) #172
sample.append(-0.059619) #173
sample.append(0.048326) #174
sample.append(0.234845) #175
sample.append(0.585668) #176
sample.append(0.651328) #177
sample.append(0.686142) #178
sample.append(5.398531) #179
sample.append(5.946909) #180
sample.append(5.904308) #181
sample.append(5.806487) #182
sample.append(0.529019) #183
sample.append(0.651328) #184
sample.append(6.084674) #185
sample.append(3.792921) #186
sample.append(3.694669) #187
sample.append(4.237240) #188
sample.append(4.096264) #189
sample.append(4.071058) #190
sample.append(3.975877) #191
sample.append(3.886222) #192
sample.append(3.886222) #193
sample.append(0.000000) #194
sample.append(3.776154) #195
sample.append(4.110508) #196
sample.append(4.119073) #197
sample.append(4.020748) #198
sample.append(3.931176) #199
sample.append(3.931177) #200
sample.append(0.000000) #201
sample.append(3.929643) #202
sample.append(2.813782) #203
sample.append(1.095648) #204
sample.append(3.325809) #205
sample.append(2.449419) #206
sample.append(2.176756) #207
sample.append(2.363436) #208
sample.append(2.456802) #209
sample.append(1.402459) #210
sample.append(1.095648) #211
sample.append(2.003560) #212
sample.append(3.639651) #213
sample.append(2.840933) #214
sample.append(2.875062) #215
sample.append(2.887117) #216
sample.append(1.448436) #217
sample.append(1.095648) #218
sample.append(2.736625) #219
sample.append(2.943081) #220
sample.append(0.954672) #221
sample.append(5.591012) #222
sample.append(3.255518) #223
sample.append(1.401905) #224
sample.append(2.261431) #225
sample.append(2.461843) #226
sample.append(1.159315) #227
sample.append(0.954672) #228
sample.append(1.819818) #229
sample.append(4.163903) #230
sample.append(4.543498) #231
sample.append(3.371371) #232
sample.append(3.151165) #233
sample.append(1.170683) #234
sample.append(0.954672) #235
sample.append(2.943081) #236
sample.append(3.081973) #237
sample.append(0.929466) #238
sample.append(5.318349) #239
sample.append(4.543498) #240
sample.append(3.256703) #241
sample.append(2.719052) #242
sample.append(2.719052) #243
sample.append(1.130633) #244
sample.append(0.929466) #245
sample.append(1.897446) #246
sample.append(4.228285) #247
sample.append(4.543498) #248
sample.append(3.707124) #249
sample.append(3.371372) #250
sample.append(1.137976) #251
sample.append(0.929466) #252
sample.append(3.216783) #253
sample.append(3.189919) #254
sample.append(0.834284) #255
sample.append(5.505028) #256
sample.append(5.403023) #257
sample.append(5.860644) #258
sample.append(3.256703) #259
sample.append(2.719052) #260
sample.append(0.929466) #261
sample.append(0.834284) #262
sample.append(1.597937) #263
sample.append(4.522202) #264
sample.append(5.142685) #265
sample.append(4.364796) #266
sample.append(3.691174) #267
sample.append(0.898620) #268
sample.append(0.834284) #269
sample.append(3.574276) #270
sample.append(3.376438) #271
sample.append(0.744629) #272
sample.append(5.598395) #273
sample.append(5.603435) #274
sample.append(5.860644) #275
sample.append(5.860644) #276
sample.append(3.166879) #277
sample.append(0.744629) #278
sample.append(0.744629) #279
sample.append(1.183479) #280
sample.append(4.781023) #281
sample.append(5.403024) #282
sample.append(4.970201) #283
sample.append(4.234641) #284
sample.append(0.684905) #285
sample.append(0.744629) #286
sample.append(4.391370) #287
sample.append(3.727261) #288
sample.append(0.744629) #289
sample.append(4.544052) #290
sample.append(4.300908) #291
sample.append(4.272226) #292
sample.append(4.071058) #293
sample.append(3.886222) #294
sample.append(3.166879) #295
sample.append(0.744629) #296
sample.append(3.604797) #297
sample.append(4.254323) #298
sample.append(4.324193) #299
sample.append(4.133639) #300
sample.append(3.966107) #301
sample.append(4.234641) #302
sample.append(0.744629) #303
sample.append(3.966615) #304
sample.append(3.792921) #305
sample.append(0.000000) #306
sample.append(4.237240) #307
sample.append(4.096264) #308
sample.append(4.071058) #309
sample.append(3.975877) #310
sample.append(3.886222) #311
sample.append(3.886222) #312
sample.append(3.694669) #313
sample.append(3.776154) #314
sample.append(4.110508) #315
sample.append(4.119073) #316
sample.append(4.020748) #317
sample.append(3.931176) #318
sample.append(3.931177) #319
sample.append(0.000000) #320
sample.append(3.929643) #321
sample.append(3.827735) #322
sample.append(0.634561) #323
sample.append(5.145152) #324
sample.append(4.961411) #325
sample.append(5.039039) #326
sample.append(4.739530) #327
sample.append(4.325072) #328
sample.append(0.463204) #329
sample.append(0.634561) #330
sample.append(0.000000) #331
sample.append(4.613133) #332
sample.append(4.903871) #333
sample.append(4.607087) #334
sample.append(4.287396) #335
sample.append(0.295320) #336
sample.append(0.634561) #337
sample.append(4.346044) #338
sample.append(2.256939) #339
sample.append(0.968915) #340
sample.append(0.498058) #341
sample.append(1.022310) #342
sample.append(1.086692) #343
sample.append(1.380610) #344
sample.append(1.639430) #345
sample.append(1.112731) #346
sample.append(0.968915) #347
sample.append(1.471541) #348
sample.append(0.000000) #349
sample.append(0.927337) #350
sample.append(1.482404) #351
sample.append(1.967686) #352
sample.append(1.114843) #353
sample.append(0.968915) #354
sample.append(1.776775) #355
sample.append(2.805316) #356
sample.append(0.977481) #357
sample.append(5.982525) #358
sample.append(1.401905) #359
sample.append(1.401905) #360
sample.append(2.001093) #361
sample.append(2.261431) #362
sample.append(1.182600) #363
sample.append(0.977481) #364
sample.append(1.762278) #365
sample.append(4.068930) #366
sample.append(3.258445) #367
sample.append(2.912313) #368
sample.append(2.912314) #369
sample.append(1.196280) #370
sample.append(0.977481) #371
sample.append(2.673644) #372
sample.append(2.762715) #373
sample.append(0.879156) #374
sample.append(6.016655) #375
sample.append(0.229778) #376
sample.append(0.565532) #377
sample.append(1.223204) #378
sample.append(1.828609) #379
sample.append(0.992046) #380
sample.append(0.879156) #381
sample.append(1.465495) #382
sample.append(4.623997) #383
sample.append(6.053906) #384
sample.append(3.258445) #385
sample.append(2.912314) #386
sample.append(0.977481) #387
sample.append(0.879156) #388
sample.append(2.397369) #389
sample.append(2.664894) #390
sample.append(0.789584) #391
sample.append(6.028709) #392
sample.append(0.009572) #393
sample.append(0.229779) #394
sample.append(0.549582) #395
sample.append(1.093048) #396
sample.append(0.824514) #397
sample.append(0.789584) #398
sample.append(1.145804) #399
sample.append(5.109279) #400
sample.append(6.053906) #401
sample.append(6.053907) #402
sample.append(3.136574) #403
sample.append(0.789584) #404
sample.append(0.789584) #405
sample.append(0.819205) #406
sample.append(3.670611) #407
sample.append(0.789584) #408
sample.append(4.590029) #409
sample.append(4.312276) #410
sample.append(4.279569) #411
sample.append(4.040213) #412
sample.append(3.826498) #413
sample.append(1.093048) #414
sample.append(0.789584) #415
sample.append(3.436912) #416
sample.append(4.256435) #417
sample.append(4.337873) #418
sample.append(4.119073) #419
sample.append(3.931176) #420
sample.append(3.136574) #421
sample.append(0.789584) #422
sample.append(3.927943) #423
sample.append(3.792921) #424
sample.append(0.000000) #425
sample.append(4.237240) #426
sample.append(4.096264) #427
sample.append(4.071058) #428
sample.append(3.975877) #429
sample.append(3.886222) #430
sample.append(3.886222) #431
sample.append(0.000000) #432
sample.append(3.776154) #433
sample.append(4.110508) #434
sample.append(4.119073) #435
sample.append(4.020748) #436
sample.append(3.931176) #437
sample.append(3.931177) #438
sample.append(3.694669) #439
sample.append(3.929643) #440
sample.append(2.943082) #441
sample.append(0.788050) #442
sample.append(5.878218) #443
sample.append(6.084674) #444
sample.append(0.075190) #445
sample.append(0.432683) #446
sample.append(1.249777) #447
sample.append(0.825022) #448
sample.append(0.788050) #449
sample.append(1.204451) #450
sample.append(4.918368) #451
sample.append(5.815236) #452
sample.append(5.538962) #453
sample.append(3.960798) #454
sample.append(0.786350) #455
sample.append(0.788050) #456
sample.append(3.255518) #457
out = decomp.transform(np.asarray(sample),selectedPCADimensions=210)
for i in range(0,len(out)):
print(i," = ",out[i])
@@ -0,0 +1,373 @@
{
"version": "3.0",
"backend": "mnet3",
"precision": "fp32",
"outputMode": "bvh",
"BVH": "headerWithHeadAndOneMotion.bvh",
"OutputDirectory": "body",
"veryHighNumberOfEpochs": 60,
"highNumberOfEpochs": 45,
"defaultNumberOfEpochs": 30,
"defaultBatchSize": 128,
"learningRate": 0.00025,
"minEarlyStoppingDelta": 0.01,
"setConstantSeedForReproducibleTraining": 0,
"activationFunction": "swish",
"weightRandomizationFunction": "glorot_uniform",
"optimizer": "rmsprop",
"dropoutRate": 0.20,
"lamda": 2.0,
"useQuadLoss": 0,
"useSquaredLoss": 1,
"earlyStoppingPatience": 4,
"rememberWeights": 1,
"rememberConsecutiveWeights": 0,
"useOnlineHardExampleMining": 0,
"hardMiningEpochs": 5,
"normalMiningEpochs": 2,
"groupOutputs": 1,
"ignoreOcclusions": 0,
"NSDMNormalizationMasterSwitch": 0,
"NSDMAlsoUseAlignmentAngles": 1,
"neuralNetworkDepth": 12,
"EDM" : 0,
"eNSRM": 1,
"eigenPoses": 0,
"autobuilder": 0,
"skipConnections": 1,
"decompositionType": "",
"doPCA": "",
"balanced2DInputs": 0,
"include2DInputVisibilityFlags": 0,
"PCADimensionsKept": 210,
"PCAAlsoKeepRawData": 0,
"padEnsembleInput": 0,
"probabilisticOutput": 0,
"filterOutEmptySamples": 1,
"outputValueDistribution": "balanced",
"outputNormalizationStrategy": "normalize",
"outputMultiplier": 1.0,
"useRadians": 0,
"rootJoint": "hip",
"NormalizeNSDMBasedOn":
[
{
"jointStart": "hip",
"jointEnd": "rshoulder"
},
{
"jointStart": "hip",
"jointEnd": "lshoulder"
}
],
"Alignment":
[
{
"jointStart": "hip",
"jointEnd": "neck"
}
],
"NSDM": [
{
"joint": "hip",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_eye.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_eye.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "neck",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "hip",
"isVirtual": 1,
"xOffset": 0.3,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rshoulder",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "relbow",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rhand",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "hip",
"isVirtual": 1,
"xOffset": -0.3,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lshoulder",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lelbow",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lhand",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rhip",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rknee",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rfoot",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lhip",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lknee",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lfoot",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
}
],
"hierarchy": [
{
"joint": "hip",
"inheritNetwork": "none",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "neck",
"inheritNetwork": "hip",
"parent": "chest",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "head",
"inheritNetwork": "hip",
"parent": "neck",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_eye.l",
"inheritNetwork": "head",
"parent": "head",
"importance": 3,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_eye.r",
"inheritNetwork": "head",
"parent": "head",
"importance": 3,
"immuneToSelfOcclusions": 0
},
{
"joint": "rshoulder",
"inheritNetwork": "hip",
"parent": "rcollar",
"importance": 1,
"immuneToSelfOcclusions": 0
},
{
"joint": "relbow",
"inheritNetwork": "rshoulder",
"parent": "rshoulder",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "rhand",
"inheritNetwork": "relbow",
"parent": "relbow",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "lshoulder",
"inheritNetwork": "hip",
"parent": "lcollar",
"importance": 1,
"immuneToSelfOcclusions": 0
},
{
"joint": "lelbow",
"inheritNetwork": "lshoulder",
"parent": "lshoulder",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "lhand",
"inheritNetwork": "lelbow",
"parent": "lelbow",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "rhip",
"inheritNetwork": "hip",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 0
},
{
"joint": "rknee",
"inheritNetwork": "rhip",
"parent": "rhip",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "rfoot",
"inheritNetwork": "rknee",
"parent": "rknee",
"importance": 3,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_toe1-2.r",
"inheritNetwork": "none",
"parent": "rfoot",
"importance": 3,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_toe5-3.r",
"inheritNetwork": "none",
"parent": "rfoot",
"importance": 3,
"immuneToSelfOcclusions": 0
},
{
"joint": "lhip",
"inheritNetwork": "hip",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 0
},
{
"joint": "lknee",
"inheritNetwork": "lhip",
"parent": "lhip",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "lfoot",
"inheritNetwork": "lknee",
"parent": "lknee",
"importance": 3,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_toe1-2.l",
"inheritNetwork": "none",
"parent": "lfoot",
"importance": 3,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_toe5-3.l",
"inheritNetwork": "none",
"parent": "lfoot",
"importance": 3,
"immuneToSelfOcclusions": 0
}
],
"banned": [
{
"output": "foo"
}
]
}
@@ -0,0 +1,395 @@
{
"version": "4.0",
"backend": "mnet3",
"precision": "fp32",
"outputMode": "bvh",
"BVH": "headerWithHeadAndOneMotion.bvh",
"OutputDirectory": "face",
"veryHighNumberOfEpochs": 32,
"highNumberOfEpochs": 32,
"defaultNumberOfEpochs": 32,
"defaultBatchSize": 64,
"learningRate": 0.00017,
"minEarlyStoppingDelta": 0.01,
"setConstantSeedForReproducibleTraining": 1,
"activationFunction": "swish",
"weightRandomizationFunction": "auto",
"optimizer": "adam",
"dropoutRate": 0.30,
"lamda": 1.9,
"useQuadLoss": 0,
"useSquaredLoss": 1,
"earlyStoppingPatience": 5,
"rememberWeights": 0,
"rememberConsecutiveWeights": 1,
"useOnlineHardExampleMining": 0,
"hardMiningEpochs": 5,
"normalMiningEpochs": 2,
"groupOutputs": 1,
"ignoreOcclusions": 1,
"NSDMNormalizationMasterSwitch": 0,
"NSDMAlsoUseAlignmentAngles": 1,
"neuralNetworkDepth": 7,
"EDM" : 0,
"eNSRM": 1,
"NSRMNormalizeAngles": 0,
"eigenPoses": 0,
"autobuilder": 0,
"skipConnections": 1,
"decompositionType": "pca",
"doPCA": "dataset/$.pca",
"balanced2DInputs": 0,
"include2DInputVisibilityFlags": 0,
"PCADimensionsKept": 200,
"PCAAlsoKeepRawData": 1,
"padEnsembleInput": 0,
"probabilisticOutput": 0,
"filterOutEmptySamples": 1,
"outputValueDistribution": "balanced",
"outputNormalizationStrategy": "normalize",
"outputMultiplier": 30.0,
"useRadians": 0,
"rootJoint": "neck",
"NormalizeNSDMBasedOn":
[
{
"jointStart": "head_chin",
"jointEnd": "head_leye"
},
{
"jointStart": "head_chin",
"jointEnd": "head_reye"
}
],
"Alignment":
[
{
"jointStart": "head_chin",
"jointEnd": "head_nostrills_2"
}
],
"NSDM":
[
{
"joint": "head_reyebrow_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_leyebrow_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_chin",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_0",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_6",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_3",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_9",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_nostrills_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye",
"isVirtual": 1,
"xOffset": -0.15,
"yOffset": -0.15,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_leye",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_leye",
"isVirtual": 1,
"xOffset": 0.15,
"yOffset": -0.15,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye_5",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_leye_1",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_leye_4",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reyebrow_4",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_leyebrow_4",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
}
],
"hierarchy":
[
{
"joint": "neck1",
"inheritNetwork": "none",
"parent": "neck1",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "jaw",
"inheritNetwork": "neck1",
"parent": "neck1",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "eye.R",
"inheritNetwork": "neck1",
"parent": "eye.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "eye.L",
"inheritNetwork": "neck1",
"parent": "eye.L",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oculi01.R",
"inheritNetwork": "eye.R",
"parent": "eye.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oculi01.L",
"inheritNetwork": "eye.L",
"parent": "eye.L",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "orbicularis03.R",
"inheritNetwork": "eye.R",
"parent": "eye.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "orbicularis04.R",
"inheritNetwork": "orbicularis03.R",
"parent": "orbicularis03.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "orbicularis03.L",
"inheritNetwork": "eye.L",
"parent": "eye.L",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "orbicularis04.L",
"inheritNetwork": "orbicularis03.L",
"parent": "orbicularis03.L",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris03.R",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris04.R",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris03.L",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris04.L",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris05",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris06.R",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris06.L",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris07.R",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris07.L",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "levator03.R",
"inheritNetwork": "orbicularis03.R",
"parent": "orbicularis03.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "levator06.R",
"inheritNetwork": "orbicularis03.R",
"parent": "orbicularis03.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "levator03.L",
"inheritNetwork": "orbicularis03.L",
"parent": "orbicularis03.L",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "levator06.L",
"inheritNetwork": "orbicularis03.L",
"parent": "orbicularis03.L",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "hip",
"inheritNetwork": "none",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 1
}
],
"banned": [
{
"output": "foo"
}
]
}
@@ -0,0 +1,37 @@
%Calibration File v 1.0.3 - Matlab Load() compatible, https://support.stereolabs.com/hc/en-us/articles/360007497173-What-is-the-calibration-file- Scale Unit: 1.0
%CameraID=0
%CameraNo=0
%Date=
%Width
1920
%Height
1080
%Description=
%Intrinsics I[1,1], I[1,2], I[1,3], I[2,1], I[2,2], I[2,3], I[3,1], I[3,2] I[3,3]
%I
1055.47
0.0
960.0
0.0
1055.15
740.0
0.0
0.0
1.0
%Distortion D[1], D[2], D[3], D[4] D[5]
%D
0.07
-0.18
0.0
0.0
0.0
%Translation T.X, T.Y, T.Z
%T
0
0
0
%Rotation Vector (Rodrigues) R.X, R.Y, R.Z
%R
0
0
0
@@ -0,0 +1,418 @@
{
"version": "4.0",
"backend": "mnet3",
"precision": "fp32",
"outputMode": "bvh",
"BVH": "headerWithHeadAndOneMotion.bvh",
"OutputDirectory": "lhand",
"veryHighNumberOfEpochs": 47,
"highNumberOfEpochs": 47,
"defaultNumberOfEpochs": 47,
"defaultBatchSize": 256,
"learningRate": 0.00005,
"minEarlyStoppingDelta": 0.001,
"setConstantSeedForReproducibleTraining": 1,
"activationFunction": "swish",
"weightRandomizationFunction": "auto",
"optimizer": "adam",
"dropoutRate": 0.10,
"lamda": 0.20,
"useQuadLoss": 0,
"useSquaredLoss": 1,
"earlyStoppingPatience": 10,
"rememberWeights": 1,
"rememberConsecutiveWeights": 0,
"useOnlineHardExampleMining": 0,
"hardMiningEpochs": 5,
"normalMiningEpochs": 2,
"groupOutputs": 0,
"ignoreOcclusions": 1,
"neuralNetworkDepth": 12,
"EDM" : 0,
"eNSRM": 1,
"NSRMNormalizeAngles": 2,
"NSDMAlsoUseAlignmentAngles": 1,
"NSDMNormalizationMasterSwitch": 0,
"eigenPoses": 0,
"autobuilder": 0,
"skipConnections": 1,
"decompositionType": "",
"doPCA": "dataset/$.pca",
"balanced2DInputs": 0,
"include2DInputVisibilityFlags": 0,
"PCADimensionsKept": 160,
"PCAAlsoKeepRawData": 1,
"padEnsembleInput": 0,
"probabilisticOutput": 0,
"filterOutEmptySamples": 1,
"outputValueDistribution": "balanced",
"outputNormalizationStrategy": "normalize",
"outputMultiplier": 2.5,
"useRadians": 0,
"rootJoint": "lhand",
"NormalizeNSDMBasedOn":
[
{
"jointStart": "lhand",
"jointEnd": "finger5-1.l"
},
{
"jointStart": "lhand",
"jointEnd": "finger4-1.l"
},
{
"jointStart": "lhand",
"jointEnd": "finger3-1.l"
},
{
"jointStart": "lhand",
"jointEnd": "finger2-1.l"
},
{
"jointStart": "lhand",
"jointEnd": "lthumb"
}
],
"Alignment":
[
{
"jointStart": "lhand",
"jointEnd": "finger3-1.l"
}
],
"NSDM": [
{
"joint": "lhand",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger5-1.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger5-2.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger5-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_finger5-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger4-1.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger4-2.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger4-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_finger4-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger3-1.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger3-2.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger3-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_finger3-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger2-1.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger2-2.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger2-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_finger2-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lthumb",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger1-2.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger1-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_finger1-3.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
}
],
"hierarchy": [
{
"joint": "lhand",
"inheritNetwork": "none",
"parent": "lhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger2-1.l",
"inheritNetwork": "lhand",
"parent": "lhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger2-2.l",
"inheritNetwork": "finger2-1.l",
"parent": "finger2-1.l",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger2-3.l",
"inheritNetwork": "finger2-2.l",
"parent": "finger2-2.l",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger2-3.l",
"inheritNetwork": "finger2-3.l",
"parent": "finger2-3.l",
"importance": 3,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger3-1.l",
"inheritNetwork": "lhand",
"parent": "lhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger3-2.l",
"inheritNetwork": "finger3-1.l",
"parent": "finger3-1.l",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger3-3.l",
"inheritNetwork": "finger3-2.l",
"parent": "finger3-2.l",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger3-3.l",
"inheritNetwork": "finger3-3.l",
"parent": "finger3-3.l",
"importance": 3,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger4-1.l",
"inheritNetwork": "lhand",
"parent": "lhand",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger4-2.l",
"inheritNetwork": "finger4-1.l",
"parent": "finger4-1.l",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger4-3.l",
"inheritNetwork": "finger4-2.l",
"parent": "finger4-2.l",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger4-3.l",
"inheritNetwork": "finger4-3.l",
"parent": "finger4-3.l",
"importance": 3,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger5-1.l",
"inheritNetwork": "lhand",
"parent": "lhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger5-2.l",
"inheritNetwork": "finger5-1.l",
"parent": "finger5-1.l",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger5-3.l",
"inheritNetwork": "finger5-2.l",
"parent": "finger5-2.l",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger5-3.l",
"inheritNetwork": "finger5-3.l",
"parent": "finger5-3.l",
"importance": 3,
"immuneToSelfOcclusions": 1
},
{
"joint": "lthumb",
"inheritNetwork": "lhand",
"parent": "lhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "lthumbBase",
"inheritNetwork": "lhand",
"parent": "lhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger1-2.l",
"inheritNetwork": "lthumb",
"parent": "lthumb",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger1-3.l",
"inheritNetwork": "finger1-2.l",
"parent": "finger1-2.l",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger1-3.l",
"inheritNetwork": "finger1-3.l",
"parent": "finger1-3.l",
"importance": 3,
"immuneToSelfOcclusions": 1
}
],
"banned": [
{
"output": "foo"
}
]
}
@@ -0,0 +1,328 @@
{
"version": "4.0",
"backend": "mnet3",
"precision": "fp32",
"outputMode": "bvh",
"BVH": "headerWithHeadAndOneMotion.bvh",
"OutputDirectory": "lowerbody",
"veryHighNumberOfEpochs": 512,
"highNumberOfEpochs": 256,
"defaultNumberOfEpochs": 128,
"defaultBatchSize": 64,
"learningRate": 0.00005,
"minEarlyStoppingDelta": 0.01,
"setConstantSeedForReproducibleTraining": 1,
"activationFunction": "swish",
"weightRandomizationFunction": "auto",
"optimizer": "adam",
"dropoutRate": 0.10,
"lamda": 0.25,
"useQuadLoss": 0,
"useSquaredLoss": 1,
"earlyStoppingPatience": 5,
"rememberWeights": 0,
"rememberConsecutiveWeights": 1,
"useOnlineHardExampleMining": 0,
"hardMiningEpochs": 5,
"normalMiningEpochs": 2,
"groupOutputs": 0,
"ignoreOcclusions": 1,
"NSRMNormalizeAngles": 2,
"NSDMNormalizationMasterSwitch": 0,
"NSDMAlsoUseAlignmentAngles": 1,
"neuralNetworkDepth": 12,
"EDM" : 0,
"eNSRM": 1,
"eigenPoses": 0,
"autobuilder": 0,
"skipConnections": 1,
"decompositionType": "",
"doPCA": "dataset/$.pca",
"balanced2DInputs": 0,
"include2DInputVisibilityFlags": 0,
"PCADimensionsKept": 230,
"PCAAlsoKeepRawData": 1,
"padEnsembleInput": 0,
"probabilisticOutput": 0,
"filterOutEmptySamples": 1,
"outputValueDistribution": "balanced",
"outputNormalizationStrategy": "normalize",
"outputMultiplier": 1.5,
"useRadians": 0,
"rootJoint": "hip",
"NormalizeNSDMBasedOn":
[
{
"jointStart": "hip",
"jointEnd": "rhip"
},
{
"jointStart": "hip",
"jointEnd": "lhip"
}
],
"Alignment":
[
{
"jointStart": "rknee",
"jointEnd": "rhip"
}
],
"NSDM":
[
{
"joint": "hip",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rhip",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rhip",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "rknee",
"secondTargetJointID": 0
},
{
"joint": "rknee",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rknee",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "rfoot",
"secondTargetJointID": 0
},
{
"joint": "rfoot",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_toe1-2.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "hip",
"isVirtual": 1,
"xOffset": 0.3,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "hip",
"isVirtual": 1,
"xOffset": -0.3,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lhip",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lhip",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "lknee",
"secondTargetJointID": 0
},
{
"joint": "lknee",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lknee",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "lfoot",
"secondTargetJointID": 0
},
{
"joint": "lfoot",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_toe1-2.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "hip",
"isVirtual": 1,
"xOffset": 0.0,
"yOffset": 0.15,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "hip",
"isVirtual": 1,
"xOffset": 0.0,
"yOffset": 0.3,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
}
],
"hierarchy": [
{
"joint": "hip",
"inheritNetwork": "none",
"parent": "hip",
"importance": 0,
"immuneToSelfOcclusions": 1
},
{
"joint": "rhip",
"inheritNetwork": "hip",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 0
},
{
"joint": "rknee",
"inheritNetwork": "rhip",
"parent": "rhip",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "rfoot",
"inheritNetwork": "rknee",
"parent": "rknee",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "toe1-2.r",
"inheritNetwork": "none",
"parent": "rfoot",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_toe1-2.r",
"inheritNetwork": "none",
"parent": "rfoot",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "toe5-3.r",
"inheritNetwork": "none",
"parent": "rfoot",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_toe5-3.r",
"inheritNetwork": "none",
"parent": "rfoot",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "lhip",
"inheritNetwork": "hip",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 0
},
{
"joint": "lknee",
"inheritNetwork": "lhip",
"parent": "lhip",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "lfoot",
"inheritNetwork": "lknee",
"parent": "lknee",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "toe1-2.l",
"inheritNetwork": "none",
"parent": "rfoot",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_toe1-2.l",
"inheritNetwork": "none",
"parent": "lfoot",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "toe5-3.l",
"inheritNetwork": "none",
"parent": "rfoot",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_toe5-3.l",
"inheritNetwork": "none",
"parent": "lfoot",
"importance": 0,
"immuneToSelfOcclusions": 0
}
],
"banned": [
{
"output": "abdomen"
},
{
"output": "chest"
}
]
}
@@ -0,0 +1,367 @@
{
"version": "4.0",
"backend": "mnet3",
"precision": "fp32",
"outputMode": "bvh",
"BVH": "headerWithHeadAndOneMotion.bvh",
"OutputDirectory": "mouth",
"veryHighNumberOfEpochs": 32,
"highNumberOfEpochs": 24,
"defaultNumberOfEpochs": 16,
"defaultBatchSize": 32,
"learningRate": 0.00017,
"minEarlyStoppingDelta": 0.001,
"setConstantSeedForReproducibleTraining": 1,
"activationFunction": "swish",
"weightRandomizationFunction": "auto",
"optimizer": "adam",
"dropoutRate": 0.25,
"lamda": 1.4,
"useQuadLoss": 0,
"useSquaredLoss": 1,
"earlyStoppingPatience": 5,
"rememberWeights": 0,
"rememberConsecutiveWeights": 1,
"useOnlineHardExampleMining": 0,
"hardMiningEpochs": 5,
"normalMiningEpochs": 2,
"groupOutputs": 1,
"ignoreOcclusions": 1,
"neuralNetworkDepth": 12,
"EDM" : 0,
"eNSRM": 1,
"NSRMNormalizeAngles": 2,
"NSDMAlsoUseAlignmentAngles": 1,
"NSDMNormalizationMasterSwitch": 0,
"eigenPoses": 0,
"autobuilder": 0,
"skipConnections": 1,
"decompositionType": "",
"doPCA": "dataset/$.pca",
"balanced2DInputs": 0,
"include2DInputVisibilityFlags": 0,
"PCADimensionsKept": 160,
"PCAAlsoKeepRawData": 1,
"padEnsembleInput": 0,
"probabilisticOutput": 0,
"filterOutEmptySamples": 1,
"outputValueDistribution": "balanced",
"outputNormalizationStrategy": "normalize",
"outputMultiplier": 2.5,
"useRadians": 0,
"rootJoint": "head_chin",
"NormalizeNSDMBasedOn":
[
{
"jointStart": "head_chin",
"jointEnd": "head_nostrills_2"
}
],
"Alignment":
[
{
"jointStart": "head_chin",
"jointEnd": "head_nostrills_2"
}
],
"NSDM":
[
{
"joint": "head_chin",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_nostrills_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_0",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_1",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_3",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_4",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_5",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_6",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_7",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_8",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_9",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_10",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_outmouth_11",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_inmouth_0",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_inmouth_1",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_inmouth_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_inmouth_3",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_inmouth_4",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_inmouth_5",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_inmouth_6",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_inmouth_7",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
}
],
"hierarchy":
[
{
"joint": "neck1",
"inheritNetwork": "none",
"parent": "neck1",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "jaw",
"inheritNetwork": "neck1",
"parent": "neck1",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris03.R",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris04.R",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris03.L",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris04.L",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris05",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris06.R",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris06.L",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris07.R",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oris07.L",
"inheritNetwork": "neck1",
"parent": "jaw",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "levator03.R",
"inheritNetwork": "orbicularis03.R",
"parent": "orbicularis03.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "levator06.R",
"inheritNetwork": "orbicularis03.R",
"parent": "orbicularis03.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "levator03.L",
"inheritNetwork": "orbicularis03.L",
"parent": "orbicularis03.L",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "levator06.L",
"inheritNetwork": "orbicularis03.L",
"parent": "orbicularis03.L",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "hip",
"inheritNetwork": "none",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 1
}
],
"banned": [
{
"output": "foo"
}
]
}
@@ -0,0 +1,265 @@
{
"version": "4.0",
"backend": "mnet3",
"precision": "fp32",
"outputMode": "bvh",
"BVH": "headerWithHeadAndOneMotion.bvh",
"OutputDirectory": "reye",
"veryHighNumberOfEpochs": 32,
"highNumberOfEpochs": 24,
"defaultNumberOfEpochs": 16,
"defaultBatchSize": 16,
"learningRate": 0.00017,
"minEarlyStoppingDelta": 0.001,
"setConstantSeedForReproducibleTraining": 1,
"activationFunction": "swish",
"weightRandomizationFunction": "auto",
"optimizer": "adam",
"dropoutRate": 0.21,
"lamda": 0.9,
"useQuadLoss": 0,
"useSquaredLoss": 1,
"earlyStoppingPatience": 5,
"rememberWeights": 0,
"rememberConsecutiveWeights": 1,
"useOnlineHardExampleMining": 0,
"hardMiningEpochs": 5,
"normalMiningEpochs": 2,
"groupOutputs": 1,
"ignoreOcclusions": 1,
"neuralNetworkDepth": 12,
"EDM" : 0,
"eNSRM": 1,
"NSRMNormalizeAngles": 2,
"NSDMAlsoUseAlignmentAngles": 1,
"NSDMNormalizationMasterSwitch": 0,
"eigenPoses": 0,
"autobuilder": 0,
"skipConnections": 1,
"decompositionType": "",
"doPCA": "dataset/$.pca",
"balanced2DInputs": 0,
"include2DInputVisibilityFlags": 0,
"PCADimensionsKept": 160,
"PCAAlsoKeepRawData": 1,
"padEnsembleInput": 0,
"probabilisticOutput": 0,
"filterOutEmptySamples": 1,
"outputValueDistribution": "balanced",
"outputNormalizationStrategy": "normalize",
"outputMultiplier": 2.5,
"useRadians": 0,
"rootJoint": "head_nostrills_2",
"NormalizeNSDMBasedOn":
[
{
"jointStart": "head_reye_0",
"jointEnd": "head_reye_3"
}
],
"Alignment":
[
{
"jointStart": "head_reye_3",
"jointEnd": "head_nostrills_2"
}
],
"NSDM":
[
{
"joint": "head_nostrills_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_chin",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_rchin_0",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye_0",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye_1",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye_3",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye",
"isVirtual": 1,
"xOffset": -0.015,
"yOffset": -0.026,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye",
"isVirtual": 1,
"xOffset": 0.015,
"yOffset": 0.026,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "head_nostrills_2",
"secondTargetJointID": 0
},
{
"joint": "head_reye_4",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reye_5",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reyebrow_0",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reyebrow_1",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reyebrow_2",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reyebrow_3",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "head_reyebrow_4",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
}
],
"hierarchy":
[
{
"joint": "neck1",
"inheritNetwork": "none",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "eye.R",
"inheritNetwork": "neck1",
"parent": "eye.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "oculi01.R",
"inheritNetwork": "eye.R",
"parent": "eye.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "orbicularis03.R",
"inheritNetwork": "eye.R",
"parent": "eye.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "orbicularis04.R",
"inheritNetwork": "orbicularis03.R",
"parent": "orbicularis03.R",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "hip",
"inheritNetwork": "none",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 1
}
],
"banned": [
{
"output": "foo"
}
]
}
@@ -0,0 +1,377 @@
{
"version": "4.0",
"backend": "mnet3",
"precision": "fp32",
"outputMode": "bvh",
"BVH": "headerWithHeadAndOneMotion.bvh",
"OutputDirectory": "rhand",
"veryHighNumberOfEpochs": 72,
"highNumberOfEpochs": 48,
"defaultNumberOfEpochs": 32,
"defaultBatchSize": 64,
"learningRate": 0.00017,
"minEarlyStoppingDelta": 0.01,
"setConstantSeedForReproducibleTraining": 1,
"activationFunction": "swish",
"weightRandomizationFunction": "auto",
"optimizer": "adam",
"dropoutRate": 0.15,
"lamda": 1.8,
"useQuadLoss": 0,
"useSquaredLoss": 1,
"earlyStoppingPatience": 8,
"rememberWeights": 1,
"rememberConsecutiveWeights": 0,
"useOnlineHardExampleMining": 0,
"hardMiningEpochs": 5,
"normalMiningEpochs": 2,
"groupOutputs": 1,
"ignoreOcclusions": 1,
"neuralNetworkDepth": 12,
"EDM" : 0,
"eNSRM": 1,
"NSRMNormalizeAngles": 1,
"NSDMAlsoUseAlignmentAngles": 1,
"NSDMNormalizationMasterSwitch": 0,
"eigenPoses": 0,
"autobuilder": 0,
"skipConnections": 1,
"decompositionType": "",
"doPCA": "dataset/$.pca",
"balanced2DInputs": 0,
"include2DInputVisibilityFlags": 0,
"PCADimensionsKept": 160,
"PCAAlsoKeepRawData": 1,
"padEnsembleInput": 0,
"probabilisticOutput": 0,
"filterOutEmptySamples": 1,
"outputValueDistribution": "balanced",
"outputNormalizationStrategy": "normalize",
"outputMultiplier": 3.5,
"useRadians": 0,
"rootJoint": "rhand",
"NormalizeNSDMBasedOn":
[
{
"jointStart": "rhand",
"jointEnd": "finger5-1.r"
},
{
"jointStart": "rhand",
"jointEnd": "finger4-1.r"
},
{
"jointStart": "rhand",
"jointEnd": "finger3-1.r"
},
{
"jointStart": "rhand",
"jointEnd": "finger2-1.r"
},
{
"jointStart": "rhand",
"jointEnd": "rthumb"
}
],
"Alignment":
[
{
"jointStart": "rhand",
"jointEnd": "finger3-1.r"
}
],
"NSDM": [
{
"joint": "rhand",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger5-1.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger5-2.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger5-3.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger4-1.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger4-2.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger4-3.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger3-1.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger3-2.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger3-3.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger2-1.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger2-2.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger2-3.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rthumb",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger1-2.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "finger1-3.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
}
],
"hierarchy": [
{
"joint": "rhand",
"inheritNetwork": "none",
"parent": "rhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger2-1.r",
"inheritNetwork": "rhand",
"parent": "rhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger2-2.r",
"inheritNetwork": "finger2-1.r",
"parent": "finger2-1.r",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger2-3.r",
"inheritNetwork": "finger2-2.r",
"parent": "finger2-2.r",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger2-3.r",
"inheritNetwork": "finger2-3.r",
"parent": "finger2-3.r",
"importance": 3,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger3-1.r",
"inheritNetwork": "rhand",
"parent": "rhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger3-2.r",
"inheritNetwork": "finger3-1.r",
"parent": "finger3-1.r",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger3-3.r",
"inheritNetwork": "finger3-2.r",
"parent": "finger3-2.r",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger3-3.r",
"inheritNetwork": "finger3-3.r",
"parent": "finger3-3.r",
"importance": 3,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger4-1.r",
"inheritNetwork": "rhand",
"parent": "rhand",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger4-2.r",
"inheritNetwork": "finger4-1.r",
"parent": "finger4-1.r",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger4-3.r",
"inheritNetwork": "finger4-2.r",
"parent": "finger4-2.r",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger4-3.r",
"inheritNetwork": "finger4-3.r",
"parent": "finger4-3.r",
"importance": 3,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger5-1.r",
"inheritNetwork": "rhand",
"parent": "rhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger5-2.r",
"inheritNetwork": "finger5-1.r",
"parent": "finger5-1.r",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger5-3.r",
"inheritNetwork": "finger5-2.r",
"parent": "finger5-2.r",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger5-3.r",
"inheritNetwork": "finger5-3.r",
"parent": "finger5-3.r",
"importance": 3,
"immuneToSelfOcclusions": 1
},
{
"joint": "rthumb",
"inheritNetwork": "rhand",
"parent": "rhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "rthumbBase",
"inheritNetwork": "rhand",
"parent": "rhand",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger1-2.r",
"inheritNetwork": "rthumb",
"parent": "rthumb",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "finger1-3.r",
"inheritNetwork": "finger1-2.r",
"parent": "finger1-2.r",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "EndSite_finger1-3.r",
"inheritNetwork": "finger1-3.r",
"parent": "finger1-3.r",
"importance": 3,
"immuneToSelfOcclusions": 1
}
],
"banned": [
{
"output": "foo"
}
]
}
@@ -0,0 +1,327 @@
{
"version": "4.0",
"backend": "mnet3",
"precision": "fp32",
"outputMode": "bvh",
"BVH": "headerWithHeadAndOneMotion.bvh",
"OutputDirectory": "upperbody",
"veryHighNumberOfEpochs": 512,
"highNumberOfEpochs": 256,
"defaultNumberOfEpochs": 128,
"defaultBatchSize": 64,
"learningRate": 0.00005,
"minEarlyStoppingDelta": 0.01,
"setConstantSeedForReproducibleTraining": 1,
"activationFunction": "swish",
"weightRandomizationFunction": "auto",
"optimizer": "adam",
"dropoutRate": 0.10,
"lamda": 0.25,
"useQuadLoss": 0,
"useSquaredLoss": 1,
"earlyStoppingPatience": 5,
"rememberWeights": 0,
"rememberConsecutiveWeights": 1,
"useOnlineHardExampleMining": 0,
"hardMiningEpochs": 5,
"normalMiningEpochs": 2,
"groupOutputs": 0,
"ignoreOcclusions": 1,
"NSRMNormalizeAngles": 2,
"NSDMNormalizationMasterSwitch": 0,
"NSDMAlsoUseAlignmentAngles": 1,
"neuralNetworkDepth": 12,
"EDM" : 0,
"eNSRM": 1,
"eigenPoses": 0,
"autobuilder": 0,
"skipConnections": 1,
"decompositionType": "",
"doPCA": "dataset/$.pca",
"balanced2DInputs": 0,
"include2DInputVisibilityFlags": 0,
"PCADimensionsKept": 230,
"PCAAlsoKeepRawData": 1,
"padEnsembleInput": 0,
"probabilisticOutput": 0,
"filterOutEmptySamples": 1,
"outputValueDistribution": "balanced",
"outputNormalizationStrategy": "normalize",
"outputMultiplier": 1.5,
"useRadians": 0,
"rootJoint": "hip",
"NormalizeNSDMBasedOn":
[
{
"jointStart": "hip",
"jointEnd": "rshoulder"
},
{
"jointStart": "hip",
"jointEnd": "lshoulder"
}
],
"Alignment":
[
{
"jointStart": "hip",
"jointEnd": "neck1"
}
],
"NSDM":
[
{
"joint": "hip",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_eye.r",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "EndSite_eye.l",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "neck1",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rshoulder",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "rshoulder",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "relbow",
"secondTargetJointID": 0
},
{
"joint": "relbow",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "relbow",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "rhand",
"secondTargetJointID": 0
},
{
"joint": "rhand",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "hip",
"isVirtual": 1,
"xOffset": -0.15,
"yOffset": -0.15,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "hip",
"isVirtual": 1,
"xOffset": 0.15,
"yOffset": -0.15,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lshoulder",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lshoulder",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "lelbow",
"secondTargetJointID": 0
},
{
"joint": "lelbow",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "lelbow",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "lhand",
"secondTargetJointID": 0
},
{
"joint": "lhand",
"isVirtual": 0,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "",
"secondTargetJointID": 0
},
{
"joint": "neck1",
"isVirtual": 2,
"xOffset": 0,
"yOffset": 0,
"halfWayFromThisAnd": "hip",
"secondTargetJointID": 0
}
],
"hierarchy":
[
{
"joint": "hip",
"inheritNetwork": "none",
"parent": "hip",
"importance": 1,
"immuneToSelfOcclusions": 1
},
{
"joint": "abdomen",
"inheritNetwork": "hip",
"parent": "hip",
"importance": 0,
"immuneToSelfOcclusions": 1
},
{
"joint": "chest",
"inheritNetwork": "abdomen",
"parent": "abdomen",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "neck1",
"inheritNetwork": "hip",
"parent": "chest",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "head",
"inheritNetwork": "hip",
"parent": "neck1",
"importance": 2,
"immuneToSelfOcclusions": 1
},
{
"joint": "eye.l",
"inheritNetwork": "head",
"parent": "head",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_eye.l",
"inheritNetwork": "head",
"parent": "head",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "eye.r",
"inheritNetwork": "head",
"parent": "head",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "EndSite_eye.r",
"inheritNetwork": "head",
"parent": "head",
"importance": 0,
"immuneToSelfOcclusions": 0
},
{
"joint": "rshoulder",
"inheritNetwork": "hip",
"parent": "rcollar",
"importance": 1,
"immuneToSelfOcclusions": 0
},
{
"joint": "relbow",
"inheritNetwork": "rshoulder",
"parent": "rshoulder",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "rhand",
"inheritNetwork": "relbow",
"parent": "relbow",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "lshoulder",
"inheritNetwork": "hip",
"parent": "lcollar",
"importance": 1,
"immuneToSelfOcclusions": 0
},
{
"joint": "lelbow",
"inheritNetwork": "lshoulder",
"parent": "lshoulder",
"importance": 2,
"immuneToSelfOcclusions": 0
},
{
"joint": "lhand",
"inheritNetwork": "lelbow",
"parent": "lelbow",
"importance": 2,
"immuneToSelfOcclusions": 0
}
],
"banned": [
{
"output": "foo"
}
]
}
+75
View File
@@ -0,0 +1,75 @@
# HTTP Multipart MJPEG downloader ..
# Edited version to work with HTTP Multipart MJPEG
# Based on https://github.com/sglvladi/TensorFlowObjectDetectionTutorial
#pip install numpy matplotlib pil opencv-python --user
import numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
import zipfile
import cv2
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image
# Helper code
def load_image_into_numpy_array(image):
(im_width, im_height) = image.size
return np.array(image.getdata()).reshape(
(im_height, im_width, 3)).astype(np.uint8)
class ESP32CamStreamer():
def __init__(self,
url = "http://192.168.1.33:80",
timeout = 35,
readBuffer = 2048
):
self.stream = urllib.request.urlopen(url,timeout=timeout)
self.should_stop = False
self.bytebuffer = bytes()
self.readBuffer = readBuffer
def isOpened(self):
return True
def release(self):
del self.stream
del self.should_stop
del self.bytebuffer
def read(self):
# Read frame from camera
success = True
while True:
self.bytebuffer += self.stream.read(self.readBuffer)
a = self.bytebuffer.find(b'\xff\xd8')
b = self.bytebuffer.find(b'\xff\xd9')
if a != -1 and b != -1:
jpg = self.bytebuffer[a:b+2]
self.bytebuffer = self.bytebuffer[b+2:]
try:
self.image_np = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
except:
success=False
break
return success,self.image_np
def visualize(
self,
windowname='Object Detection',
width=800,
height=600
):
# Display output
cv2.imshow(windowname, cv2.resize(self.image_np,(width,height)))
if cv2.waitKey(10) & 0xff == ord('q'):
cv2.destroyAllWindows()
self.should_stop = True
#break
@@ -0,0 +1,748 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
#TODO : FIX 3D MODE!
import os
import sys
import gc
import time
#--------------------------------------------------
import numpy as np
#--------------------------------------------------
from readCSV import parseConfiguration,checkIfConfigurationHierarchyIsTheSameAsLabelList,readCSVLabels,readCSVFile,checkIfTestAndTrainListsAreOk,readGroundTruthFile,splitNumpyArray
from DNNModel import setupDNNModelsUsingJSONConfiguration
from DNNTraining import printTrainingVersion,regularTraining,onlineHardExampleMiningTraining
from tools import bcolors,dumpListToFile,getRAMInformation,createDirectory,checkIfFileExists,getConfigurationJointIsDeclaredInHierarchy,getConfigurationJointPriority,getParentNetwork,notification
from getModelFromDatabase import retrieveAndSetupModel,retrieveAndSetupBasedOnSerial
print("evaluateMocapNET starting up..\n")
printTrainingVersion()
print("""
███████╗██╗ ██╗ █████╗ ██╗ ██╗ ██╗ █████╗ ████████╗███████╗
██╔════╝██║ ██║██╔══██╗██║ ██║ ██║██╔══██╗╚══██╔══╝██╔════╝
█████╗ ██║ ██║███████║██║ ██║ ██║███████║ ██║ █████╗
██╔══╝ ╚██╗ ██╔╝██╔══██║██║ ██║ ██║██╔══██║ ██║ ██╔══╝
███████╗ ╚████╔╝ ██║ ██║███████╗╚██████╔╝██║ ██║ ██║ ███████╗
╚══════╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝
""")
print("""
██████╗ ██████╗ ██████╗ ██╗ ██╗
██╔══██╗██╔═══██╗██╔══██╗╚██╗ ██╔╝
██████╔╝██║ ██║██║ ██║ ╚████╔╝
██╔══██╗██║ ██║██║ ██║ ╚██╔╝
██████╔╝╚██████╔╝██████╔╝ ██║
╚═════╝ ╚═════╝ ╚═════╝ ╚═╝
""")
print("Ensuring the same seed for reproductible results always..\n")
from numpy.random import seed
seed(1)
np.set_printoptions(precision=2)
np.set_printoptions(formatter={"float_kind": lambda x: "%g" % x})
def setBackendToHalfFloats():
dtype='float16'
print("\nUsing Half-Floats for training ");
#-----------------------------------------------------------------------------------------------------------------------
def identifyProblematicOutput(mapPath):
print("READING evaluateMocapNET.lastresults.csv")
#-----------------------------------------------------------------
losses = readCSVFile("evaluateMocapNET.lastresults.csv" , 1.0 , 0)
#-----------------------------------------------------------------
f = open("evaluateMocapNET.identified.csv", "w")
f.write("SampleID,MAE,BVH,fID,cumulative\n")
# Using readlines()
file1 = open(mapPath, 'r')
Lines = file1.readlines()
#-----------------------------------------------------------------
minimum=np.min(losses['body'])
maximum=np.max(losses['body'])
median=np.median(losses['body'])
mean=np.mean(losses['body'])
std=np.std(losses['body'])
var=np.var(losses['body'])
print(" Min/Max=%0.2f/%0.2f,Median=%0.2f,Mean=%0.2f,Std=%0.2f,Var=%0.2f" % (minimum,maximum,median,mean,std,var))
sampleID = 0
hits = 0
previousBVHFile="dummy initial value"
consecutiveHits=0
errorThreshold=250.0
for item in losses['body']:
if (item>errorThreshold):
bvhFile = Lines[sampleID+1].split(",")[0]
fID = int(Lines[sampleID+1].split(",")[1])
#----------------------------------------------
if (previousBVHFile!=bvhFile):
consecutiveHits=0
previousBVHFile=bvhFile
else:
consecutiveHits=consecutiveHits+1
#----------------------------------------------
print(sampleID," error=",item[0]," -> ",bvhFile," fID ",fID)
f.write("%u,%f,%s,%u,%u\n"%(sampleID,item[0],bvhFile,fID,consecutiveHits))
hits=hits+1
sampleID=sampleID+1
#---------------------------------------------------------------
print("Found ",hits," occurances of error > ",errorThreshold)
file1.close()
#-----------------------------------------------------------------------------------------------------------------------
def appendRAWResultsForGNUplot(outputFile,globalJointDistances):
fileHandler = open(outputFile, "w")
fileHandler.write(outputFile)
fileHandler.write("\n")
for measurement in globalJointDistances:
fileHandler.write(str(measurement))
fileHandler.write("\n")
fileHandler.close()
#-----------------------------------------------------------------------------------------------------------------------
def ground3DJointsFromBVH(bvh,rawBVHPrediction :dict):
#Extract a BVH dict of BVH motion fields
#Modify our BVH armature with the new BVH values
if (bvh.modify(rawBVHPrediction)):
#Render to 2D/3D
bvh.processFrame(0) #only have 1 frame ID
#Retreive 2D/3D Values
output2D = dict()
output3D = dict()
for jointID in range(0,bvh.numberOfJoints):
#-------------------------------------------
jointName = bvh.getJointName(jointID).lower()
#-------------------------------------------
x3D,y3D,z3D = bvh.getJoint3D(jointID)
output3D["3DX_"+jointName]=float(x3D)
output3D["3DY_"+jointName]=float(y3D)
output3D["3DZ_"+jointName]=float(z3D)
#-------------------------------------------
x2D,y2D = bvh.getJoint2D(jointID)
output2D["2DX_"+jointName]=float(x2D)
output2D["2DY_"+jointName]=float(y2D)
#-------------------------------------------
else:
print(bcolors.FAIL,"We where unable to process the BVH output",bcolors.ENDC)
return output3D
def evaluateMocapNET(useCSVBackend,groundTruthTrain,groundTruthTest):
#----------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------
# Command-Line configuration and parameters and stuff
#----------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------
#Note starting time
startEverythingAt = time.time()
#1/0 = safe settings
saveResultsToDisk=1
if (not saveResultsToDisk):
input("\n\n\n\n\nResults will not be saved..! All of the computing time will go in vain..\nAre you sure you want to do this ?\n\n\n\n")
#Options in case of cluster operation
startPosition = 0
endPosition = 0
jobsPerCluster = 0
jobsPerClusterStart = 0
jobsPerClusterEnd = 0
#Cheapout on the test by default
testMemPercentage=1.0
#Use the whole training Dataset by default
memPercentage=1.0
#networkCompression=1.0
useHalfFloats = 0
useRadians = 0
#Resume training options
step=1
compareAllJoints=0
#AutoStart Tensorboard, disabled by default!
autostartTensorboard=0
doDebugVisualization = False
doProfiling = False
doOnlyIdentification = False
#I/O settings
outputDirectoryForTrainedModels = "step0FrontBody"
dataFile = "body"
hierarchyPartName = "body"
outputMode = "bvh"
useTestData = True
doNNEveryNFrames = 1
doHCDPostProcessing = 0
hcdLearningRate = 0.001
hcdEpochs = 30
hcdIterations = 15
#This needs to be populated using the --config argument otherwise session will fail..
configuration = []
configurationPath=""
engine = "onnx"
label = "evaluation"
doProcrustes = 1
# Sample call with some example parameters : ( needs --all body to have all joints ) if you see MocapNET always
# gets initiallized with upper/lower networks, this is just needed to correctly parse the ground truth test files
# --getPCA 15 105
# python3 -m evaluateMocapNET --getPCA 15 32 --config dataset/body_configuration.json --skip 5 --all body
# python3 -m evaluateMocapNET --config dataset/body_configuration.json --all body --skip 5 --mem 100
# python3 -m evaluateMocapNET --getPCA 210 64 --mem 10 --config dataset/body_configuration.json --all body
# python3 -m evaluateMocapNET --get 128 --config dataset/body_configuration.json --all body
# python3 -m evaluateMocapNET --config dataset/body_configuration.json --all body --engine onnx --3d #<- Evaluate 3D data!
#
# To generate evaluateMocapNET.lastresults.csv and then evaluateMocapNET.identified.csv do :
# python3 -m evaluateMocapNET --config dataset/body_configuration.json --all body --mem 1.0 --engine onnx --traindataset
# python3 -m evaluateMocapNET --config dataset/body_configuration.json --all body --mem 10 --engine onnx --traindataset --identify
#-----------------------------------------------------------------------------------------------------------------------------------------
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--hcd"):
doHCDPostProcessing = 1
if (sys.argv[i]=="--visualize"):
doDebugVisualization = True
if (sys.argv[i]=="--ik"):
doHCDPostProcessing = 1
hcdLearningRate = float(sys.argv[i+1])
hcdEpochs = int(sys.argv[i+2])
hcdIterations = int(sys.argv[i+3])
if (sys.argv[i]=="--nnsubsample"):
doNNEveryNFrames = int(sys.argv[i+1])
if (sys.argv[i]=="--noprocrustes"):
doProcrustes=0
if (sys.argv[i]=="--3d"):
print(bcolors.WARNING,"Evaluate in 3D mode\n",bcolors.ENDC)
#if needed by the model this will get auto activated later..
outputMode = "3d"
if (sys.argv[i]=="--identify"):
doOnlyIdentification=True
if (sys.argv[i]=="--engine"):
engine=sys.argv[i+1]
print("Selecting engine : ",engine)
if (sys.argv[i]=="--profile"):
doProfiling=True
if (sys.argv[i]=="--label"):
label=sys.argv[i+1]
if (sys.argv[i]=="--get"):
serial =int(sys.argv[i+1])
retrieveAndSetupBasedOnSerial(serial,download=1)
if (sys.argv[i]=="--getPCA"):
PCADimensions =int(sys.argv[i+1])
parameterCount=int(sys.argv[i+2])
label = "evaluation_pca%u_param%u" % (PCADimensions,parameterCount)
print("Get ",label)
retrieveAndSetupModel(PCADimensions,parameterCount,download=1)
if (sys.argv[i]=="--config"):
configurationPath=sys.argv[i+1]
configuration = parseConfiguration(configurationPath)
setupDNNModelsUsingJSONConfiguration(configuration)
if (sys.argv[i]=="--mem"):
print("\nMemory usage ",sys.argv[i+1]);
memPercentage=float(sys.argv[i+1])
if (sys.argv[i]=="--skip"):
print("\nSkipping frames ",sys.argv[i+1]);
step=int(sys.argv[i+1])
if (sys.argv[i]=="--full"):
print("\nComparing All Joints : ",sys.argv[i+1]);
compareAllJoints=int(sys.argv[i+1])
#-----------------------------------------------
# New 4way split
#-----------------------------------------------
if (sys.argv[i]=="--traindataset"):
print("\n Using training data instead of test data");
useTestData=False
if (sys.argv[i]=="--dataset"):
print("\nOverriding dataset ",dataFile," and using ",sys.argv[i+1]);
dataFile=sys.argv[i+1]
if (sys.argv[i]=="--all"):
#Don't mix this --all with the step2_OrientatonClassifier.py --all
hierarchyPartName=sys.argv[i+1]
dataFile="%s_all" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--back"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_back" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--front"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_front" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--left"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_left" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--right"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_right" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
#-----------------------------------------------
if (len(configuration)==0):
print(bcolors.FAIL,"Evaluation cannot run without a configuration!",bcolors.ENDC)
sys.exit(0)
#Resolve PCA name.. :(
x = configuration['doPCA'].split("$")
if (len(x)>0):
#If there is a $ character this is our place holder to autocomplete our dataFile
print("PCA filename is resolved from ",configuration['doPCA'])
print(" to ")
configuration['doPCA']=x[0]+dataFile+".pca"
print(configuration['doPCA'])
print("Creating directory for training models "+outputDirectoryForTrainedModels)
createDirectory(outputDirectoryForTrainedModels)
#----------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------
#The default compatibility setting is the BMVC2019 2channel NSDM, however nowadays we use NSRM
numberOfChannelsPerNSDMElement=2
if (configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
configuration['numberOfChannelsPerNSDMElement']=numberOfChannelsPerNSDMElement
#Printout the current configuration with regard to what network to inherit from
if (configuration['rememberWeights']):
print("Reloading previous training results")
else:
print("Not reloading")
#----------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------
# Read our training and test datasets
#----------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------
print("\n-------------------------------------------------");
startAt = time.time()
#Special case if the user has a set memory requirement we try to mimic it for test as well..
if (testMemPercentage==1.0):
if (memPercentage==0): testMemPercentage=memPercentage
if (memPercentage>1): testMemPercentage=memPercentage
#Hardcoded path for dataset if using CSV file
#datasetDirectory="/home/ammar/Documents/Programming/DNNTracker/DNNTracker/dataset"
#datasetDirectory="../../DNNTracker/dataset"
datasetDirectory="dataset/generated/"
#Auto activate 3D outputMode if needed
if ('outputMode' in configuration) and (configuration['outputMode'] == "3d"):
outputMode="3d"
#Eigenposes should be loaded before Train/Test files since they are used in the input transform step
#---------------------------------------------------------------------------------------------------
if ("eigenPoses" in configuration):
#We have eigenPoses Declared!
if (configuration['eigenPoses']==1):
#We have eigenPoses Active!
configuration['eigenPoseData'] = readGroundTruthFile(
configuration,
"Eigenposes",
"%s/2d_%s_eigenposes.csv" % (datasetDirectory,dataFile),
"%s/%s_%s_eigenposes.csv" % (datasetDirectory,outputMode,dataFile), # comparisonMode / configuration['outputMode'] is either bvh or 3d
1.0,
numberOfChannelsPerNSDMElement,
useRadians,
useHalfFloats
)
datasetUsedLabel="Train"
filenamePostfix=""
if (useTestData):
datasetUsedLabel="Test"
filenamePostfix="_test"
#Easier and faster way to get output list..
if (useCSVBackend):
inputLabelsWithoutNSDM = readCSVLabels("%s/2d_%s%s.csv" % (datasetDirectory,dataFile,filenamePostfix))
outputLabels = readCSVLabels("%s/%s_%s%s.csv" % (datasetDirectory,outputMode,dataFile,filenamePostfix)) #outputMode is either bvh or 3d
mapPath = "%s/map_%s%s.csv" % (datasetDirectory,dataFile,filenamePostfix)
else:
inputLabelsWithoutNSDM = groundTruthTrain["labelInNoNSDM"]
outputLabels = groundTruthTrain["labelOut"]
#No Map Path will cause an error in --identify
if (not checkIfConfigurationHierarchyIsTheSameAsLabelList(configuration,inputLabelsWithoutNSDM,0)):
print(bcolors.WARNING +"step0_DNNTrainer.py : Inconsistent Configuration association compared to the inputLabelList" + bcolors.ENDC )
sys.exit(1)
print("Input Labels (no NSDM) : ");
print(inputLabelsWithoutNSDM)
print("\nOutput Labels : ");
print(outputLabels)
numberOfOutputColumns=len(outputLabels)
#Initially we would have to do all outputs ourself
endPosition=numberOfOutputColumns
#But if a cluster has been set up we should only do *some* of the training
if (jobsPerCluster):
startPosition = jobsPerClusterStart
endPosition = jobsPerClusterEnd
print("\nWill run from ",startPosition," to ",endPosition," / ",numberOfOutputColumns);
RAMBefore = getRAMInformation()
print("Initial | free RAM ",RAMBefore['free']," KB");
#If we want to use the CSV loading back end here
#otherwise we assume groundTruthTrain and groundTruthTest have been already provided
if (useCSVBackend):
#---------------------------------------------------------------
#Simplify..
data2D = readCSVFile("%s/2d_%s%s.csv" % (datasetDirectory,dataFile,filenamePostfix),testMemPercentage,useHalfFloats)
dataBVH = readCSVFile("%s/%s_%s%s.csv" % (datasetDirectory,outputMode,dataFile,filenamePostfix),testMemPercentage,useHalfFloats)
groundTruthTest = dict()
groundTruthTest['labelIn'] = data2D['label']
groundTruthTest['in'] = data2D['body']
groundTruthTest['labelOut'] = dataBVH['label']
groundTruthTest['out'] = dataBVH['body']
checkIfTestAndTrainListsAreOk(groundTruthTest,groundTruthTrain)
#---------------------------------------------------------------
RAMAfter = getRAMInformation()
print("After reading the dataset | free RAM ",RAMAfter['free']," KB");
#----------------------------------------------------------------------------------------------------------
endAt = time.time()
print("Memory Occupied ",(RAMAfter['used']-RAMBefore['used'])/1024," MB")
print("Time required to load from disk was ",(endAt-startAt)/60," mins")
#
print("\n-------------------------------------------------");
#----------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------
#We have lodaded everything as normal but we only want to do identification in this run!
if (doOnlyIdentification):
identifyProblematicOutput(mapPath)
sys.exit(0)
#At this point we are ready..
#We should free whatever memory we have allocated because it is training time..!
#------------------------
gc.collect()
#------------------------
#Select a MocapNET class from tensorflow/tensorrt/onnx/tf-lite engines
from MocapNET import easyMocapNETConstructor
mnet = easyMocapNETConstructor(engine,
doProfiling=doProfiling,
doHCDPostProcessing = doHCDPostProcessing,
hcdLearningRate = hcdLearningRate,
hcdEpochs = hcdEpochs,
hcdIterations = hcdIterations
) #<- do not use post processing to actually evaluate MocapNET NN
mnet.test()
from align3DPoints import compareGroundTruthToPrediction
# Use body to grab all joints
#python3 evaluateMocapNET.py --mem 50 --config dataset/body_configuration.json --all upperbody
#-----------------------------------------------
totalSamples = 0
totalError = 0.0
averageErrorDistances = list()
allErrorDistanceSamples = list()
errorSamplesPerJoint = dict()
#-----------------------------------------------
numberOfSamples = len(groundTruthTest['in'])
#Declare joints we are interested in..
#-----------------------------------------
JOINTS_TO_COMPARE=list()
if (compareAllJoints==0):
JOINTS_TO_COMPARE.append('neck') #0
JOINTS_TO_COMPARE.append('rshoulder') #1
JOINTS_TO_COMPARE.append('relbow') #2
JOINTS_TO_COMPARE.append('rhand') #3
JOINTS_TO_COMPARE.append('lshoulder') #4
JOINTS_TO_COMPARE.append('lelbow') #5
JOINTS_TO_COMPARE.append('lhand') #6
JOINTS_TO_COMPARE.append('hip') #7
JOINTS_TO_COMPARE.append('rhip') #8
JOINTS_TO_COMPARE.append('rknee') #9
JOINTS_TO_COMPARE.append('rfoot') #10
JOINTS_TO_COMPARE.append('lhip') #11
JOINTS_TO_COMPARE.append('lknee') #12
JOINTS_TO_COMPARE.append('lfoot') #13
else:
print(bcolors.FAIL,"TODO: IMPLEMENT COMPARE ALL JOINTS",bcolors.ENDC)
sys.exit(1)
#Allocate errors per joint
#-----------------------------------------
if (len(JOINTS_TO_COMPARE)==0):
numberOfJoints = len(configuration["hierarchy"])
for jID in range (0,numberOfJoints):
jointName = configuration["hierarchy"][jID]["joint"].lower()
errorSamplesPerJoint[jointName]=list()
JOINTS_TO_COMPARE.append(jointName)
else:
numberOfJoints = len(JOINTS_TO_COMPARE)
for jID in range (0,numberOfJoints):
jointName = JOINTS_TO_COMPARE[jID].lower()
errorSamplesPerJoint[jointName]=list()
#-----------------------------------------
print("Doing evaluation based on errors of the following ",numberOfJoints," joints : ",JOINTS_TO_COMPARE)
f = open("evaluateMocapNET.lastresults.csv", "w")
#Append CSV Log
f.write("mae_from_%u_to_%u_step_%u\n" % (0,numberOfSamples,step))
framerates = list()
beginTime = time.time()
evaluationMode = "?"
frameNumber = 0 #<- simpler counter for nn subsampling
for thisSample in range(0,numberOfSamples,step) :
thisInputRaw = groundTruthTest['in'][thisSample]
correctOutputRaw = groundTruthTest['out'][thisSample]
regressedResult = dict()
correctResult = dict()
#DATA Looks like this : { 'labelInNoNSDM':names2D, 'labelIn':inputLabels, 'in':npInput, 'labelOut':outputLabels, 'out':npOutput };
thisInput = dict()
for i in range(0,len(groundTruthTest['labelIn'])):
thisLabelIn = groundTruthTest['labelIn'][i].lower()
if ( ( thisLabelIn.find("edm-")== -1 ) and ( thisLabelIn.find("nsrm-")== -1 ) ):
thisInput[thisLabelIn] = float(groundTruthTest['in'][thisSample][i])
#If we are dealing with just BVH output use training BVH output to extract 3D data
#------------------------------------------------------------------------------------------------------
if outputMode=="bvh":# (not 'outputMode' in configuration) or (configuration['outputMode'] == "bvh"):
evaluationMode="bvh"
correctOutput = dict()
for i in range(0,len(groundTruthTest['labelOut'])):
correctOutput[groundTruthTest['labelOut'][i]] = float(groundTruthTest['out'][thisSample][i])
correctResult = ground3DJointsFromBVH(mnet.bvh,correctOutput)
#------------------------------------------------------------------------------------------------------
#If we are dealing with 3D output immediately use training 3D output to compare 3D data
elif outputMode=="3d":# ('outputMode' in configuration) and (configuration['outputMode'] == "3d"):
evaluationMode="3d"
correctResult = dict()
for i in range(0,len(groundTruthTest['labelOut'])):
correctResult[groundTruthTest['labelOut'][i]] = float(groundTruthTest['out'][thisSample][i])
#------------------------------------------------------------------------------------------------------
startTime = time.time()
#================================================
#================================================
doNN = 1
if (doHCDPostProcessing) and (doNNEveryNFrames>1):
doNN = (frameNumber%doNNEveryNFrames)==0
#print("Frame ",frameNumber," doNN = ",doNN)
regressedResult = mnet.predict3DJoints(thisInput,runNN=doNN)
#================================================
#================================================
endTime = time.time()
processing_time = endTime - startTime
framerates.append(float(processing_time))
if (processing_time==0):
processing_time=1
#------------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------------
# Debug visualization (we shouldn't be doing a visualization in evaluateMocapNET.py)
#------------------------------------------------------------------------------------------------------
if (doDebugVisualization):
import cv2
import numpy as np
bgcolor = 30
annotated_image = np.full((1080,1920,3), bgcolor , dtype=np.uint8) #<--
from MocapNETVisualization import visualizeMocapNETEnsemble
image,plotImage = visualizeMocapNETEnsemble(mnet,annotated_image)
cv2.imshow('MocapNET 4 Evaluation', image)
if cv2.waitKey(1) & 0xFF == 27:
break
#------------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------------
#print("\n\n\n\nthisInput ",thisInput)
#print("\n\n\n\ncorrectOutput ",correctOutput)
#print("\n\n\n\regressedResult ",regressedResult)
#print("\n\n\n\n")
stats = compareGroundTruthToPrediction(
configuration,
correctResult, #<- We want to compare this
regressedResult, #<- to This
doProcrustes=doProcrustes,
allowProcrustesToChangeScale=1,
jointsToCompare=JOINTS_TO_COMPARE
)
#Append CSV log
f.write("%f\n" % (float(stats["meanAverageError"])))
#print("\nstats ",stats)
print("\nstats={",end="")
for k in stats.keys():
print("'%s':%0.2f, "%(k,stats[k]),end="")
print("}\n")
progressMessage = "Progress : %0.2f %% %u / %u %0.2f fps" % ((100*thisSample)/numberOfSamples,thisSample,numberOfSamples,1/processing_time)
print(progressMessage," Evaluation Mode :",bcolors.OKGREEN,evaluationMode,bcolors.ENDC,"\n\n\n\n")
#numberOfJoints = len(configuration["hierarchy"])
for jID in range (0,numberOfJoints):
jointName = JOINTS_TO_COMPARE[jID]
if jointName in stats:
allErrorDistanceSamples.append(float(stats[jointName]))
errorSamplesPerJoint[jointName].append(float(stats[jointName]))
totalSamples = totalSamples + 1
totalError = totalError + float(stats[jointName])
else:
print("Could not find ",jointName)
averageErrorDistances.append(float(stats["meanAverageError"]))
frameNumber = frameNumber + 1 #<- simpler counter for nn subsampling
endTime = time.time()
print("Finished in ",(endTime-beginTime)/60," minutes")
f.close()
import numpy as np
appendRAWResultsForGNUplot("alldistance.raw",averageErrorDistances)
#------------------------------------------
for jID in range (0,numberOfJoints):
jointName = JOINTS_TO_COMPARE[jID]
appendRAWResultsForGNUplot("joint_%s.raw"%jointName,errorSamplesPerJoint[jointName])
#------------------------------------------
meanProcessingTime = np.mean(framerates)
minimum = np.min(averageErrorDistances)
maximum = np.max(averageErrorDistances)
median = np.median(averageErrorDistances)
mean = np.mean(averageErrorDistances)
std = np.std(averageErrorDistances)
var = np.var(averageErrorDistances)
#------------------------------------------
title_string=" Min/Max=%0.1f/%0.1f,Mean=%0.1f,Median=%0.1f,Std=%0.1f,Var=%0.1f" % (minimum,maximum,mean,median,std,var)
#Show a summary
#------------------------------------------
print("Flops : ",mnet.getModelFlops()," Model Params : ",mnet.getModelParameters())
print("Upperbody Decomposition : ",mnet.ensemble["upperbody"].configuration["decompositionType"]," | Input Size : ",mnet.ensemble["upperbody"].configuration["PCADimensionsKept"])
print("EDM upperbody : ",mnet.ensemble["upperbody"].configuration["EDM"])
print("eNSRM upperbody : ",mnet.ensemble["upperbody"].configuration["eNSRM"])
print("Lowerbody Decomposition : ",mnet.ensemble["lowerbody"].configuration["decompositionType"]," | Input Size : ",mnet.ensemble["lowerbody"].configuration["PCADimensionsKept"])
print("EDM lowerbody : ",mnet.ensemble["lowerbody"].configuration["EDM"])
print("eNSRM lowerbody : ",mnet.ensemble["lowerbody"].configuration["eNSRM"])
print("Sample Step : %u / Total Samples %u "%(step,numberOfSamples))
print("Procrustes : %u"%doProcrustes)
print("Mean Framerate : %0.2f fps"%(1/meanProcessingTime))
print("doHCDPostProcessing = ",doHCDPostProcessing)
print("doNNEveryNFrames = ",doNNEveryNFrames)
print("hcdLearningRate = ",hcdLearningRate)
print("hcdEpochs = ",hcdEpochs)
print("hcdIterations = ",hcdIterations)
print("Result : %s "%title_string)
notification("MocapNET Network Evaluation","Done evaluating -> %s " % (title_string))
f = open(label+"_results.csv", "w")
f.write("Params,PCA,FPS,Min,Max,Median,Mean,Std,Var,HCD,NNSubsample,HCD_LR,HCD_Epochs,HCD_Iterations\n")
f.write("%0.2f"%(mnet.getModelParameters()/1000.0))
f.write(",")
f.write(str(mnet.ensemble["upperbody"].configuration["PCADimensionsKept"]))
f.write(",")
f.write("%0.2f"%(1/meanProcessingTime))
f.write(",")
f.write(str(minimum))
f.write(",")
f.write(str(maximum))
f.write(",")
f.write(str(median))
f.write(",")
f.write(str(mean))
f.write(",")
f.write(str(std))
f.write(",")
f.write(str(var))
f.write(",")
f.write(str(doHCDPostProcessing))
f.write(",")
f.write(str(doNNEveryNFrames))
f.write(",")
f.write(str(hcdLearningRate))
f.write(",")
f.write(str(hcdEpochs))
f.write(",")
f.write(str(hcdIterations))
f.write("\n")
f.close()
#Plotting !
#------------------------------------------
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(8, 4))
#------------------------------------------
x = averageErrorDistances
mu = 200
sigma = 25
n_bins = 100
# plot the cumulative histogram
n, bins, patches = ax.hist(x, n_bins, density=True, histtype='step',cumulative=True, label='Accuracy')
#------------------------------------------
# Add a line showing the expected distribution.
y = ((1 / (np.sqrt(2 * np.pi) * sigma)) *
np.exp(-0.5 * (1 / sigma * (bins - mu))**2))
y = y.cumsum()
y /= y[-1]
#------------------------------------------
#ax.plot(bins, y, 'k--', linewidth=1.5, label='Theoretical')
# tidy up the figure
ax.grid(True)
ax.legend(loc='right')
ax.set_title('Cumulative step histograms')
ax.set_xlabel('3D Error (mm)')
ax.set_ylabel('Likelihood of occurrence')
#------------------------------------------
#plt.show()
print("Done")
if __name__ == '__main__':
#When working standalone assume simple csv backend
emptyData = dict()
emptyTestData = { 'labelInNoNSDM': [], 'labelIn': [], 'in': [], 'labelOut':[], 'out': [] }
useCSVBackend=1
evaluateMocapNET(useCSVBackend,emptyData,emptyTestData)
+117
View File
@@ -0,0 +1,117 @@
#pip install numpy opencv-python --user
import numpy as np
import os
import sys
import cv2
from tools import eprint
"""
Check if a file exists
"""
def checkIfFileExists(filename):
return os.path.isfile(filename)
def resize_with_padding(image, width, height, DO_PADDING=True, TINY_FLOAT=1e-5):
"""
Resizes an image to the specified size,
adding padding to preserve the aspect ratio.
"""
shape_out=(height,width)
if image.ndim == 3 and len(shape_out) == 2:
shape_out = [*shape_out, 3]
hw_out, hw_image = [np.array(x[:2]) for x in (shape_out, image.shape)]
resize_ratio = np.min(hw_out / hw_image)
hw_wk = (hw_image * resize_ratio + TINY_FLOAT).astype(int)
# Resize the image
resized_image = cv2.resize(
image, tuple(hw_wk[::-1]), interpolation=cv2.INTER_NEAREST
)
if not DO_PADDING or np.all(hw_out == hw_wk):
return resized_image
# Create a black image with the target size
padded_image = np.zeros(shape_out, dtype=np.uint8)
# Calculate the number of rows/columns to add as padding
dh, dw = (hw_out - hw_wk) // 2
# Add the resized image to the padded image, with padding on the left and right sides
padded_image[dh : hw_wk[0] + dh, dw : hw_wk[1] + dw] = resized_image
return padded_image
class FolderStreamer():
def __init__(self,
path = "./",
label = "colorFrame_0_",
width = 0,
height = 0
):
self.path = path
self.label = label
self.frameNumber = 0
self.width = width
self.height = height
self.should_stop = False
def isOpened(self):
return not self.should_stop
def release(self):
print("Release Called ")
self.should_stop = True
def read(self):
# Read frame from camera
#----------------------------------------------------------------------
filenameJPG = "%s/%s%05u.jpg" % (self.path,self.label,self.frameNumber)
filenamePNG = "%s/%s%05u.png" % (self.path,self.label,self.frameNumber)
#----------------------------------------------------------------------
if (checkIfFileExists(filenameJPG)):
self.img = cv2.imread(filenameJPG)
elif (checkIfFileExists(filenamePNG)):
self.img = cv2.imread(filenamePNG)
else:
eprint("Could not find ",filenameJPG," or ",filenamePNG)
self.img = None
#----------------------------------------------------------------------
if not self.img is None:
if (self.width != 0) and (self.height != 0):
#--------------------------
width = self.img.shape[1]
height = self.img.shape[0]
eprint("Received Image size was ",width,"x",height, end = "")
#--------------------------
self.img = resize_with_padding(self.img, self.width, self.height)
#--------------------------
width = self.img.shape[1]
height = self.img.shape[0]
eprint(" Rescaled Image size is ",width,"x",height)
#--------------------------
success = True
self.frameNumber+=1
else:
success = False
self.should_stop = True
return success,self.img
def visualize(
self,
windowname='Object Detection',
width=800,
height=600
):
# Display output
cv2.imshow(windowname, cv2.resize(self.img,(width,height)))
if cv2.waitKey(10) & 0xff == ord('q'):
cv2.destroyAllWindows()
self.should_stop = True
#break
@@ -0,0 +1,610 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import os
import sys
import gc
import time
import numpy as np
#--------------------------------------------------
from tools import bcolors,notification,checkIfPathExists,checkIfPathIsDirectory,checkIfFileExists,getRAMInformation
ONNX_OPSET=17 # Was 14
def downloadAndParseDatabase():
file = "modelDatabase.json"
if (checkIfFileExists(file)):
print("Erasing previous database snapshot")
os.system('rm "%s"' % (file))
os.system('wget "http://ammar.gr/mocapnet/mnet4/database.php" && mv database.php "%s"' % file)
import json
db = []
with open(file) as f:
s = f.read()
s = s.replace('\t','')
s = s.replace('\n','')
s = s.replace(',}','}')
s = s.replace(',]',']')
db = json.loads(s)
return db
def quickCopy(step0,step1):
onnxModel = "%s/model.onnx" % step0
tfliteModel = "%s/model.tflite" % step0
if ( (not checkIfFileExists(onnxModel)) or (not checkIfFileExists(tfliteModel)) ):
print("No quick copy capability (old MocapNET package)")
return False
os.system('rm -rf %s/' % step1)
os.system('mkdir %s/' % step1)
os.system('cp %s/* %s/' % (step0,step1) )
return True
def downloadAndCompileSingle(file,part,step0,step1,json,pca,allowQuickCopy=True,download=1):
#---------------------------------------------------------------------------------------
if (download):
if (not checkIfFileExists(file)):
os.system('wget "http://ammar.gr/mocapnet/mnet4/%s"' % (file))
else:
print("Ensemble %s already exists locally" % (file))
#---------------------------------------------------------------------------------------
if checkIfPathExists(step0) and checkIfPathIsDirectory(step0):
print(bcolors.OKBLUE,"Clean up ",step0," \n",bcolors.ENDC)
os.system('rm -rf %s/'% (step0))
else:
print("Do not need to clear step0 ",step0)
if checkIfPathExists(step1) and checkIfPathIsDirectory(step1):
print(bcolors.OKBLUE,"Clean up ",step1," \n",bcolors.ENDC)
os.system('rm -rf %s/'% (step1))
else:
print("Do not need to clear step1 ",step1)
print(bcolors.OKBLUE,"Extracting models from ",file," \n",bcolors.ENDC)
#print(bcolors.OKBLUE,'tar -xf %s' % (file),bcolors.ENDC)
os.system('tar -xf %s' % (file))
if (allowQuickCopy) and (quickCopy(step0,step1)):
print(bcolors.OKBLUE,"Quick Copied models \n",bcolors.ENDC)
else:
print(bcolors.OKBLUE,"Combine models \n",bcolors.ENDC)
#os.system('cp %s/%s dataset/'%(step0,pca)) #We dont need to do this it will be done automatically from step1_DNNCombine.py
#os.system('mkdir %s/'%step1) #We dont need to do this it will be done automatically from step1_DNNCombine.py
#os.system('cp %s/%s %s/'%(step0,json,step1))#We dont need to do this it will be done automatically from step1_DNNCombine.py
#os.system('cp %s/%s %s/'%(step0,pca,step1))#We dont need to do this it will be done automatically from step1_DNNCombine.py
print(bcolors.OKBLUE,"Combining %s \n"%part,bcolors.ENDC)
print(bcolors.OKBLUE,'python3 -m step1_DNNCombine --config %s/%s --all %s'%(step0,json,part),bcolors.ENDC)
return_value = os.system('python3 -m step1_DNNCombine --config %s/%s --all %s'%(step0,json,part))
if (return_value!=0):
print(bcolors.FAIL,"Failed preparing ",part," stopping model database retrieval",bcolors.ENDC)
raise IOError
#---------------------------------------------------------------------------------------
gc.collect()
#---------------------------------------------------------------------------------------
RAM = getRAMInformation()
if (RAM["free"]>=2000000):
os.system('python3 -m tf2onnx.convert --saved-model %s --opset %u --tag serve --output %s/model.onnx' % (step1,ONNX_OPSET,step1))
os.system('tflite_convert --saved_model_dir=%s --output_file=%s/model.tflite' % (step1,step1))
else:
print(bcolors.FAIL,"Not Enough RAM (we have ",RAM["free"],") to perform ONNX/TF-Lite conversions!",bcolors.ENDC)
notification("MocapNET Database","Finished Compiling MocapNET %s ensemble" % part)
def downloadAndCompileModel(fileUpper,fileLower,fileHand="",fileFace="",fileReye="",fileMouth="",allowQuickCopy=True,download=1):
#---------------------------------------------------------------------------------------
if (fileUpper!=""):
downloadAndCompileSingle(
fileUpper,
"upperbody",
"step0_upperbody_all",
"step1_upperbody_all",
"upperbody_configuration.json",
"upperbody_all.pca",
allowQuickCopy=allowQuickCopy
)
#---------------------------------------------------------------------------------------
if (fileLower!=""):
downloadAndCompileSingle(
fileLower,
"lowerbody",
"step0_lowerbody_all",
"step1_lowerbody_all",
"lowerbody_configuration.json",
"lowerbody_all.pca",
allowQuickCopy=allowQuickCopy
)
#---------------------------------------------------------------------------------------
if (fileHand!=""):
downloadAndCompileSingle(
fileHand,
"lhand",
"step0_lhand_all",
"step1_lhand_all",
"lhand_configuration.json",
"lhand_all.pca",
allowQuickCopy=allowQuickCopy
)
#---------------------------------------------------------------------------------------
if (fileFace!=""):
downloadAndCompileSingle(
fileFace,
"face",
"step0_face_all",
"step1_face_all",
"face_configuration.json",
"face_all.pca",
allowQuickCopy=allowQuickCopy
)
#---------------------------------------------------------------------------------------
if (fileReye!=""):
downloadAndCompileSingle(
fileReye,
"reye",
"step0_reye_all",
"step1_reye_all",
"reye_configuration.json",
"reye_all.pca",
allowQuickCopy=allowQuickCopy
)
#---------------------------------------------------------------------------------------
if (fileMouth!=""):
downloadAndCompileSingle(
fileMouth,
"mouth",
"step0_mouth_all",
"step1_mouth_all",
"mouth_configuration.json",
"mouth_all.pca",
allowQuickCopy=allowQuickCopy
)
#---------------------------------------------------------------------------------------
print(bcolors.OKGREEN,"Models ready for use \n",bcolors.ENDC)
print(bcolors.OKGREEN,"try : python3 -m PoseNET --from shuffle.webm\n",bcolors.ENDC)
print(bcolors.OKGREEN,"or : python3 -m evaluateMocapNET --config dataset/body_configuration.json --all body --skip 5\n",bcolors.ENDC)
#---------------------------------------------------------------------------------------
notification("MocapNET Database","Finished Compiling MocapNET ensemble")
def retrieveAndSetupModel(PCADimensions:int,parameterCount:int,download:int=0):
#Baseline
fileUpper = "87A_Training-22-05-06_13-22-16-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "87B_Training-22-05-06_22-29-54-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
#PCA 15 - 105K Parameters
if (PCADimensions==15) and (parameterCount==105):
fileUpper = "81B_Training-22-05-03_05-10-48-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "82B_Training-22-05-03_15-03-10-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (PCADimensions==15) and (parameterCount==32):
fileUpper = "84B_Training-22-05-05_17-12-02-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "85B_Training-22-05-06_03-08-00-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (PCADimensions==30) and (parameterCount==105):
fileUpper = "79B_Training-22-05-01_06-59-02-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "80B_Training-22-05-01_17-01-13-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (PCADimensions==30) and (parameterCount==32):
fileUpper = "90A_Training-22-05-08_17-56-16-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "90B_Training-22-05-09_00-15-55-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (PCADimensions==60) and (parameterCount==105):
fileUpper = "94A_Training-22-05-10_13-08-52-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "94B_Training-22-05-10_19-18-19-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==60) and (parameterCount==32):
fileUpper = "93A_Training-22-05-09_17-37-46-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "93B_Training-22-05-10_01-27-31-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (PCADimensions==90) and (parameterCount==105):
fileUpper = "77B_Training-22-04-29_18-02-28-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "78B_Training-22-04-30_03-20-33-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (PCADimensions==90) and (parameterCount==32):
fileUpper = "88A_Training-22-05-07_09-20-26-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "88B_Training-22-05-07_17-03-03-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (PCADimensions==120) and (parameterCount==105):
fileUpper = "96A_Training-22-05-11_09-31-02-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "96B_Training-22-05-11_15-52-05-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==120) and (parameterCount==32):
fileUpper = "77A_Training-22-04-28_22-55-49-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "78A_Training-22-04-29_05-11-09-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==150) and (parameterCount==105):
fileUpper = "79A_Training-22-04-30_12-55-12-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "80A_Training-22-04-30_19-08-26-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==150) and (parameterCount==32):
fileUpper = "92A_Training-22-05-09_11-28-35-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "92B_Training-22-05-09_18-00-37-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==180) and (parameterCount==105):
fileUpper = "99A_Training-22-05-13_01-55-31-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "99B_Training-22-05-13_08-45-27-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==180) and (parameterCount==32):
fileUpper = "91A_Training-22-05-08_11-35-19-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "91B_Training-22-05-08_18-15-12-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==210) and (parameterCount==105):
fileUpper = "83A_Training-22-05-03_03-35-52-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "83B_Training-22-05-03_10-10-19-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==210) and (parameterCount==30):
fileUpper = "103A_Training-22-05-20_07-41-34-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "103B_Training-22-05-21_01-16-48-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==210) and (parameterCount==32):
fileUpper = "84A_Training-22-05-04_11-39-49-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "85A_Training-22-05-04_19-08-05-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==210) and (parameterCount==417):
#12 layers deep!
fileUpper = "106A_Training-22-07-11_09-35-20-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "106B_Training-22-07-11_15-57-01-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==210) and (parameterCount==326):
#12 layers deep!
fileUpper = "107A_Training-22-07-13_09-30-24-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "107B_Training-22-07-13_15-40-47-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==210) and (parameterCount==83):
#6 layers deep!
fileUpper = "100A_Training-22-05-14_21-23-11-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "100B_Training-22-05-15_02-28-09-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==210) and (parameterCount==64):
#4 layers deep!
fileUpper = "101A_Training-22-05-16_04-13-58-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "101B_Training-22-05-16_08-08-49-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (PCADimensions==323) and (parameterCount==105):
fileUpper = "95A_Training-22-05-11_04-10-01-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "95B_Training-22-05-11_11-26-16-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (PCADimensions==323) and (parameterCount==32):
print("TODO")
elif (PCADimensions==323) and (parameterCount==153):
fileUpper = "87A_Training-22-05-06_13-22-16-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "87B_Training-22-05-06_22-29-54-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
else:
print(bcolors.WARNING,"Unknown combination PCA dims ",PCADimensions," and ",parameterCount,"K parameters \n",bcolors.ENDC)
print(bcolors.WARNING,"Completely halting execution to avoid a wrong run!\n",bcolors.ENDC)
sys.exit(1)
return;
print("Selecting PCA dims ",PCADimensions," and ",parameterCount," K parameters \n")
downloadAndCompileModel(fileUpper,fileLower,download=download)
def retrieveAndSetupBasedOnSerial(serial:int,allowQuickCopy:bool=True,download:int=0):
#Baseline
fileUpper = "" #"116A_Training-22-09-01_00-27-23-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "" #"116B_Training-22-09-01_06-19-41-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileHand = ""
fileFace = ""
fileReye = ""
fileMouth = ""
if (serial==116):
fileUpper = "116A_Training-22-09-01_00-27-23-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "116B_Training-22-09-01_06-19-41-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (serial==117):
fileUpper = "117A_Training-22-09-02_15-14-17-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "117B_Training-22-09-03_03-56-55-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (serial==118):
fileUpper = "118A_Training-22-09-05_02-34-35-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "118B_Training-22-09-05_10-27-46-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (serial==119):
fileUpper = "119A_Training-22-09-05_23-19-05-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "119B_Training-22-09-06_05-52-27-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (serial==120):
fileUpper = "120A_Training-22-09-06_19-16-27-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "120B_Training-22-09-07_00-21-03-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (serial==125):
fileUpper = "125-A-Training-22-10-12_06-28-17-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "125-B-Training-22-10-12_12-06-36-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (serial==128):
fileUpper = "128-a-remanual.tar.bz2"
fileLower = "128-b-remanual.tar.bz2"
elif (serial==129):
fileUpper = "129-A-Training-22-10-18_01-17-44-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "129-B-Training-22-10-18_07-11-41-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==130):
fileUpper = "130-A-Training-22-10-19_23-50-56-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "130-B-Training-22-10-20_07-05-38-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (serial==131):
fileUpper = "131-A-manual.tar.bz2"
fileLower = "131-B-manual.tar.bz2"
elif (serial==132):
fileUpper = "132-A-Training-22-10-23_21-16-03-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "132-B-Training-22-10-24_07-28-31-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==133):
fileUpper = "133-A-Training-22-10-25_08-24-58-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "133-B-Training-22-10-25_16-11-05-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==134):
fileUpper = "134-A-Training-22-10-27_06-52-13-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "134-B-Training-22-10-28_20-21-16-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (serial==137):
fileUpper = "137-A-Training-22-10-29_05-15-56-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "137-B-Training-22-10-29_10-55-49-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==138):
fileUpper = "138-A-Training-22-10-30_03-45-34-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "138-B-Training-22-10-30_12-51-38-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==139):
fileUpper = "139-A-Training-22-10-31_04-38-46-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "139-B-Training-22-10-31_13-29-44-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==140):
fileUpper = "140-A-Training-22-11-02_09-41-59-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "140-B-Training-22-11-02_17-37-13-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==150):
fileUpper = "150-A-Training-22-12-01_05-34-13-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "150-B-Training-22-12-02_06-58-52-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==168):
fileUpper = "168-A-Training-23-01-28_22-23-09-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "168-B-Training-23-01-31_02-23-50-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileHand = "169A-Training-23-02-02_19-05-54-lhand-ammar-forth-Ubuntu-20.04.tar.bz2"
fileFace = "167A-Training-23-01-27_10-23-03-face-elina-kriti-Ubuntu-22.04.tar.bz2"
elif (serial==170):
fileUpper = "170-A-Training-23-02-05_18-10-16-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "170-B-Training-23-02-06_03-49-34-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileHand = "169B-Training-23-02-05_13-51-44-lhand-cvrl-demo-Ubuntu-18.04.tar.bz2"
elif (serial==174):
fileUpper = "174-A-Training-23-02-16_12-34-37-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "174-B-Training-23-02-17_07-21-02-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileHand = "169B-Training-23-02-05_13-51-44-lhand-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileFace = "176A-Training-23-02-17_15-49-14-face-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==177):
fileUpper = "174-A-Training-23-02-16_12-34-37-upperbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileLower = "174-B-Training-23-02-17_07-21-02-lowerbody-ammar-forth-Ubuntu-20.04.tar.bz2"
fileHand = "175B-Training-23-02-21_05-10-46-lhand-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileFace = "176A-Training-23-02-17_15-49-14-face-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==193):
fileUpper = "193-A-Training-23-03-18_22-07-35-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "193-B-Training-23-03-21_01-31-46-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
#fileHand = "175B-Training-23-02-21_05-10-46-lhand-cvrl-demo-Ubuntu-18.04.tar.bz2"
#fileFace = "176A-Training-23-02-17_15-49-14-face-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==209):
fileUpper = "209-A-Training-23-03-23_16-11-00-upperbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileLower = "209-B-Training-23-03-24_13-16-47-lowerbody-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileHand = "217A-Training-23-04-11_03-40-56-lhand-cvrl-demo-Ubuntu-18.04.tar.bz2"
#fileFace = "176A-Training-23-02-17_15-49-14-face-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==217):
fileHand = "217A-Training-23-04-11_03-40-56-lhand-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileUpper = ""
fileLower = ""
elif (serial==232):
fileUpper = "232-A-Training-23-04-21_17-14-06-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2" #ffe5156750f3 is supermicro docker container
fileLower = "232-B-Training-23-04-21_21-37-52-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileHand = "230A-Training-23-04-24_11-14-08-lhand-cvrl-demo-Ubuntu-18.04.tar.bz2"
fileFace = "233A-Training-23-04-23_06-39-35-face-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==234):
fileUpper = "234-A-Training-23-04-25_06-27-18-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "234-B-Training-23-04-26_00-29-55-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==241):
fileUpper = "241-A-Training-23-05-05_20-51-52-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "241-B-Training-23-05-06_01-32-59-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==242):
fileUpper = "242-A-Training-23-05-07_11-16-13-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "242-B-Training-23-05-07_16-18-47-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==262):
fileUpper = "262-A-Training-23-05-20_10-41-38-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "262-B-Training-23-05-21_12-00-38-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
#fileHand = "251A-Training-23-05-19_17-32-01-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
#fileReye = "261B-Training-23-05-19_03-25-32-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
#fileMouth = "253A-Training-23-05-13_09-53-34-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==269):
fileUpper = "268-A-Training-23-05-27_20-01-59-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "268-B-Training-23-05-28_16-05-19-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileHand = "269A-Training-23-05-30_22-06-06-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileReye = "267B-Training-23-05-26_06-50-57-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
fileMouth = "269B-Training-23-05-29_09-46-36-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==266):
fileUpper = "266-A-Training-23-05-25_12-31-28-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "266-B-Training-23-05-25_21-46-50-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==268):
fileUpper = "268-A-Training-23-05-27_20-01-59-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "268-B-Training-23-05-28_16-05-19-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==270):
fileUpper = "270-A-Training-23-05-30_16-32-29-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "270-B-Training-23-05-31_12-36-21-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==272):
fileUpper = "272-A-Training-23-06-03_06-50-09-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "272-B-Training-23-06-04_22-01-12-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==274):
fileUpper = "274-A-Training-23-06-07_23-45-42-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "274-B-Training-23-06-09_19-32-34-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==277):
fileUpper = "277-A-Training-23-06-11_21-50-57-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "277-B-Training-23-06-13_08-41-09-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==279):
fileUpper = "279-A-Training-23-06-15_13-36-59-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "279-B-Training-23-06-16_23-44-25-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==282):
fileUpper = "282-A-Training-23-06-18_06-16-23-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "282-B-Training-23-06-19_03-35-29-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==284):
#fileUpper = "282-A-Training-23-06-18_06-16-23-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
#fileLower = "282-B-Training-23-06-19_03-35-29-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
#fileHand = "280B-Training-23-06-17_14-26-51-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileReye = "283A-Training-23-06-19_10-01-31-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
fileMouth = "284A-Training-23-06-20_12-01-36-mouth-ammar-forth-Ubuntu-20.04.tar.bz2" #<- Paper FACE
elif (serial==285):
fileUpper = "285-A-Training-23-06-20_18-26-12-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "285-B-Training-23-06-21_10-17-45-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==287):
fileUpper = "287-A-Training-23-06-22_13-25-01-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "287-B-Training-23-06-23_07-02-15-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==289):
fileUpper = "289-A-Training-23-06-24_21-37-02-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "289-B-Training-23-06-25_03-03-02-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
elif (serial==290):
fileUpper = "289-A-Training-23-06-24_21-37-02-upperbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileLower = "289-B-Training-23-06-25_03-03-02-lowerbody-cvrl-demo-Ubuntu-20.04.tar.bz2"
fileHand = "290A-Training-23-06-28_10-31-52-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileReye = "290B-Training-23-06-27_14-48-40-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
fileMouth = "284B-Training-23-06-21_03-14-26-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==292):
fileUpper = "292-A-Training-23-07-09_18-18-30-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "292-B-Training-23-07-10_13-51-52-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==293):
fileMouth = "293B-Training-23-07-13_05-05-04-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==294):
fileUpper = "294-A-Training-23-07-11_19-04-21-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "294-B-Training-23-07-12_01-32-27-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==295):
fileUpper = "295-A-Training-23-07-12_16-47-41-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "295-B-Training-23-07-12_22-49-19-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==297):
fileUpper = "297-A-Training-23-07-14_16-50-22-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "297-B-Training-23-07-14_21-34-29-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileReye = "297A-Training-23-07-14_07-26-12-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
fileMouth = "293B-Training-23-07-13_05-05-04-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==300):
fileUpper = "300-A-Training-23-07-16_02-44-28-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "300-B-Training-23-07-16_07-40-40-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==301):
fileUpper = "301-A-Training-23-07-16_17-58-25-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "301-B-Training-23-07-16_22-45-49-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==302):
fileUpper = "302-A-Training-23-07-17_06-32-23-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "302-B-Training-23-07-17_11-35-01-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==304):
fileUpper = "302-A-Training-23-07-17_06-32-23-upperbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileLower = "302-B-Training-23-07-17_11-35-01-lowerbody-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileHand = "290A-Training-23-06-28_10-31-52-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileMouth = "299B-Training-23-07-17_08-29-17-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
fileReye = "304A-Training-23-07-19_16-51-17-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==305):
fileHand = "305B-Training-23-07-29_09-52-21-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==307):
fileHand = "307A-Training-23-08-19_23-23-06-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
elif (serial==310): #COMMON LOSS EXPERIMENTS
fileHand = "307B-Training-23-09-08_13-54-22-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "309-A-Training-23-09-08_00-20-09-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "310B.tar.bz2"
fileMouth = "299B-Training-23-07-17_08-29-17-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
fileReye = "304A-Training-23-07-19_16-51-17-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==314): #COMMON LOSS EXPERIMENTS
fileHand = "314C-Training-23-09-12_09-40-45-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "314-A-Training-23-09-11_07-21-06-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "314-B-Training-23-09-11_17-55-38-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "299B-Training-23-07-17_08-29-17-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
fileReye = "304A-Training-23-07-19_16-51-17-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==314): #COMMON LOSS EXPERIMENTS
fileHand = "314C-Training-23-09-12_09-40-45-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "314-A-Training-23-09-11_07-21-06-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "314-B-Training-23-09-11_17-55-38-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "299B-Training-23-07-17_08-29-17-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
fileReye = "304A-Training-23-07-19_16-51-17-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==-314): #AUGMENTED HAND FROM THE FUTURE / COMMON LOSS EXPERIMENTS
fileHand = "323A-Training-23-10-11_21-40-44-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "314-A-Training-23-09-11_07-21-06-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "314-B-Training-23-09-11_17-55-38-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "299B-Training-23-07-17_08-29-17-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
fileReye = "304A-Training-23-07-19_16-51-17-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==315): #COMMON LOSS EXPERIMENTS
fileHand = "314D-Training-23-09-14_02-14-17-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "315-A-Training-23-09-14_00-34-56-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "315-B-Training-23-09-14_09-00-31-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "299B-Training-23-07-17_08-29-17-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
fileReye = "304A-Training-23-07-19_16-51-17-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==317): #COMMON LOSS EXPERIMENTS
fileHand = "315C-Training-23-09-16_09-40-44-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "317-A-Training-23-09-19_00-29-49-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "317-B-Training-23-09-19_08-00-19-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "299B-Training-23-07-17_08-29-17-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
fileReye = "304A-Training-23-07-19_16-51-17-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==318): #COMMON LOSS EXPERIMENTS
fileHand = "318C-Training-23-09-28_13-58-59-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "318-A-Training-23-09-19_23-26-18-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "318-B-Training-23-09-20_08-16-26-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "299B-Training-23-07-17_08-29-17-mouth-ammar-forth-Ubuntu-20.04.tar.bz2"
fileReye = "304A-Training-23-07-19_16-51-17-reye-ammar-forth-Ubuntu-20.04.tar.bz2"
elif (serial==319): #COMMON LOSS EXPERIMENTS
fileHand = "318C-Training-23-09-28_13-58-59-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "319-A-Training-23-09-21_11-34-19-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "319-B-Training-23-09-21_18-59-56-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "318D-Training-23-09-25_17-06-26-mouth-ammar-forth-Ubuntu-22.04.tar.bz2"
fileReye = "320B-Training-23-09-24_23-08-19-reye-ammar-forth-Ubuntu-22.04.tar.bz2"
elif (serial==324): #COMMON LOSS EXPERIMENTS
fileHand = "323B-Training-23-10-26_21-41-51-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "324-A-Training-23-10-11_07-49-40-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "324-B-Training-23-10-11_17-24-31-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "318D-Training-23-09-25_17-06-26-mouth-ammar-forth-Ubuntu-22.04.tar.bz2"
fileReye = "320B-Training-23-09-24_23-08-19-reye-ammar-forth-Ubuntu-22.04.tar.bz2"
elif (serial==325): #COMMON LOSS EXPERIMENTS
fileHand = "323B-Training-23-10-26_21-41-51-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "325-A-Training-23-10-13_19-20-50-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "325-B-Training-23-10-13_23-35-55-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "318D-Training-23-09-25_17-06-26-mouth-ammar-forth-Ubuntu-22.04.tar.bz2"
fileReye = "320B-Training-23-09-24_23-08-19-reye-ammar-forth-Ubuntu-22.04.tar.bz2"
elif (serial==326): #COMMON LOSS EXPERIMENTS
fileHand = "323B-Training-23-10-26_21-41-51-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "326-A-Training-23-10-14_10-10-30-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "326-B-Training-23-10-14_17-49-14-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "318D-Training-23-09-25_17-06-26-mouth-ammar-forth-Ubuntu-22.04.tar.bz2"
fileReye = "320B-Training-23-09-24_23-08-19-reye-ammar-forth-Ubuntu-22.04.tar.bz2"
elif (serial==327): #COMMON LOSS EXPERIMENTS
fileHand = "323B-Training-23-10-26_21-41-51-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "327-A-Training-23-10-19_21-52-53-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "327-B-Training-23-10-20_04-48-26-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "318D-Training-23-09-25_17-06-26-mouth-ammar-forth-Ubuntu-22.04.tar.bz2"
fileReye = "320B-Training-23-09-24_23-08-19-reye-ammar-forth-Ubuntu-22.04.tar.bz2"
elif (serial==328): #COMMON LOSS EXPERIMENTS
fileHand = "323B-Training-23-10-26_21-41-51-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "328-A-Training-23-10-20_17-07-08-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "328-B-Training-23-10-20_23-34-06-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "318D-Training-23-09-25_17-06-26-mouth-ammar-forth-Ubuntu-22.04.tar.bz2"
fileReye = "320B-Training-23-09-24_23-08-19-reye-ammar-forth-Ubuntu-22.04.tar.bz2"
elif (serial==339): #COMMON LOSS EXPERIMENTS
fileHand = "323B-Training-23-10-26_21-41-51-lhand-ffe5156750f3-Ubuntu-20.04.tar.bz2"
fileUpper = "339-A-Training-23-11-10_08-28-59-upperbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileLower = "339-B-Training-23-11-10_15-36-02-lowerbody-ammar-forth-Ubuntu-22.04.tar.bz2"
fileMouth = "318D-Training-23-09-25_17-06-26-mouth-ammar-forth-Ubuntu-22.04.tar.bz2"
fileReye = "320B-Training-23-09-24_23-08-19-reye-ammar-forth-Ubuntu-22.04.tar.bz2"
else:
print(bcolors.WARNING,"Unknown serial ",serial,bcolors.ENDC)
print(bcolors.WARNING,"Completely halting execution to avoid a wrong run!\n",bcolors.ENDC)
sys.exit(1)
return;
print("Selecting Serial ",serial," => ",fileUpper," ",fileLower," \n")
print("FileHand ",fileHand," fileFace ",fileFace," \n")
downloadAndCompileModel(fileUpper,fileLower,fileHand=fileHand,fileFace=fileFace,fileReye=fileReye,fileMouth=fileMouth,allowQuickCopy=allowQuickCopy,download=download)
if __name__ == '__main__':
startEverythingAt = time.time()
RAM = getRAMInformation()
print("RAM : ",RAM)
if (RAM["free"]<2000000):
print(bcolors.FAIL,"We do not have enough memory (we have ",RAM["free"],") for ONNX / TF-Lite model so stopping..",bcolors.ENDC)
raise MemoryError
db = downloadAndParseDatabase()
print(db)
#sys.exit(0)
serial=0
allowQuickCopy = False
#When working standalone assume simple csv backend
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--noquickcopy"):
allowQuickCopy = False
if (sys.argv[i]=="--quickcopy"):
allowQuickCopy = True
#--------------------------------------
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--getPCA"):
PCADimensions =int(sys.argv[i+1])
parameterCount=int(sys.argv[i+2])
retrieveAndSetupModel(PCADimensions,parameterCount)
if (sys.argv[i]=="--get"):
serial =int(sys.argv[i+1])
retrieveAndSetupBasedOnSerial(serial,allowQuickCopy=allowQuickCopy,download=1)
#--------------------------------------
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--pack"):
print(bcolors.WARNING,"Packaging to -> mnet4_%u.zip "%(serial),bcolors.ENDC)
os.system('zip mnet4_%u.zip step1_*/*' % (serial))
endAt = time.time()
finalMessage="getModelFromDatabase run took %0.2f mins"%((endAt-startEverythingAt)/60)
print(finalMessage)
File diff suppressed because it is too large Load Diff
+81
View File
@@ -0,0 +1,81 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
class JointDataMapper:
#-----------------------------------------------------------------
def __init__(self, csvFilename, configuration , jointLabels):
self.filename = csvFilename
self.jointLabelToJointIDMap = dict()
self.numberOfExpectedLabels = len(jointLabels)
jID = 0
for jointDescription in jointLabels:
self.jointLabelToJointIDMap[jointDescription.lower()]=jID
jID = jID+1
#-----------------------------------------------------------------
def checkJointListDimensions(self,jointLabels):
return self.numberOfExpectedLabels == len(jointLabels)
#-----------------------------------------------------------------
def getJointID_2DX(self,jointName):
nname = "2dx_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_2DX: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_2DY(self,jointName):
nname = "2dy_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_2DY: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_2DZ(self,jointName):
nname = "2dz_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_2DZ: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_3DX(self,jointName):
nname = "3dx_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_3DX: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_3DY(self,jointName):
nname = "3dy_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_3DY: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_3DZ(self,jointName):
nname = "3dz_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_3DZ: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_Visibility(self,jointName):
nname = "visible_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_Visibility: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_Exists(self,jointName):
nnameX = "2dx_"+jointName.lower()
nnameY = "2dy_"+jointName.lower()
if ((nnameX in self.jointLabelToJointIDMap) and (nnameY in self.jointLabelToJointIDMap)):
return True
return False
#-----------------------------------------------------------------
if __name__ == '__main__':
print("jointMap.py is a library it cannot be run standalone")
@@ -0,0 +1,622 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
#pip install mediapipe pandas pillow matplotlib opencv-python
import cv2
import mediapipe as mp
import numpy as np
import time
import sys
import os
from readCSV import parseConfiguration,zeroOutXYJointsThatAreInvisible,performNSRMAlignment
from NSDM import NSDMLabels,createNSDMUsingRules
from tools import secondsToHz,eprint
from MocapNET import MocapNET
mp_drawing = mp.solutions.drawing_utils
mp_holistic = mp.solutions.holistic
mp_face_mesh = mp.solutions.face_mesh
#------------------------------------------------------------------------------------------------
LEFT_EYE = [362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385,384, 398 ]
LEFT_IRIS = [474,475, 476, 477]
RIGHT_EYE = [33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161 , 246 ]
RIGHT_IRIS = [469, 470, 471, 472]
#------------------------------------------------------------------------------------------------
#I have added a seperate list with the joints
from holisticPartNames import getHolisticBodyNameList, getHolisticFaceNameList, getHolisticLHandNameList, getHolisticRHandNameList, processPoseLandmarks, guessLandmarks
#------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MEDIAPIPE_BODY_LANDMARK_NAMES = getHolisticBodyNameList()
MEDIAPIPE_FACE_LANDMARK_NAMES = getHolisticFaceNameList()
MEDIAPIPE_LHAND_LANDMARK_NAMES = getHolisticLHandNameList()
MEDIAPIPE_RHAND_LANDMARK_NAMES = getHolisticRHandNameList()
#------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class MediaPipePose():
def __init__(self,doMediapipeVisualization = False):
#Tensorflow attempt to be reasonable
#------------------------------------------
self.mp = mp_holistic.Holistic(static_image_mode=True)
#------------------------------------------
self.doMediapipeVisualization = doMediapipeVisualization
self.output = dict()
#------------------------------------------
def get2DOutput(self):
return self.output
def processIncomingBodyOnlyLandmarks(self,body,currentAspectRatio,trainedAspectRatio):
#This function runs ~10000Hz
#-----------------------------------------------
mnetPose2D = dict()
#------------------------------------------------------------------------------------
processPoseLandmarks(mnetPose2D,MEDIAPIPE_BODY_LANDMARK_NAMES ,body,currentAspectRatio,trainedAspectRatio)
#------------------------------------------------------------------------------------
guessLandmarks(mnetPose2D) #Some landmarks ( neck, hip need to be guessed by others )
#-----------------------------------------------
return mnetPose2D
def processIncomingAllLandmarks(self,landmarks,currentAspectRatio,trainedAspectRatio):
#This function runs ~10000Hz
#-----------------------------------------------
mnetPose2D = dict()
#------------------------------------------------------------------------------------
processPoseLandmarks(mnetPose2D,MEDIAPIPE_BODY_LANDMARK_NAMES ,landmarks.pose_landmarks,currentAspectRatio,trainedAspectRatio)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_LHAND_LANDMARK_NAMES,landmarks.left_hand_landmarks,currentAspectRatio,trainedAspectRatio,threshold=0.001)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_RHAND_LANDMARK_NAMES,landmarks.right_hand_landmarks,currentAspectRatio,trainedAspectRatio,threshold=0.001)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_FACE_LANDMARK_NAMES ,landmarks.face_landmarks,currentAspectRatio,trainedAspectRatio)
#------------------------------------------------------------------------------------
guessLandmarks(mnetPose2D) #Some landmarks ( neck, hip need to be guessed by others )
#-----------------------------------------------
return mnetPose2D
def convertImageToMocapNETInput(self,image):
#holistic = self.mp
if (type(image)==type(None)):
print("Invalid Image given, can't do anything with it")
return dict() , image
width = image.shape[1]
height = image.shape[0]
if ((width==0) or (height==0)):
print("Cannot work with empty image")
return dict() , image
#Try to speed up by scaling down image
#if ( (width>1024) or (height>720) ):
# width = int(image.shape[1]/2)
# height = int(image.shape[0]/2)
# image = cv2.resize(image, (width,height))
#The aspect ratios involved
currentAspectRatio = width/height
trainedAspectRatio = 1920/1080
#-----------------------------------------------
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_pose = mp.solutions.pose
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
mocapNETInput = dict()
with mp_pose.Pose(static_image_mode=True,smooth_landmarks=True,model_complexity=0,enable_segmentation=True,min_detection_confidence=0.5) as pose:
# with mp_holistic.Holistic(static_image_mode=True) as holistic:
start = time.time()
#-----------------------------------------------
results = pose.process(image)
#results = holistic.process(image)
#Draw the pose annotation on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
if (self.doMediapipeVisualization):
try:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACEMESH_TESSELATION) #This used to be called FACE_CONNECTIONS
except:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACE_CONNECTIONS) #This used to be called FACE_CONNECTIONS
mp_drawing.draw_landmarks(image, results.left_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
mp_drawing.draw_landmarks(image, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
mp_drawing.draw_landmarks(
image,
results.pose_landmarks,
mp_pose.POSE_CONNECTIONS,
landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style()
)
#Body only
#-----------------------------------------------
mocapNETInput = self.processIncomingBodyOnlyLandmarks(results.pose_landmarks,currentAspectRatio,trainedAspectRatio)
#mocapNETInput = self.processIncomingAllLandmarks(results,currentAspectRatio,trainedAspectRatio)
#-----------------------------------------------
end = time.time()
# Time elapsed
seconds = end - start
if (seconds==0.0):
seconds=1.0
# Calculate frames per second
fps = 1 / seconds
#print("Mediapipe Pose Only 2D Joint Estimation Framerate : ",round(fps,2)," fps \n", end="", flush=True)
self.output = mocapNETInput
return mocapNETInput,image
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
class MediaPipeHolistic():
def __init__(self,doMediapipeVisualization = False):
#Tensorflow attempt to be reasonable
#------------------------------------------
self.mp = mp_holistic.Holistic(
static_image_mode=False,
model_complexity=1, #1 = default complexity, 2 = high complexity
min_detection_confidence=0.2,
min_tracking_confidence=0.2
)
#------------------------------------------
#self.mpHands = mp.solutions.hands.Hands(
# min_detection_confidence=0.5,
# min_tracking_confidence=0.5
# )
#------------------------------------------
self.mpFace = mp_face_mesh.FaceMesh(
max_num_faces=1,
refine_landmarks=True,
min_detection_confidence=0.3,
min_tracking_confidence=0.3
)
#------------------------------------------
self.doMediapipeVisualization = doMediapipeVisualization
self.output = dict()
#------------------------------------------
def get2DOutput(self):
return self.output
def processIncomingHolisticLandmarks(self,face,lhand,rhand,body,currentAspectRatio,trainedAspectRatio):
mnetPose2D = dict()
#------------------------------------------------------------------------------------
processPoseLandmarks(mnetPose2D,MEDIAPIPE_BODY_LANDMARK_NAMES ,body ,currentAspectRatio,trainedAspectRatio,useVisibility=False)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_LHAND_LANDMARK_NAMES,lhand,currentAspectRatio,trainedAspectRatio,useVisibility=False)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_RHAND_LANDMARK_NAMES,rhand,currentAspectRatio,trainedAspectRatio,useVisibility=False)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_FACE_LANDMARK_NAMES ,face ,currentAspectRatio,trainedAspectRatio,useVisibility=False)
#------------------------------------------------------------------------------------
guessLandmarks(mnetPose2D) #Some landmarks ( neck, hip need to be guessed by others )
#------------------------------------------------------------------------------------
return mnetPose2D
def convertImageToMocapNETInput(self,image):
holisticEstimator = self.mp
faceEstimator = self.mpFace
#handEstimator = self.mpHands
if (type(image)==type(None)):
print("Invalid Image given, can't do anything with it")
return dict() , image
#-----------------------------------------
width = image.shape[1]
height = image.shape[0]
if ((width==0) or (height==0)):
print("Cannot work with empty image")
return dict() , image
#-----------------------------------------
currentAspectRatio = width/height
trainedAspectRatio = 1920/1080
#-----------------------------------------
start = time.time()
#--------------------------------------------------------------------------------------------------
# To improve performance, optionally mark the image as not writeable to pass by reference.
image.flags.writeable = False
#==============================================
#================= MEDIAPIPE ==================
#==============================================
results = holisticEstimator.process(image)
resultsF = faceEstimator.process(image) #Extra Face
#resultsH = handEstimator.process(image)
#==============================================
# Draw the hand annotations on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
#--------------------------------------------------------------------------------------------------
end = time.time()
# Time elapsed
seconds = end - start
if (seconds==0.0):
seconds=1.0
# Calculate frames per second
fps = 1 / seconds
#print("Mediapipe Holistic 2D Joint Estimation Framerate : ",round(fps,2)," fps \n", end="", flush=True)
#annotated_image = image.copy()
annotated_image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) #Our annotated image must be BGR to show correctly
#--------------------------------------------------------------------------------------------------
if (self.doMediapipeVisualization):
#Compensate for name mediapipe change..
try:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACEMESH_TESSELATION) #This used to be called FACE_CONNECTIONS
except:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACE_CONNECTIONS) #This used to be called FACE_CONNECTIONS
#--------------------------------------------------------------------------------------------------
mp_drawing.draw_landmarks(annotated_image, results.left_hand_landmarks , mp_holistic.HAND_CONNECTIONS)
mp_drawing.draw_landmarks(annotated_image, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
#--------------------------------------------------------------------------------------------------
#for hand_landmarks in resultsH.multi_hand_landmarks:
# mp_drawing.draw_landmarks(annotated_image, hand_landmarks, mp_hands.HAND_CONNECTIONS)
#--------------------------------------------------------------------------------------------------
# Use mp_holistic.UPPER_BODY_POSE_CONNECTIONS for drawing below when upper_body_only is set to True.
mp_drawing.draw_landmarks(annotated_image, results.pose_landmarks , mp_holistic.POSE_CONNECTIONS)
#--------------------------------------------------------------------------------------------------
mocapNETInput = self.processIncomingHolisticLandmarks(
results.face_landmarks,
results.left_hand_landmarks,
results.right_hand_landmarks,
results.pose_landmarks,
currentAspectRatio,
trainedAspectRatio
)
#EYES
#--------------------------------------------------------------------------------------------
img_h, img_w = image.shape[:2]
if resultsF.multi_face_landmarks:
mesh_points=np.array([np.multiply([p.x, p.y], [img_w, img_h]).astype(int) for p in resultsF.multi_face_landmarks[0].landmark])
(l_cx, l_cy), l_radius = cv2.minEnclosingCircle(mesh_points[LEFT_IRIS])
(r_cx, r_cy), r_radius = cv2.minEnclosingCircle(mesh_points[RIGHT_IRIS])
center_left = np.array([l_cx, l_cy], dtype=np.int32)
center_right = np.array([r_cx, r_cy], dtype=np.int32)
#cv2.circle(annotated_image, center_left, int(l_radius), (255,0,0), -1, cv2.LINE_AA)
#cv2.circle(annotated_image, center_right, int(r_radius), (255,0,0), -1, cv2.LINE_AA)
#--------------------------------------------------------
from holisticPartNames import normalize2DPointWhileAlsoMatchingTrainingAspectRatio
#--------------------------------------------------------
lEyex2D = float(l_cx/img_w) #Dont Flip X
lEyey2D = float(l_cy/img_h)
lEyex2D,lEyey2D = normalize2DPointWhileAlsoMatchingTrainingAspectRatio(lEyex2D,lEyey2D,currentAspectRatio)
lEyeVis = 0.0
if ( (lEyex2D!=0.0) or (lEyey2D!=0.0) ):
lEyeVis = 1.0
mocapNETInput["2dx_head_leye"] = lEyex2D
mocapNETInput["2dy_head_leye"] = lEyey2D
mocapNETInput["visible_head_leye"] = lEyeVis
mocapNETInput["2dx_endsite_eye.l"] = lEyex2D
mocapNETInput["2dy_endsite_eye.l"] = lEyey2D
mocapNETInput["visible_endsite_eye.l"] = lEyeVis
#--------------------------------------------------------
rEyex2D = float(r_cx/img_w) #Dont Flip X
rEyey2D = float(r_cy/img_h)
rEyex2D,rEyey2D = normalize2DPointWhileAlsoMatchingTrainingAspectRatio(rEyex2D,rEyey2D,currentAspectRatio)
rEyeVis = 0.0
if ( (rEyex2D!=0.0) or (rEyey2D!=0.0) ):
rEyeVis = 1.0
mocapNETInput["2dx_head_reye"] = rEyex2D
mocapNETInput["2dy_head_reye"] = rEyey2D
mocapNETInput["visible_head_reye"] = rEyeVis
mocapNETInput["2dx_endsite_eye.r"] = rEyex2D
mocapNETInput["2dy_endsite_eye.r"] = rEyey2D
mocapNETInput["visible_endsite_eye.r"] = rEyeVis
#--------------------------------------------------------
else:
#print("UNABLE TO GET EYES")
pass
#don't populate them at all..
#mocapNETInput["2dx_head_leye"] = 0.0
#mocapNETInput["2dy_head_leye"] = 0.0
#mocapNETInput["visible_head_leye"] = 0.0
#mocapNETInput["2dx_head_reye"] = 0.0
#mocapNETInput["2dy_head_reye"] = 0.0
#mocapNETInput["visible_head_reye"] = 0.0
#--------------------------------------------------------
#--------------------------------------------------------------------------------------------------
#from MocapNETVisualization import drawMocapNETInput
#drawMocapNETInput(mocapNETInput,annotated_image)
#--------------------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------------
self.output = mocapNETInput
#--------------------------------------------------------------------------------------------
return mocapNETInput,annotated_image
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
def streamPosesFromCameraToMocapNET():
engine = "onnx"
headless = False
doProfiling = False
multiThreaded = False
videoFilePath = "webcam"
videoWidth = 1280
videoHeight = 720
saveVideo = False
doBody = True
doFace = False
doREye = False
doMouth = False
doHands = False
aspectCorrection = 1.0
scale = 1.0
addNoise = 0.0
doNNEveryNFrames = 0
frameSkip = 0
doHCDPostProcessing = 1
hcdLearningRate = 0.001
hcdEpochs = 30
hcdIterations = 10
smoothingSampling = 30.0
smoothingCutoff = 5.0
plotBVHChannels = False
liveDemo = False
calibrationFile = ""
bvhAnglesForPlotting = list()
bvhAllAnglesForPlotting = list()
#python3 -m mediapipeHolisticWebcamMocapNET --from damien.avi --face --nobody --plot --save
#python3 -m mediapipeHolisticWebcamMocapNET --from damien.avi --nobody --face --plot --aspectCorrection 0.8 --save
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--headless"):
headless = True
if (sys.argv[i]=="--live"):
liveDemo = True
if (sys.argv[i]=="--mt"):
multiThreaded = True
if (sys.argv[i]=="--calib"):
calibrationFile = sys.argv[i+1]
if (sys.argv[i]=="--frameskip"):
frameSkip = int(sys.argv[i+1])
if (sys.argv[i]=="--nnsubsample"):
doNNEveryNFrames = int(sys.argv[i+1])
if (sys.argv[i]=="--ik"):
hcdLearningRate = float(sys.argv[i+1])
hcdEpochs = int(sys.argv[i+2])
hcdIterations = int(sys.argv[i+3])
if (sys.argv[i]=="--smooth"):
smoothingSampling = float(sys.argv[i+1])
smoothingCutoff = float(sys.argv[i+2])
if (sys.argv[i]=="--noik"):
doHCDPostProcessing = 0
if (sys.argv[i]=="--aspectCorrection"):
aspectCorrection=float(sys.argv[i+1])
if (sys.argv[i]=="--noise"):
addNoise=float(sys.argv[i+1])
if (sys.argv[i]=="--size"):
videoWidth = int(sys.argv[i+1])
videoHeight = int(sys.argv[i+2])
if (sys.argv[i]=="--scale"):
scale=float(sys.argv[i+1])
if (sys.argv[i]=="--plot"):
plotBVHChannels=True
if (sys.argv[i]=="--all"):
doBody=True
doREye=True
doMouth=True
doHands=True
if (sys.argv[i]=="--nobody"):
doBody=False
if (sys.argv[i]=="--face"):
doFace=True
if (sys.argv[i]=="--eyes") or (sys.argv[i]=="--reye"):
doREye=True
if (sys.argv[i]=="--mouth"):
doMouth=True
if (sys.argv[i]=="--hands"):
doHands=True
if (sys.argv[i]=="--save"):
saveVideo=True
if (sys.argv[i]=="--engine"):
engine=sys.argv[i+1]
print("Selecting engine : ",engine)
if (sys.argv[i]=="--from"):
videoFilePath=sys.argv[i+1]
if (sys.argv[i]=="--profile"):
doProfiling=True
if "/dev/video" in videoFilePath:
smoothingSampling = 20.0
smoothingCutoff = 8.0
print("Special Low Smoothing setup")
from MocapNETVisualization import drawMocapNETOutput,drawDescriptor,drawNSRM,drawMAE2DError,drawMocapNETAllPlots
#Select a MocapNET class from tensorflow/tensorrt/onnx/tf-lite engines
from MocapNET import easyMocapNETConstructor
mnet = easyMocapNETConstructor(
engine,
doProfiling = doProfiling,
multiThreaded = multiThreaded,
doHCDPostProcessing = doHCDPostProcessing,
hcdLearningRate = hcdLearningRate,
hcdEpochs = hcdEpochs,
hcdIterations = hcdIterations,
smoothingSampling = smoothingSampling,
smoothingCutoff = smoothingCutoff,
bvhScale = scale,
doBody = doBody,
doFace = doFace,
doREye = doREye,
doMouth = doMouth,
doHands = doHands,
addNoise = addNoise
)
if (calibrationFile!=""):
print("Enforcing Calibration file : ",calibrationFile)
mnet.bvh.configureRendererFromFile(calibrationFile)
#To scale the intrinsic camera parameters (focal length and principal point) when changing the resolution of the image from 640x480 to 1280x720, you can use the following formula:
#New Focal Length (fx_new, fy_new) = (New Image Width / Original Image Width) * Original Focal Length
#New Principal Point (cx_new, cy_new) = (New Image Width / Original Image Width) * Original Principal Point
mnet.test()
mnet.recordBVH(not liveDemo)
#Body only
mp = None
if (doFace or doMouth or doMouth or doHands):
mp = MediaPipeHolistic(doMediapipeVisualization = False)
else:
mp = MediaPipePose(doMediapipeVisualization = False)
# For webcam input:
frameNumber = 0
#------------------------------------------
if (videoFilePath=="esp"):
from espStream import ESP32CamStreamer
cap = ESP32CamStreamer()
elif (videoFilePath=="webcam"):
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
elif (videoFilePath=="/dev/video0"):
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
elif (videoFilePath=="/dev/video1"):
cap = cv2.VideoCapture(1)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
elif (videoFilePath=="/dev/video2"):
cap = cv2.VideoCapture(2)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
else:
from tools import checkIfPathIsDirectory
if (checkIfPathIsDirectory(videoFilePath) and (not "/dev/" in videoFilePath) ):
from folderStream import FolderStreamer
cap = FolderStreamer(path=videoFilePath,width=videoWidth,height=videoHeight)
mnet.bvh.configureRendererFromFile("%s/color.calib"%videoFilePath)
else:
cap = cv2.VideoCapture(videoFilePath)
#-----------------------------------------
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
print("\n\n\n\nStarting MocapNET using MediaPipe 2D Joint Estimator Input")
print("Please wait until input processing finishes!")
maxBrokenFrames = 100
brokenFrames = 0
while cap.isOpened():
success, image = cap.read()
#Frame skipping..!
if (frameSkip>0):
for i in range(0,frameSkip):
frameNumber = frameNumber + 1
success, image = cap.read()
plotImage = image
if not success:
eprint("Ignoring empty camera frame : ",brokenFrames,"/",maxBrokenFrames)
brokenFrames = brokenFrames + 1
if (brokenFrames>maxBrokenFrames):
break
else:
continue
# If loading a video, use 'break' instead of 'continue'.
#continue
if ( aspectCorrection!=1.0 ):
width = int(image.shape[1]*aspectCorrection)
height = int(image.shape[0])
image = cv2.resize(image, (width,height))
#--------------------------------------------------------------------------------------------------------------
start = time.time() # Time elapsed
mocapNETInput,annotated_image = mp.convertImageToMocapNETInput(image)
end = time.time() # Time elapsed
mnet.hz_2DEst = secondsToHz(end - start)
mnet.history_hz_2DEst.append(mnet.hz_2DEst)
if (len(mnet.history_hz_2DEst)>mnet.perfHistorySize):
mnet.history_hz_2DEst.pop(0) #Keep mnet history on limits
#--------------------------------------------------------------------------------------------------------------
doNN = 1
if (doNNEveryNFrames>0):
doNN = (frameNumber%doNNEveryNFrames)==0
#--------------------------------------------------------------------------------------------------------------
mocapNET3DOutput = mnet.predict3DJoints(mocapNETInput,runNN=doNN,runHCD=True)
mocapNETBVHOutput = mnet.outputBVH
bvhAnglesForPlotting.append(mocapNETBVHOutput)
bvhAllAnglesForPlotting.append(mocapNETBVHOutput)
if (len(bvhAnglesForPlotting)>100):
bvhAnglesForPlotting.pop(0)
#--------------------------------------------------------------------------------------------------------------
from MocapNETVisualization import visualizeMocapNETEnsemble
image,plotImage = visualizeMocapNETEnsemble(mnet,annotated_image,plotBVHChannels=plotBVHChannels,bvhAnglesForPlotting=bvhAnglesForPlotting)
#--------------------------------------------------------------------------------------------------------------
frameNumber = frameNumber + 1
mnet.printStatus()
if (saveVideo):
cv2.imwrite('colorFrame_0_%05u.jpg'%(frameNumber), annotated_image)
if (plotBVHChannels):
cv2.imwrite('plotFrame_0_%05u.jpg'%(frameNumber), plotImage)
if not headless:
cv2.imshow('MocapNET 4 using MediaPipe Holistic 2D Joints', annotated_image)
if (plotBVHChannels):
cv2.imshow('MocapNET 4 using MediaPipe Holistic Motion History',plotImage)
if cv2.waitKey(1) & 0xFF == 27:
break
if (saveVideo): # 1280x720 by default
os.system("ffmpeg -framerate 30 -i colorFrame_0_%%05d.jpg -s %ux%u -y -r 30 -pix_fmt yuv420p -threads 8 livelastRun3DHiRes.mp4 && rm colorFrame_0_*.jpg " % (videoWidth,videoHeight)) #
if (plotBVHChannels):
os.system("ffmpeg -framerate 30 -i plotFrame_0_%05d.jpg -s 1200x720 -y -r 30 -pix_fmt yuv420p -threads 8 livelastPlot3DHiRes.mp4 && rm plotFrame_0_*.jpg")
del mnet #So that the out.bvh file gets created..
if (not liveDemo):
os.system("rm 2d_out.csv 3d_out.csv bvh_out.csv map_out.csv")
os.system("./GroundTruthDumper --from out.bvh --setPositionRotation -2.6 0 2000 0 0 0 --csv ./ out.csv 2d+3d+bvh ") # Remove noise offsetPositionRotation
cap.release()
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
if __name__ == '__main__':
streamPosesFromCameraToMocapNET()
+255
View File
@@ -0,0 +1,255 @@
#!/usr/bin/python3
import sys
import numpy as np
import matplotlib.pyplot as plt
from readCSV import readGroundTruthFile,splitNumpyArray
from readCSV import parseConfiguration
from tools import getFileFromPath
def splitNumpyArray(model,column):
numberOfSamples=len(model)
npOutput = np.empty([numberOfSamples],dtype=float,order='C')
for num in range(0,numberOfSamples):
npOutput[num]=float(model[num,column]);
return npOutput;
def draw2D(data,width=1920,height=1080):
#----------------------------------------------------
from MocapNETVisualization import drawMocapNETInput
#----------------------------------------------------
import cv2
import numpy as np
#----------------------------------------------------
for sampleID in range(0,len(data['body'])):
image = np.zeros([height,width,3],dtype=np.uint8)
joints2D = dict()
for labelID in range(0,len(data['label'])):
label = data['label'][labelID].lower()
value = data['body'][sampleID][labelID]
#----------------------------------------------------
if "2d_x" in label:
value = value * width
if "2d_y" in label:
value = value * height
#----------------------------------------------------
joints2D[label] = value
drawMocapNETInput(joints2D,image,flipX=False)
font = cv2.FONT_HERSHEY_SIMPLEX
org = (30,60)
fontScale = 1.5
color = (255,255,255)
thickness = 2
message = 'Sample Number : %u / %u ' % (sampleID,len(data['body']))
image = cv2.putText(image, message , org, font, fontScale, color, thickness, cv2.LINE_AA)
cv2.imshow('2D',image)
#print("Sample ",sampleID," -> ",joints2D)
if cv2.waitKey(1000) & 0xFF == 27:
sys.exit(0)
#----------------------------------------------------
def plotDistribution(column,filename,values):
print("Plotting ",filename)
#print(values.shape)
plt.clf()
plt.hist(values,bins=100)
median = np.median(values)
mean = np.mean(values)
std = np.std(values)
var = np.var(values)
minimum = np.min(values)
maximum = np.max(values)
title_string="Histogram of Output distribution for %s \nMedian=%0.2f,Mean=%0.2f,Std=%0.2f,Var=%0.2f,Samples=%u,Min=%0.2f,Max=%0.2f" % (filename,median,mean,std,var,len(values),minimum,maximum)
plt.title(title_string)
print("Stats,%s,%0.2f,%0.2f,%0.2f,%0.2f,%u,%0.2f,%0.2f" % (filename,median,mean,std,var,len(values),minimum,maximum))
plt.savefig("%03u_%s.png" % (column,filename))
def calculate_relative_magnitudes(edm, n):
row_magnitudes = []
column_magnitudes = []
for i in range(n):
row_magnitude = sum(edm[i*n:(i+1)*n])
row_magnitudes.append(row_magnitude)
column_magnitude = sum(edm[i::n])
column_magnitudes.append(column_magnitude)
central_element = edm[n*n // 2]
row_magnitudes_sum = sum(row_magnitudes) - central_element
column_magnitudes_sum = sum(column_magnitudes) - central_element
max_magnitude = max(row_magnitudes_sum, column_magnitudes_sum)
relative_row_magnitudes = [m / max_magnitude for m in row_magnitudes]
relative_column_magnitudes = [m / max_magnitude for m in column_magnitudes]
return relative_row_magnitudes, relative_column_magnitudes
def plotCovariance(X):
covariance = np.cov(X.T)
# Plot the covariance matrix
plt.imshow(covariance, cmap='coolwarm', interpolation='nearest')
plt.colorbar()
plt.title('Covariance Matrix')
plt.savefig("covariance.png")
#plt.show()
def plotTestOutputDistribution(csvfiletoplotIn,csvfiletoplotOut,mem):
useRadians=0
useHalfFloats=0
dataFile = "body"
#This will be get populated using the --config argument
configuration = []
configurationPath=""
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--config"):
configurationPath=sys.argv[i+1]
configuration = parseConfiguration(configurationPath)
#setupDNNModelsUsingJSONConfiguration(configuration)
if (sys.argv[i]=="--mem"):
print("\nMemory usage ",sys.argv[i+1]);
mem=float(sys.argv[i+1])
#-----------------------------------------------
# New 4way split
#-----------------------------------------------
if (sys.argv[i]=="--dataset"):
print("\nOverriding dataset ",dataFile," and using ",sys.argv[i+1]);
dataFile=sys.argv[i+1]
if (sys.argv[i]=="--all"):
#Don't mix this --all with the step2_OrientatonClassifier.py --all
hierarchyPartName=sys.argv[i+1]
dataFile="%s_all" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--back"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_back" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--front"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_front" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--left"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_left" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--right"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_right" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
#-----------------------------------------------
#Resolve PCA name.. :(
x = configuration['doPCA'].split("$",1)
if (len(x)>0):
#If there is a $ character this is our place holder to autocomplete our dataFile
print("PCA filename is resolved from ",configuration['doPCA'])
print(" to ")
configuration['doPCA']=x[0]+dataFile+".pca"
print(configuration['doPCA'])
numberOfChannelsPerNSDMElement=2
if (configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
groundTruth = readGroundTruthFile(
configuration,
csvfiletoplotIn,
csvfiletoplotIn,
csvfiletoplotOut,
mem,
numberOfChannelsPerNSDMElement,
useRadians,
useHalfFloats
)
#----------------------------------------------------------
data = np.empty(len(groundTruth['out']))
for z in range(0,len(groundTruth['labelOut'])):
data=splitNumpyArray(groundTruth['out'],z)
if (z<3):
np.multiply(data,10)
plotDistribution(z,groundTruth['labelOut'][z],data)
#----------------------------------------------------------
data = np.empty(len(groundTruth['in']))
for z in range(0,len(groundTruth['labelIn'])):
data=splitNumpyArray(groundTruth['in'],z)
plotDistribution(z,groundTruth['labelIn'][z],data)
#----------------------------------------------------------
#Test Plots
#./GroundTruthDumper --from dataset/yawTest.bvh --csv ./ yaw.csv 2d --svg .
# python3 csvNET.py --from 2d_yaw.csv --save --keep --hands --white
# convert colorFrame_0_00000.jpg -crop 234x500+0+90 nsrm_00000.jpg
#./GroundTruthDumper --from dataset/pitchTest.bvh --csv ./ pitch.csv 2d --svg .
# python3 csvNET.py --from 2d_pitch.csv --save --keep --hands --white
#./GroundTruthDumper --from dataset/rollTest.bvh --csv ./ roll.csv 2d --svg .
# python3 csvNET.py --from 2d_roll.csv --save --keep --hands --white
def doRun():
label = "nolabel"
if (len(sys.argv)==3) :
#==========================================
if (sys.argv[1]=="--2d"):
print(sys.argv[0]," --2d your.csv")
labelSplit = sys.argv[2].split('.',1)
label = labelSplit[0]
from readCSV import readCSVFile
data = readCSVFile(sys.argv[2],1.0,0)
draw2D(data)
sys.exit(0)
#==========================================
elif (sys.argv[1]=="--simple"):
print(sys.argv[0]," --simple your.csv")
labelSplit = sys.argv[2].split('.',1)
label = labelSplit[0]
from readCSV import readCSVFile
data = readCSVFile(sys.argv[2],1.0,0)
plotCovariance(data['body'])
#USE : python3 plotCSV.py --simple loss.csv | grep Stats > lossStats.csv to create stats csv file!
print("Stats,Output,Median,Mean,Std,Var,Samples,Min,Max")
for z in range(0,len(data['label'])):
print("Plotting Column ",data['label'][z])
specificData=splitNumpyArray(data['body'],z)
filename = getFileFromPath('%s-%s' % (label,data['label'][z]))
plotDistribution(z,filename,specificData)
sys.exit(0)
#==========================================
if (len(sys.argv)<5) :
print("plotCSV.py: Please rerun using a parameter of the CSV file you want to run..")
print("e.g.")
print(sys.argv[0]," --config dataset/lhand_configuration.json dataset/generated/2d_lhand_all.csv dataset/generated/bvh_lhand_all.csv --all lhand")
print(" or ")
print(sys.argv[0]," --config dataset/upperbody_configuration.json dataset/generated/2d_upperbody_all.csv dataset/generated/bvh_upperbody_all.csv --all upperbody ")
print(" or ")
print(sys.argv[0]," --config dataset/face_configuration.json dataset/generated/2d_face_all.csv dataset/generated/bvh_face_all.csv --all face")
print(" or ")
print(sys.argv[0]," --simple your.csv")
sys.exit(0)
plotTestOutputDistribution(sys.argv[3],sys.argv[4],1.0)
if __name__== "__main__":
doRun()
@@ -0,0 +1,352 @@
import matplotlib as mp
import matplotlib.pyplot as plt
import numpy as np
import os
import sys
import time
import array
import csv
# Fixing random state for reproducibility
np.random.seed(19680801)
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
"""
Bytes to KB/MB/GB/TB converter
"""
def convert_bytes(num):
"""
this function will convert bytes to MB.... GB... etc
"""
step_unit = 1000.0 #1024 bad the size
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
if num < step_unit:
return "%3.1f %s" % (num, x)
num /= step_unit
"""
Check if a file exists
"""
def checkIfFileExists(filename):
return os.path.isfile(filename)
"""
Count the number of lines by parsing the file inside python
"""
def getNumberOfLines(filename):
#import socket
#print("Hostname is ",socket.gethostname())
#if (socket.gethostname()=="ammar-kriti"):
# print(bcolors.FAIL,"RETURNING FIXED NUMBER OF LINES FOR SPEED IN MY SLOW PC",bcolors.ENDC)
# return 3858095
print("Counting number of lines in file ",filename)
with open(filename) as f:
return sum(1 for line in f)
"""
typically we work with data[NUMBER_OF_SAMPLES,NUMBER_OF_COLUMNS]
calling splitNumpyArray(data,4,4,0) means get back columns 4,5,6,7 so it will return a data[NUMBER_OF_SAMPLES,4]
"""
def splitNumpyArray(data,column,columnsToTake,useHalfFloats=0):
#-------------------------------------
dtypeSelected=np.dtype(np.float32)
if (useHalfFloats):
dtypeSelected=np.dtype(np.float16)
#-------------------------------------
numberOfSamples=len(data)
npOutput = np.full([numberOfSamples,columnsToTake],fill_value=0,dtype=dtypeSelected,order='C')
for outCol in range(0,columnsToTake):
for num in range(0,numberOfSamples):
npOutput[num,outCol]=float(data[num,column+outCol])
#-------------------------------------
return npOutput;
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
def readCSVFile(filename,memPercentage,useHalfFloats=0):
print("CSV file :",filename,"..\n")
if (not checkIfFileExists(filename)):
print( bcolors.FAIL + "Input file "+filename+" does not exist, cannot read ground truth.." + bcolors.ENDC)
print("Current Directory was "+os.getcwd())
sys.exit(1)
start = time.time()
dtypeSelected=np.dtype(np.float32)
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
if (useHalfFloats):
dtypeSelected=np.dtype(np.float16)
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
progress=0.0
#useSquared=1
sampleNumber=0
receivedHeader=0
inputNumberOfColumns=0
outputNumberOfColumns=0
inputLabels=list()
#-------------------------------------------------------------------------------------------------
numberOfSamplesInput=getNumberOfLines(filename)-2
print(" Input file has ",numberOfSamplesInput," training samples\n")
#-------------------------------------------------------------------------------------------------
numberOfSamples = numberOfSamplesInput
numberOfSamplesLimit=int(numberOfSamples*memPercentage)
#-------------------------------------------------------------------------------------------------
if (memPercentage==0.0):
print("readGroundTruthFile was asked to occupy 0 memory so this probably means we just want one record")
numberOfSamplesLimit=2
if (memPercentage>1.0):
print("Memory Limit will be interpreted as a raw value..")
numberOfSamplesLimit=int(memPercentage)
#-------------------------------------------------------------------------------------------------
thisInput = array.array('f')
#---------------------------------
fi = open(filename, "r")
readerIn = csv.reader( fi , delimiter =',', skipinitialspace=True)
for rowIn in readerIn:
#------------------------------------------------------
if (not receivedHeader): #use header to get labels
#------------------------------------------------------
inputNumberOfColumns=len(rowIn)
inputLabels = list(rowIn[i] for i in range(0,inputNumberOfColumns) )
print("Number of Input elements : ",len(inputLabels))
#------------------------------------------------------
if (memPercentage==0):
print("Will only return labels\n")
return {'labels':inputLabels};
#i=0
#print("class Input(Enum):")
#for label in inputLabels:
# print(" ",label," = ",i," #",int(i/3))
# print(" ",label,"=",int(i/3))
# i=i+1
#---------------------------------
# Allocate Lists
#---------------------------------
for i in range(inputNumberOfColumns):
thisInput.append(0.0)
#---------------------------------
#---------------------------------
# Allocate Numpy Arrays
#---------------------------------
inputSize=0
startCompressed=0
inputSize=inputNumberOfColumns
startCompressed=inputNumberOfColumns
npInputBytesize=0+numberOfSamplesLimit * inputSize * dtypeSelectedByteSize
print(" Input file on disk has a shape of [",numberOfSamples,",",inputSize,"]")
print(" Input we will read has a shape of [",numberOfSamplesLimit,",",inputSize,"]")
print(" Input will occupy ",convert_bytes(npInputBytesize)," of RAM\n")
npInput = np.full([numberOfSamplesLimit,inputSize],fill_value=0,dtype=dtypeSelected,order='C')
#----------------------------------------------------------------------------------------------------------
receivedHeader=1
#sys.exit(0)
else:
#-------------------------------------------
# First convert our string INPUT to floats
#-------------------------------------------
for i in range(inputNumberOfColumns):
try:
thisInput[i]=float(rowIn[i])
except ValueError:
thisInput[i]=0.0
#-------------------------------------------
for num in range(0,inputNumberOfColumns):
npInput[sampleNumber,num]=float(thisInput[num]);
#-------------------------------------------
sampleNumber=sampleNumber+1
if (numberOfSamples>0):
progress=sampleNumber/numberOfSamplesLimit
if (sampleNumber%1000==0) :
progressString = "%0.2f"%float(100*progress)
print("\rReading from disk (",sampleNumber,") - ",progressString," % \r", end="", flush=True)
if (numberOfSamplesLimit<=sampleNumber):
print("\rStopping reading file to obey memory limit given by parameter --mem ",memPercentage,"\n")
break
#-------------------------------------------
fi.close()
del readerIn
print("\n read, Samples: ",sampleNumber,", was expecting ",numberOfSamples," samples\n")
print(npInput.shape)
totalNumberOfBytes=npInput.nbytes;
totalNumberOfGigaBytes=totalNumberOfBytes/1073741824;
print("GPU Size Occupied by data = ",totalNumberOfGigaBytes," GB \n")
end = time.time()
print("Time elapsed : ",(end-start)/60," mins")
#---------------------------------------------------------------------
return {'label':inputLabels, 'body':npInput };
def resolve(theList,theName):
result = 0
for item in theList:
if (item==theName):
return result,True
result = result + 1
return result,False
if __name__== "__main__":
filename="report.csv"
output="out.png"
jointName=" HCD FineTune "
#----------------------------------------------
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--from"):
filename=sys.argv[i+1]
data = readCSVFile(filename,1.0)
#----------------------------------------------
if (filename=="report.csv"):
data = readCSVFile(filename,1.0)
#----------------------------------------------
xCol=1
yCol=6
zCol=8
target1Col=11
target2Col=12
xs = None
ys = None
zs = None
vs = None
v2s = None
#https://matplotlib.org/stable/gallery/color/colormap_reference.html
colorMapString = "Greens_r"
#supported values are 'Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Greens', 'Greens_r', 'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu', 'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r', 'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn', 'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r', 'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r', 'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r', 'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis', 'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'gist_earth', 'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_heat', 'gist_heat_r', 'gist_ncar', 'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg', 'gist_yarg_r', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r', 'hot', 'hot_r', 'hsv', 'hsv_r', 'inferno', 'inferno_r', 'jet', 'jet_r', 'magma', 'magma_r', 'nipy_spectral', 'nipy_spectral_r', 'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow', 'rainbow_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer', 'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c', 'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', 'twilight_shifted_r', 'viridis', 'viridis_r', 'winter', 'winter_r'
xOk = False
yOk = False
zOk = False
target1Ok = False
target2Ok = False
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--colormap"):
colorMapString=sys.argv[i+1]
if (sys.argv[i]=="--to"):
output=sys.argv[i+1]
if (sys.argv[i]=="--title"):
jointName=sys.argv[i+1]
if (sys.argv[i]=="--label"):
jointName=sys.argv[i+1]
if (sys.argv[i]=="-x"):
xCol,xOk = resolve(data["label"],sys.argv[i+1])
if (sys.argv[i]=="-y"):
yCol,yOk = resolve(data["label"],sys.argv[i+1])
if (sys.argv[i]=="-z"):
zCol,zOk = resolve(data["label"],sys.argv[i+1])
if (sys.argv[i]=="-v2"):
target2Col,target2Ok = resolve(data["label"],sys.argv[i+1])
if (sys.argv[i]=="-v1"):
target1Col,target1Ok = resolve(data["label"],sys.argv[i+1])
#-------------------------
xLabel=data["label"][xCol]
yLabel=data["label"][yCol]
zLabel=data["label"][zCol]
#-------------------------
viewAzimuth=45
viewElevation=45
transparency=0.6
scale = 0.12 #Smaller is smaller :P
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
if xOk:
xs = splitNumpyArray(data["body"],xCol,1) # 1 = learning rate
else:
print("Error Resolving X")
if yOk:
ys = splitNumpyArray(data["body"],yCol,1) # 6 = iteration
else:
print("Error Resolving Y")
if zOk:
zs = splitNumpyArray(data["body"],zCol,1) # 8 = langevin
else:
print("Error Resolving Z")
if target1Ok:
vs = splitNumpyArray(data["body"],target1Col,1) # 10 = mae
else:
print("Error Resolving Color (v1)")
if target2Ok:
v2s = splitNumpyArray(data["body"],target2Col,1) # 10 = mae
v2sMean = np.mean(v2s)
v2s = v2s * (100.0/v2sMean)
else:
print("Error Resolving Size (v2)")
ax.view_init(viewAzimuth,viewElevation)
#cm = plt.cm.get_cmap('RdYlBu')
#cm = plt.cm.get_cmap('hot')
cm = mp.colormaps.get_cmap(colorMapString)
if target1Ok and target2Ok:
sc = ax.scatter(xs, ys, zs, c=vs, s=v2s , cmap=cm, alpha=transparency)
else:
sc = ax.scatter(xs, ys, zs, alpha=transparency)
plt.colorbar(sc)
ax.set_title(jointName) # Title of the plot
ax.set_xlabel(xLabel)
ax.set_ylabel(yLabel)
ax.set_zlabel(zLabel)
fig.savefig(output)
plt.show()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,287 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import sys
import numpy as np
from readCSV import parseConfiguration,splitNumpyArray,readGroundTruthFile
from DNNModel import setupDNNModelsUsingJSONConfiguration
OKGREEN = '\033[92m'
ENDC = '\033[0m'
FAIL = '\033[91m'
"""
Retreive the available system RAM
"""
def getRAMInformation():
"""
Get node total memory and memory usage
"""
with open('/proc/meminfo', 'r') as mem:
ret = {}
tmp = 0
for i in mem:
sline = i.split()
if str(sline[0]) == 'MemTotal:':
ret['total'] = int(sline[1])
elif str(sline[0]) in ('MemFree:', 'Buffers:', 'Cached:'):
tmp += int(sline[1])
ret['free'] = int(tmp)
ret['used'] = int(ret['total']) - int(ret['free'])
return ret
if __name__ == '__main__':
print("""
██████╗ ███████╗ ██████╗ ██████╗ ███╗ ███╗██████╗ ██████╗ ███████╗███████╗
██╔══██╗██╔════╝██╔════╝██╔═══██╗████╗ ████║██╔══██╗██╔═══██╗██╔════╝██╔════╝
██║ ██║█████╗ ██║ ██║ ██║██╔████╔██║██████╔╝██║ ██║███████╗█████╗
██║ ██║██╔══╝ ██║ ██║ ██║██║╚██╔╝██║██╔═══╝ ██║ ██║╚════██║██╔══╝
██████╔╝███████╗╚██████╗╚██████╔╝██║ ╚═╝ ██║██║ ╚██████╔╝███████║███████╗
╚═════╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚══════╝╚══════╝""")
configuration = []
configurationPath=""
#Use the whole training Dataset by default
memPercentage=1.0
#networkCompression=1.0
useHalfFloats = 0
useRadians = 0
#I/O settings
outputDirectoryForTrainedModels = "step0FrontBody"
dataFile = "body"
testFile = "body_test"
hierarchyPartName = "body"
outputMode = "bvh"
# Sample call with some example parameters :
# python3 principleComponentAnalysisTool.py --config dataset/body_configuration.json --mem 1000 --highlight 3 --all body --show --mode 3
highlightChannel = -1 #<- default shows PC4
batch = 0
mode = 1
dimensions = 0
decompositionType = "pca"
viewA = 45
viewB = 45
visualize = 0
dumpRules = 1
addScreePlot = 0
label = "not defined"
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--config"):
configurationPath=sys.argv[i+1]
configuration = parseConfiguration(configurationPath)
setupDNNModelsUsingJSONConfiguration(configuration)
decompositionType = configuration['decompositionType']
dimensions = int(configuration['PCADimensionsKept'])
if (configuration['precision']=="fp16"):
useHalfFloats=1
configuration['rememberWeights']=0
setBackendToHalfFloats()
elif (configuration['precision']!="fp32"):
print(bcolors.WARNING,"Cannot use ",configuration['precision']," precision\n",bcolors.ENDC)
if (sys.argv[i]=="--mem"):
print("\nMemory usage ",sys.argv[i+1]);
memPercentage=float(sys.argv[i+1])
#-----------------------------------------------
# New 4way split
#-----------------------------------------------
if (sys.argv[i]=="--dataset"):
print("\nOverriding dataset ",dataFile," and using ",sys.argv[i+1]);
dataFile=sys.argv[i+1]
if (sys.argv[i]=="--all"):
#Don't mix this --all with the step2_OrientatonClassifier.py --all
hierarchyPartName=sys.argv[i+1]
dataFile="%s_all" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--back"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_back" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--front"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_front" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--left"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_left" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--right"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_right" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
#-----------------------------------------------
if (sys.argv[i]=="--type"):
print("\nSet Mode to ",sys.argv[i+1]);
decompositionType=sys.argv[i+1]
configuration['decompositionType'] = decompositionType
if (sys.argv[i]=="--dims"):
print("\nSet Dimensions to ",sys.argv[i+1]);
dimensions=int(sys.argv[i+1])
configuration['PCADimensionsKept']=str(dimensions)
if (sys.argv[i]=="--mode"):
print("\nSet Mode to ",sys.argv[i+1]);
mode=int(sys.argv[i+1])
if (sys.argv[i]=="--highlight"):
print("\nSet Highlight to ",sys.argv[i+1]);
highlightChannel=int(sys.argv[i+1])
if (sys.argv[i]=="--view"):
print("\nSet View to ",sys.argv[i+1],sys.argv[i+2]);
viewA=int(sys.argv[i+1])
viewB=int(sys.argv[i+2])
if (sys.argv[i]=="--batch"):
batch=1
visualize = 1
if (sys.argv[i]=="--nosave"):
dumpRules=0
if (sys.argv[i]=="--show"):
visualize=1
if (sys.argv[i]=="--noscree"):
addScreePlot=0
if (decompositionType==""):
print(OKGREEN,"Not doing everything because no decomposition type requested",ENDC)
sys.exit(0)
#The default compatibility setting is the BMVC2019 2channel NSDM, however nowadays we use NSRM
numberOfChannelsPerNSDMElement=2
if (configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
#Hardcoded path for dataset if using CSV file
#datasetDirectory="/home/ammar/Documents/Programming/DNNTracker/DNNTracker/dataset"
#datasetDirectory="../../DNNTracker/dataset"
datasetDirectory="dataset/generated/"
RAMBefore = getRAMInformation()
print("Initial | free RAM ",RAMBefore['free']," KB");
groundTruthTrain = readGroundTruthFile(
configuration,
"%s Train data for decomposition" % (decompositionType),
"%s/2d_%s.csv" % (datasetDirectory,dataFile),
"%s/%s_%s.csv" % (datasetDirectory,outputMode,dataFile), #outputMode is either bvh or 3d
memPercentage,
numberOfChannelsPerNSDMElement,
useRadians,
useHalfFloats,
completelyDisablePCACode = 1 #If we do PCA while trying to do PCA it will be madness
)
RAMAfter = getRAMInformation()
print("After reading the dataset | free RAM ",RAMAfter['free']," KB");
#----------------------------------------------------------------------------------------------------------
startOfNSxMColumn = len(groundTruthTrain['labelInNoNSDM'])
numberOfNSxMColumns = len(groundTruthTrain['labelIn'])-startOfNSxMColumn
print("2D data are 0 to ",startOfNSxMColumn)
print("NSRM data are ",startOfNSxMColumn , " to ",numberOfNSxMColumns)
if (mode==1):
NSxM = groundTruthTrain['in']
label = "on 2D+NSRM data"
elif (mode==2):
NSxM = splitNumpyArray(groundTruthTrain['in'],startOfNSxMColumn,numberOfNSxMColumns,useHalfFloats)
label = "on NSRM data"
elif (mode==3):
NSxM = splitNumpyArray(groundTruthTrain['in'],0,startOfNSxMColumn,useHalfFloats)
label = "on 2D data"
elif (mode==4):
NSxM = groundTruthTrain['out']
label = "on all BVH Data"
elif (mode==5):
onlyRotationalBVHOutputs = len(groundTruthTrain['labelOut']) - 3
print("Will take output from 3-",onlyRotationalBVHOutputs,"/",len(groundTruthTrain['labelOut']))
NSxM = splitNumpyArray(groundTruthTrain['out'],3,onlyRotationalBVHOutputs,useHalfFloats)
label = "on rot. BVH Data"
elif (mode==6):
onlyLimbRotationalBVHOutputs = len(groundTruthTrain['labelOut']) - 6
print("Will take output from 6-",onlyLimbRotationalBVHOutputs,"/",len(groundTruthTrain['labelOut']))
NSxM = splitNumpyArray(groundTruthTrain['out'],6,onlyLimbRotationalBVHOutputs,useHalfFloats)
label = "on limb rot. BVH Data"
#----------------------------------------------------------------------------------------------------------
RAMSplit = getRAMInformation()
print("After splitting the dataset | free RAM ",RAMSplit['free']," KB");
del groundTruthTrain['in']
if (not visualize):
del groundTruthTrain['out']
RAMFree = getRAMInformation()
print("After freeing original input | free RAM ",RAMFree['free']," KB");
print(OKGREEN,"Will perform dimensionality reduction on ",label,ENDC)
if (decompositionType=="pca"):
print("Attempting PCA using my code with ",dimensions," elements")
print("Our Input Shape is ",NSxM.shape[0],"x",NSxM.shape[1])
from principleComponentAnalysis import PCA
ourDecomposition = PCA(inputData=NSxM,decompositionType=decompositionType)
for i in range(0,len(ourDecomposition.cumulative)):
thisValue = 0.0
try:
thisValue = ourDecomposition.cumulative[i].real
except:
thisValue = ourDecomposition.cumulative[i]
#---------------------------------------------------
if (thisValue>0.99):
print(OKGREEN,"Useless? PCA Dim #",i," - ",thisValue*100,"%",ENDC)
else:
print("PCA Dim #",i," - Explanation of data until here ",thisValue*100,"%")
if (dimensions==i):
print(FAIL," ------------- OUR LIMIT IS SET HERE (",dimensions,") ------------- ",ENDC)
else:
from dataDecomposition import Decomposition
print("Attempting Generic Decomposition ",decompositionType," with ",dimensions," elements")
print("Our Input Shape is ",NSxM.shape[0],"x",NSxM.shape[1])
ourDecomposition = Decomposition(inputData=NSxM,decompositionType=decompositionType,selectedPCADimensions=dimensions)
if (dumpRules):
print("Dumping rules to json file..")
x = configuration['doPCA'].split("$")
if (len(x)>0):
#If there is a $ character this is our place holder to autocomplete our dataFile
print("We resolve ",configuration['doPCA'])
print(" to ")
configuration['doPCA']=x[0]+dataFile+".pca"
print(configuration['doPCA'])
ourDecomposition.save(configuration['doPCA'])
#Number of PCA components to plot on second plot
#-----------------------------------------------------------------------------
onlyScreePlotNDimensions=8
if (batch==1) or (visualize):
if (highlightChannel<0):
colors = list()
colorLabel = "highlighting PC-4"
else:
colorLabel="highlighting "+ groundTruthTrain['labelOut'][highlightChannel]
colors = groundTruthTrain['out'][:,highlightChannel]
#-----------------------------------------------------------------------------
filename = ""
if (batch==1):
filename = "%s_%s_%s_%u_v%u%u.png"%(decompositionType,label,colorLabel,int(memPercentage),viewA,viewB)
filename = filename.replace(' ','_')
#-----------------------------------------------------------------------------
if (visualize):
ourDecomposition.visualize(NSxM,saveToFile=filename,onlyScreePlotNDimensions=onlyScreePlotNDimensions,label=label,colors=colors,colorLabel=colorLabel,viewAzimuth=viewA,viewElevation=viewB,showScree=addScreePlot)
print(OKGREEN,"Finished with ",decompositionType," code!",ENDC)
File diff suppressed because it is too large Load Diff
+124
View File
@@ -0,0 +1,124 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$DIR"
#Simple dependency checker that will apt-get stuff if something is missing
# sudo apt-get install python3-venv python3-pip
SYSTEM_DEPENDENCIES="build-essential python3-venv python3-pip freeglut3-dev libglew-dev protobuf-compiler libprotobuf-dev libavdevice-dev"
for REQUIRED_PKG in $SYSTEM_DEPENDENCIES
do
PKG_OK=$(dpkg-query -W --showformat='${Status}\n' $REQUIRED_PKG|grep "install ok installed")
echo "Checking for $REQUIRED_PKG: $PKG_OK"
if [ "" = "$PKG_OK" ]; then
echo "No $REQUIRED_PKG. Setting up $REQUIRED_PKG."
#If this is uncommented then only packages that are missing will get prompted..
#sudo apt-get --yes install $REQUIRED_PKG
#if this is uncommented then if one package is missing then all missing packages are immediately installed..
sudo apt-get --yes install $SYSTEM_DEPENDENCIES
break
fi
done
#------------------------------------------------------------------------------
HEADLESS=" --headless"
OPENCV=" "
if [[ $* == *--collab* ]]
then
echo "Collab mode!"
echo "Performing python package installation without a virtual environment"
HEADLESS=" --headless"
OPENCV="opencv-python-headless"
rm -rf /content/sample_data/ #remove sample data
ln -s $DIR /content/mnet4
sudo apt-get --yes install build-essential freeglut3-dev libglew-dev #For some reason collab has some errors on previous check so just double-make sure we have these libraries
else
echo "Using a python pythonVirtualEnvironment environment"
echo "Activate it using : source pythonVirtualEnvironment/bin/activate"
python3 -m venv pythonVirtualEnvironment
source pythonVirtualEnvironment/bin/activate
OPENCV="opencv-python"
HEADLESS=" "
fi
cd "$DIR"
if [ -f RGBDAcquisition/README.md ]; then
echo "RGBDAcquisition appears to already exist .."
else
git clone https://github.com/AmmarkoV/RGBDAcquisition
cd RGBDAcquisition
#----------------------------------------------------------------------------------------------------------------------
#mkdir build
#cd build
#cmake ..
#cd ..
#----------------------------------------------------------------------------------------------------------------------
cd opengl_acquisition_shared_library/opengl_depth_and_color_renderer/
mkdir build
cd build
cmake ..
make BVHTester
#----------------------------------------------------------------------------------------------------------------------
cd "$DIR"
ln -s RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Applications/BVHTester BVH
ln -s RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/BVHTester GroundTruthDumper
fi
python3 -m pip install --upgrade pip #2.8.0 nvidia-tensorrt
python3 -m pip install tensorflow numpy numba tensorboard_plugin_profile tensorflow-model-optimization keras pillow tf2onnx onnxruntime onnx matplotlib pydot mediapipe $OPENCV scikit-learn
#Two ways to get Models!
#One through the database and compile them yourself (commented out to save Google Collab CPU time)..
#python3 -m getModelFromDatabase --get 318
#To generate the archive in the next lines do :
# zip mnet4_318.zip step1_*/*
#Another just take the precompiled ensembles ready to run
wget http://ammar.gr/mocapnet/mnet4/mnet4_-314.zip -O mnet4_-314.zip
unzip -o mnet4_-314.zip #<- upgrade to 324 mnet4_318.zip
#Unzip models for PoseNET.py operation..
wget http://ammar.gr/mocapnet/mnet4/mediapipe.zip -O mediapipe.zip
unzip -o mediapipe.zip
#To get :
# python3 -m evaluateMocapNET --config dataset/body_configuration.json --all body --engine onnx
# to work
#wget http://cvrlcode.ics.forth.gr/web_share/mocapnet/MocapNETBodyValidationSet.zip
#wget http://ammar.gr/datasets/MocapNETBodyValidationSet.zip
#unzip MocapNETBodyValidationSet.zip
#Doing a test run!
# echo "To enable Tensorflow profiling for non-root users please add : "
# echo "options nvidia \"NVreg_RestrictProfilingToAdminUsers=0\""
# echo "to /etc/modprobe.d/nvidia-graphics-drivers.conf"
# echo " "
echo "Ready for use"
echo "From now on to work with MocapNET you can use : "
echo "source pythonVirtualEnvironment/bin/activate"
echo "!python3 -m mediapipeHolisticWebcamMocapNET --from webcam --save --plot"
echo " OR "
echo "!python3 -m mediapipeHolisticWebcamMocapNET --from shuffle.webm --save --plot"
echo " OR "
echo "!python3 -m csvNET --from ../../../dataset/sample.csv --save --plot"
echo " "
echo " if you are running on collab don't forget to append --headless to your command"
echo " after the run is complete out.bvh will contain your results "
#Force making of library during last-stage of setup..
BVH/makeLibrary.sh
@@ -0,0 +1,556 @@
from scipy.stats import qmc
import numpy as np
import random
"""
python3 sobolRandomDatasetGenerator.py --upperbody --exponent 21
rm dataset/generated/2d_upperbody_all.csv dataset/generated/bvh_upperbody_all.csv
./GroundTruthDumper --from dataset/headerWithHeadAndOneMotion.bvh --importCSVPoses sobolUpperbody_2097152.csv --filterOccludedJoints --csv dataset/generated/ upperbody_all.csv 2d+3d+bvh
python3 sobolRandomDatasetGenerator.py --lowerbody --exponent 21
rm dataset/generated/2d_lowerbody_all.csv dataset/generated/bvh_lowerbody_all.csv
./GroundTruthDumper --from dataset/headerWithHeadAndOneMotion.bvh --importCSVPoses sobolLowerbody_2097152.csv --csv dataset/generated/ lowerbody_all.csv 2d+3d+bvh
python3 sobolRandomDatasetGenerator.py --lhand --exponent 21
rm dataset/generated/2d_lhand_all.csv dataset/generated/bvh_lhand_all.csv
./GroundTruthDumper --from dataset/lhand.qbvh --importCSVPoses sobolLHand_2097152.csv --csv dataset/generated/ lhand_all.csv 2d+3d+bvh
scp -P 2234 dataset/generated/2d_upperbody_all.csv dataset/generated/bvh_upperbody_all.csv dataset/generated/2d_lowerbody_all.csv dataset/generated/bvh_lowerbody_all.csv dataset/generated/2d_lhand_all.csv dataset/generated/bvh_lhand_all.csv ammar@cvrldemo:/home/ammar/Documents/Programming/DNNTracker/tensorflow2GPU/src/dataset/generated
"""
#python3 -m csvNET --from SCANREYE.csv --reye --nobody --plot --save
def scanReye(filename):
f = open(filename, 'w')
f.write("2DX_head_reye_0,2DY_head_reye_0,visible_head_reye_0,2DX_head_reye_1,2DY_head_reye_1,visible_head_reye_1,2DX_head_reye_2,2DY_head_reye_2,visible_head_reye_2,2DX_head_reye_3,2DY_head_reye_3,visible_head_reye_3,2DX_head_reye_4,2DY_head_reye_4,visible_head_reye_4,2DX_head_reye_5,2DY_head_reye_5,visible_head_reye_5,2DX_head_nostrills_2,2DY_head_nostrills_2,visible_head_nostrills_2,2DX_head_rchin_0,2DY_head_rchin_0,visible_head_rchin_0,2DX_head_chin,2DY_head_chin,visible_head_chin,2DX_head_reyebrow_0,2DY_head_reyebrow_0,visible_head_reyebrow_0,2DX_head_reyebrow_1,2DY_head_reyebrow_1,visible_head_reyebrow_1,2DX_head_reyebrow_2,2DY_head_reyebrow_2,visible_head_reyebrow_2,2DX_head_reyebrow_3,2DY_head_reyebrow_3,visible_head_reyebrow_3,2DX_head_reyebrow_4,2DY_head_reyebrow_4,visible_head_reyebrow_4,2DX_head_reye,2DY_head_reye,visible_head_reye\n")
for x in range(710,740): #710 - 750
for y in range(270,280): #range(270,271): #260 - 290
xF = float(x / 1000)
yF = float(y / 1000)
f.write("0.706034,0.271945,1,0.713014,0.265075,1,0.724606,0.264025,1,0.734642,0.276731,1,0.723602,0.280737,1,0.71263,0.277377,1,0.755537,0.331723,1,0.688397,0.274243,1,0.749762,0.466904,1,0.690998,0.262801,1,0.703323,0.247993,1,0.713234,0.238449,1,0.731472,0.246738,1,0.742246,0.255172,1,%f,%f,1\n" % (xF,yF) )
f.close()
import sys
sys.exit(0)
def getUpperbodyList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
minR = -179.90
maxR = 179.90
dof = 0
#-----------------------------------
#joints.append("hip_Xposition"); minima.append(-340.0); maxima.append(340.0); rootDofs.append(dof); dof+=1 # -529 529 original
#joints.append("hip_Yposition"); minima.append(-80.0); maxima.append(80.0); rootDofs.append(dof); dof+=1 # -207 208 original
#joints.append("hip_Zposition"); minima.append(-500.0); maxima.append(-100.0); rootDofs.append(dof); dof+=1 # -450 -90 original
#-------------------------------------------------------------------------------
#joints.append("hip_Zrotation"); minima.append(-45.0); maxima.append(45.0); rootDofs.append(dof); dof+=1
#joints.append("hip_Yrotation"); minima.append(minR); maxima.append(maxR); rootDofs.append(dof); dof+=1
#joints.append("hip_Xrotation"); minima.append(-45.0); maxima.append(45.0); rootDofs.append(dof); dof+=1
#-------------------------------------------------------------------------------
joints.append("abdomen_Zrotation"); minima.append(-175.82); maxima.append(maxR); dof+=1
joints.append("abdomen_Xrotation"); minima.append(-87.84); maxima.append(92.43); dof+=1
joints.append("abdomen_Yrotation"); minima.append(-176.7); maxima.append(173.33); dof+=1
joints.append("chest_Zrotation"); minima.append(-63.64); maxima.append(59.23); dof+=1
joints.append("chest_Xrotation"); minima.append(-59.62); maxima.append(42.48); dof+=1
joints.append("chest_Yrotation"); minima.append(-30.52); maxima.append(34.27); dof+=1
joints.append("neck1_Zrotation"); minima.append(-74.41); maxima.append(97.04); dof+=1
joints.append("neck1_Xrotation"); minima.append(-63.63); maxima.append(81.78); dof+=1
joints.append("neck1_Yrotation"); minima.append(-63.31); maxima.append(71.25); dof+=1
joints.append("head_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("head_Xrotation"); minima.append(-89.24); maxima.append(86.77); dof+=1
joints.append("head_Yrotation"); minima.append(-178.54); maxima.append(maxR); dof+=1
#-------------------------------------------------------------------------------
joints.append("rshoulder_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rshoulder_Xrotation"); minima.append(-102.07); maxima.append(103.87); dof+=1
joints.append("rshoulder_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("relbow_Zrotation"); minima.append(-44.67); maxima.append(34.52); dof+=1
joints.append("relbow_Xrotation"); minima.append(-68.55); maxima.append(9.42); dof+=1
joints.append("relbow_Yrotation"); minima.append(-110.29); maxima.append(164.34); dof+=1
joints.append("rhand_Zrotation"); minima.append(-169.3); maxima.append(4.01); dof+=1
joints.append("rhand_Xrotation"); minima.append(-88.3); maxima.append(85.24); dof+=1
joints.append("rhand_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#-------------------------------------------------------------------------------
joints.append("lshoulder_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lshoulder_Xrotation"); minima.append(-103.92); maxima.append(103.45); dof+=1
joints.append("lshoulder_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lelbow_Zrotation"); minima.append(-14.97); maxima.append(47.34); dof+=1
joints.append("lelbow_Xrotation"); minima.append(-68.43); maxima.append(8.68); dof+=1
joints.append("lelbow_Yrotation"); minima.append(-163.07); maxima.append(15.34); dof+=1
joints.append("lhand_Zrotation"); minima.append(-7.17); maxima.append(172.41); dof+=1
joints.append("lhand_Xrotation"); minima.append(-88.13); maxima.append(85.43); dof+=1
joints.append("lhand_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
#python3 sobolRandomDatasetGenerator.py --exponent 21 --lowerbody --copy
def getLowerbodyList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
minR = -179.90
maxR = 179.90
dof = 0
#-------------------------------------------------------------------------------
#These are no longer needed because they are randomized by the GroundTruthGenerator tool!
#joints.append("hip_Xposition"); minima.append(-340.0); maxima.append(340.0); rootDofs.append(dof); dof+=1 # -529 529 original
#joints.append("hip_Yposition"); minima.append(-80.0); maxima.append(80.0); rootDofs.append(dof); dof+=1 # -207 208 original
#joints.append("hip_Zposition"); minima.append(-500.0); maxima.append(-100.0); rootDofs.append(dof); dof+=1 # -450 -90 original
#-------------------------------------------------------------------------------
#joints.append("hip_Zrotation"); minima.append(-45.0); maxima.append(45.0); rootDofs.append(dof); dof+=1
#joints.append("hip_Yrotation"); minima.append(minR); maxima.append(maxR); rootDofs.append(dof); dof+=1
#joints.append("hip_Xrotation"); minima.append(-45.0); maxima.append(45.0); rootDofs.append(dof); dof+=1
#-------------------------------------------------------------------------------
#joints.append("abdomen_Zrotation"); minima.append(-174.88); maxima.append(174.88); dof+=1
#joints.append("abdomen_Xrotation"); minima.append(-90.0); maxima.append(90.0); dof+=1
#joints.append("abdomen_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#joints.append("chest_Zrotation"); minima.append(-57.0); maxima.append(57.0); dof+=1
#joints.append("chest_Xrotation"); minima.append(-61.78); maxima.append(40.94); dof+=1
#joints.append("chest_Yrotation"); minima.append(-35.27); maxima.append(27.58); dof+=1
#joints.append("neck1_Zrotation"); minima.append(-76.28); maxima.append(97.18); dof+=1
#joints.append("neck1_Xrotation"); minima.append(-63.08); maxima.append(81.78); dof+=1
#joints.append("neck1_Yrotation"); minima.append(-63.31); maxima.append(71.64); dof+=1
#-------------------------------------------------------------------------------
joints.append("rhip_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rhip_Xrotation"); minima.append(-104.0); maxima.append(94.0); dof+=1 #Default -104.11 .. 73.67
joints.append("rhip_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rknee_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rknee_Xrotation"); minima.append(-66.0); maxima.append(94.0); dof+=1 #Default -66.73 .. 94.07
joints.append("rknee_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rfoot_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rfoot_Xrotation"); minima.append(-89.0); maxima.append(89.0); dof+=1 #Default -90.86 .. 89.26
joints.append("rfoot_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#-------------------------------------------------------------------------------
joints.append("lhip_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lhip_Xrotation"); minima.append(-104.0); maxima.append(94.0); dof+=1 #Default -104.23 .. 93.92
joints.append("lhip_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lknee_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lknee_Xrotation"); minima.append(-66.0); maxima.append(94.0); dof+=1 #Default -46.36 .. 94.34
joints.append("lknee_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lfoot_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lfoot_Xrotation"); minima.append(-89.0); maxima.append(89.0); dof+=1 #Default -89.38 .. 91.81
joints.append("lfoot_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
def getFullFaceList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
#/home/ammar/Programs/blender-3.4.1-linux-x64/3.4/scripts/addons/io_anim_bvh/import_bvh.py
#-----------------------------------
joints.append("hip_Xposition"); minima.append(-0.24); maxima.append(0.24); rootDofs.append(dof); dof+=1
joints.append("hip_Yposition"); minima.append(-0.10); maxima.append(0.10); rootDofs.append(dof); dof+=1
joints.append("hip_Zposition"); minima.append(-2.4); maxima.append(-1.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Zrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Xrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Yrotation"); minima.append(-30.0); maxima.append(30.0); rootDofs.append(dof); dof+=1
joints.append("eye.R_Zrotation"); minima.append(-45.36); maxima.append(45.36); dof+=1
joints.append("eye.R_Xrotation"); minima.append(-10.0); maxima.append(16.0); dof+=1
#Let's assume eyes move together..
#joints.append("eye.L_Zrotation"); minima.append(-20.0); maxima.append(20.0)
#joints.append("eye.L_Xrotation"); minima.append(-7.0); maxima.append(20.0)
joints.append("oculi01.R_Zrotation"); minima.append(-20.0); maxima.append(20.0); dof+=1
joints.append("oculi01.L_Zrotation"); minima.append(-20.0); maxima.append(20.0); dof+=1
joints.append("orbicularis03.R_Xrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
joints.append("orbicularis03.L_Xrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
#joints.append("orbicularis04.R_Xrotation"); minima.append(-15.0); maxima.append(15.0) #This is flipped orbicularis03.R_Xrotation
#joints.append("orbicularis04.L_Xrotation"); minima.append(-15.0); maxima.append(15.0) #This is flipped orbicularis03.L_Xrotation
joints.append("levator06.L_Xrotation"); minima.append(-9.0); maxima.append(9.0); dof+=1
#joints.append("levator06.R_Xrotation"); minima.append(-9.0); maxima.append(9.0) #This is levator06.L_Xrotation
joints.append("levator03.L_Zrotation"); minima.append(-8.0); maxima.append(9.0); dof+=1
#joints.append("levator03.R_Zrotation"); minima.append(-9.0); maxima.append(8.0); dof+=1 #This is flipped levator03.L_Zrotation
joints.append("oris03.L_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris03.R_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris07.L_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("oris07.R_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("jaw_Xrotation"); minima.append(-4.0); maxima.append(20.0); dof+=1
joints.append("jaw_Yrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
joints.append("oris04.L_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("oris04.R_Zrotation"); minima.append(0.0); maxima.append(30.0); dof+=1
joints.append("oris06.L_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris06.R_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
#-----------------------------------
constants["orbicularis03.R_Yrotation"] = 172.0
constants["orbicularis04.R_Yrotation"] = 172.0
constants["orbicularis03.L_Yrotation"] = -172.0
constants["orbicularis04.L_Yrotation"] = 172.0
constants["levator06.L_Yrotation"] = -247.0
constants["levator06.R_Yrotation"] = 247.0
constants["oris03.L_Xrotation"] = -40.0
constants["oris03.L_Yrotation"] = 172.0
constants["oris07.L_Yrotation"] = 172.0
constants["oris03.R_Xrotation"] = -40.0
constants["oris03.R_Yrotation"] = 179.0
constants["oris07.R_Yrotation"] = 172.0
constants["oris05_Xrotation"] = -35.0
constants["oris05_Yrotation"] = -176.0
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
def getReyeList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
#-----------------------------------
joints.append("hip_Xposition"); minima.append(-0.24); maxima.append(0.24); rootDofs.append(dof); dof+=1
joints.append("hip_Yposition"); minima.append(-0.10); maxima.append(0.10); rootDofs.append(dof); dof+=1
joints.append("hip_Zposition"); minima.append(-2.3); maxima.append(-1.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Zrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Xrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Yrotation"); minima.append(-30.0); maxima.append(30.0); rootDofs.append(dof); dof+=1
joints.append("eye.R_Zrotation"); minima.append(-45.36); maxima.append(45.36); dof+=1
joints.append("eye.R_Xrotation"); minima.append(-10.0); maxima.append(16.0); dof+=1
joints.append("oculi01.R_Zrotation"); minima.append(-20.0); maxima.append(20.0); dof+=1
joints.append("orbicularis03.R_Xrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
joints.append("jaw_Xrotation"); minima.append(-4.0); maxima.append(20.0); dof+=1 #Reason being adding some robustness
joints.append("jaw_Yrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1 #Reason being adding some chin robustness
#-----------------------------------
constants["orbicularis03.R_Yrotation"] = 172.0
constants["orbicularis04.R_Yrotation"] = 172.0
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
def getMouthList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
#-----------------------------------
joints.append("hip_Xposition"); minima.append(-0.24); maxima.append(0.24); rootDofs.append(dof); dof+=1
joints.append("hip_Yposition"); minima.append(-0.10); maxima.append(0.10); rootDofs.append(dof); dof+=1
joints.append("hip_Zposition"); minima.append(-2.4); maxima.append(-1.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Zrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Xrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Yrotation"); minima.append(-30.0); maxima.append(30.0); rootDofs.append(dof); dof+=1
joints.append("levator06.L_Xrotation"); minima.append(-9.0); maxima.append(9.0); dof+=1
#joints.append("levator06.R_Xrotation"); minima.append(-9.0); maxima.append(9.0); dof+=1 #This is levator06.L_Xrotation
joints.append("levator03.L_Zrotation"); minima.append(-8.0); maxima.append(9.0); dof+=1
#joints.append("levator03.R_Zrotation"); minima.append(-9.0); maxima.append(8.0); dof+=1 #This is flipped levator03.L_Zrotation
joints.append("oris03.L_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris03.R_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris07.L_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("oris07.R_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("jaw_Xrotation"); minima.append(-4.0); maxima.append(20.0); dof+=1
joints.append("jaw_Yrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
joints.append("oris04.L_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("oris04.R_Zrotation"); minima.append(0.0); maxima.append(30.0); dof+=1
joints.append("oris06.L_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris06.R_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
#-----------------------------------
constants["levator06.L_Yrotation"] = -247.0
constants["levator06.R_Yrotation"] = 247.0
constants["oris03.L_Xrotation"] = -40.0
constants["oris03.L_Yrotation"] = 172.0
constants["oris07.L_Yrotation"] = 172.0
constants["oris03.R_Xrotation"] = -40.0
constants["oris03.R_Yrotation"] = 179.0
constants["oris07.R_Yrotation"] = 172.0
constants["oris05_Xrotation"] = -35.0
constants["oris05_Yrotation"] = -176.0
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
def getLHandList():
#--------------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
#--------------------------------------
joints.append("lhand_Xposition"); minima.append(-120.0); maxima.append(120.0); rootDofs.append(dof); dof+=1 #230
joints.append("lhand_Yposition"); minima.append(-60.0); maxima.append(60.0); rootDofs.append(dof); dof+=1 #92
joints.append("lhand_Zposition"); minima.append(-250.0); maxima.append(-75.0); rootDofs.append(dof); dof+=1
#joints.append("padding_1"); minima.append(0.0); maxima.append(0.0); rootDofs.append(dof); dof+=1 #<- Align to 4 elements
#--------------------------------------
joints.append("lhand_Wrotation"); minima.append(-1.0); maxima.append(1.0); rootDofs.append(dof); dof+=1
joints.append("lhand_Xrotation"); minima.append(-1.0); maxima.append(1.0); rootDofs.append(dof); dof+=1
joints.append("lhand_Yrotation"); minima.append(-1.0); maxima.append(1.0); rootDofs.append(dof); dof+=1
joints.append("lhand_Zrotation"); minima.append(-1.0); maxima.append(1.0); rootDofs.append(dof); dof+=1
#--------------------------------------
joints.append("finger2-1.l_Zrotation"); minima.append(-90.0); maxima.append(10.0); dof+=1
joints.append("finger2-1.l_Yrotation"); minima.append(-20.0); maxima.append(20.0); dof+=1
joints.append("finger2-2.l_Zrotation"); minima.append(-90.0); maxima.append(0.0); dof+=1
joints.append("finger2-3.l_Zrotation"); minima.append(-45.0); maxima.append(0.0); dof+=1
#--------------------------------------
joints.append("finger3-1.l_Zrotation"); minima.append(-90.0); maxima.append(10.0); dof+=1
joints.append("finger3-1.l_Yrotation"); minima.append(-10.0); maxima.append(10.0); dof+=1
joints.append("finger3-2.l_Zrotation"); minima.append(-90.0); maxima.append(0.0); dof+=1
joints.append("finger3-3.l_Zrotation"); minima.append(-45.0); maxima.append(0.0); dof+=1
#--------------------------------------
joints.append("finger4-1.l_Zrotation"); minima.append(-90.0); maxima.append(10.0); dof+=1
joints.append("finger4-1.l_Yrotation"); minima.append(-10.0); maxima.append(10.0); dof+=1
joints.append("finger4-2.l_Zrotation"); minima.append(-90.0); maxima.append(0.0); dof+=1
joints.append("finger4-3.l_Zrotation"); minima.append(-45.0); maxima.append(0.0); dof+=1
#--------------------------------------
joints.append("finger5-1.l_Zrotation"); minima.append(-90.0); maxima.append(10.0); dof+=1
joints.append("finger5-1.l_Yrotation"); minima.append(-8.0); maxima.append(25.0); dof+=1
joints.append("finger5-2.l_Zrotation"); minima.append(-90.0); maxima.append(0.0); dof+=1
joints.append("finger5-3.l_Zrotation"); minima.append(-45.0); maxima.append(0.0); dof+=1
#--------------------------------------
joints.append("lthumbBase_Zrotation"); minima.append(0.0); maxima.append(60.0); dof+=1
joints.append("lthumbBase_Xrotation"); minima.append(-35.0); maxima.append(0.0); dof+=1
joints.append("lthumbBase_Yrotation"); minima.append(0.0); maxima.append(60.0); dof+=1
#joints.append("padding_2"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#--------------------------------------
joints.append("lthumb_Zrotation"); minima.append(-85.0); maxima.append(85.0); dof+=1
joints.append("lthumb_Xrotation"); minima.append(-30.0); maxima.append(48.0); dof+=1
joints.append("lthumb_Yrotation"); minima.append(0.0); maxima.append(85.0); dof+=1
#joints.append("padding_3"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#--------------------------------------
joints.append("finger1-2.l_Zrotation"); minima.append(-35.0); maxima.append(0.0); dof+=1
joints.append("finger1-2.l_Xrotation"); minima.append(-40.0); maxima.append(45.0); dof+=1
joints.append("finger1-2.l_Yrotation"); minima.append(-70.0); maxima.append(35.0); dof+=1
#joints.append("padding_4"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#--------------------------------------
joints.append("finger1-3.l_Zrotation"); minima.append(-50.0); maxima.append(0.0); dof+=1
joints.append("finger1-3.l_Xrotation"); minima.append(0.0); maxima.append(50.0); dof+=1
#joints.append("padding_5"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#joints.append("padding_6"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#--------------------------------------
return minima,maxima,joints,constants,dof,rootDofs
#------------------------------------------
# Generate actual samples..
#------------------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
datasetPart = "Face"
exponent = 17
doPlots = False
doFinalCopy = False
neutralSamples = 0
#----------------
# Exponent
#----------------
# 14 = 16.384
# 15 = 32.768
# 16 = 65.536
# 17 = 131.072
# 18 = 262.144
# 19 = 524.288
# 20 = 1.048.576
# 21 = 2.097.152
# 22 = 4.194.304
# 23 = 8.388.608
# 24 = 16.777.216
#----------------
import sys
mem = 1.0
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--scanreye"):
scanReye("SCANREYE.csv")
if (sys.argv[i]=="--copy"):
doFinalCopy = True
if (sys.argv[i]=="--plot"):
doPlots = True
if (sys.argv[i]=="--neutral"):
neutralSamples = int(sys.argv[i+1])
elif (sys.argv[i]=="--exponent"):
exponent = int(sys.argv[i+1])
elif (sys.argv[i]=="--upperbody"):
datasetPart = "Upperbody"
minima,maxima,joints,constants,dof,rootDofs = getUpperbodyList()
elif (sys.argv[i]=="--lowerbody"):
datasetPart = "Lowerbody"
minima,maxima,joints,constants,dof,rootDofs = getLowerbodyList()
elif (sys.argv[i]=="--lhand"):
datasetPart = "LHand"
minima,maxima,joints,constants,dof,rootDofs = getLHandList()
elif (sys.argv[i]=="--reye"):
datasetPart = "REye"
minima,maxima,joints,constants,dof,rootDofs = getReyeList()
elif (sys.argv[i]=="--mouth"):
datasetPart = "Mouth"
minima,maxima,joints,constants,dof,rootDofs = getMouthList()
elif (sys.argv[i]=="--face"):
datasetPart = "Face"
minima,maxima,joints,constants,dof,rootDofs = getFullFaceList()
if (len(minima)==0) and (len(maxima)==0) and (len(joints)==0):
print("Please rerun using --face OR --mouth OR --reye OR --lhand OR --upperbody OR --lowerbody to select a target")
numberOfDimensions = len(joints)
numberOfSamples = 2**exponent
filename = "sobol%s_%u.csv" % (datasetPart,numberOfSamples+neutralSamples)
#------------------------------------------
print("Will generate ",numberOfSamples," samples ")
print("Will generate random numbers for ",numberOfDimensions," dimensions")
print("We have ",dof," degrees of freedom")
samplesPerDimension = np.power(numberOfSamples,1/dof)
print("Samples per Dimension : %0.2f "%samplesPerDimension)
print("Involved joints are : ",joints)
sampler = qmc.Sobol(d=numberOfDimensions, scramble=False)
sample = sampler.random_base2(m=exponent)
print("Numbers generated now storing them to ",filename)
#print(sample)
#=========================================
# Write label
#=========================================
f = open(filename, 'w')
recordsWritten=0
#-----------------------------------------
for item in range(0,numberOfDimensions):
if (recordsWritten>0):
f.write(',')
#f.write("dim%u"%(recordsWritten))
f.write("%s" % (joints[item]))
recordsWritten=recordsWritten+1
#-----------------------------------------
if (constants):
for key in constants.keys():
if (recordsWritten>0):
f.write(',')
#f.write("dim%u"%(recordsWritten))
f.write("%s" % (joints[item]))
recordsWritten=recordsWritten+1
#-----------------------------------------
f.write("\n")
#=========================================
#=========================================
# Write Sobol Samples
#=========================================
for sampleNumber in range(0,numberOfSamples):
recordsWritten=0
for item in range(0,numberOfDimensions):
if (recordsWritten>0):
f.write(',')
thisRange = maxima[item]-minima[item]
f.write("%f"%( (thisRange * sample[sampleNumber][item]) + minima[item]) )
recordsWritten=recordsWritten+1
if (constants):
for key in constants.keys():
if (recordsWritten>0):
f.write(',')
f.write("%f"%(constants[key]))
recordsWritten=recordsWritten+1
f.write("\n")
#=========================================
#=========================================
# Write Neutral Samples
#=========================================
if (neutralSamples>0):
print("We will also append %u neutral samples " % neutralSamples)
#=========================================
for sampleNumber in range(0,neutralSamples):
recordsWritten=0
for item in range(0,numberOfDimensions):
if (recordsWritten>0):
f.write(',')
if (item in rootDofs):
#Poor quality uniform random value
value = random.uniform(minima[item],maxima[item])
else:
#True Neutral mean value
value = float((maxima[item]+minima[item]) / 2)
f.write("%f" % value)
recordsWritten=recordsWritten+1
if (constants):
for key in constants.keys():
if (recordsWritten>0):
f.write(',')
f.write("%f"%(constants[key]))
recordsWritten=recordsWritten+1
f.write("\n")
#=========================================
f.close()
import os
#------------------------------
if (doPlots):
os.system("python3 plotCSV.py --simple %s "%filename)
#------------------------------
command1 = ""
command2 = ""
command3 = ""
havePayload = False
minOrientation = -179.90
maxOrientation = 179.90
#------------------------------
if (datasetPart == "LHand"):
command1 = "rm dataset/generated/2d_lhand_all.csv dataset/generated/bvh_lhand_all.csv"
command2 = "./GroundTruthDumper --from dataset/lhand.qbvh --importCSVPoses %s --randomize2D 200 2500 -179.0 -179.0 -179.0 179.0 179.0 179.0 --selectJoints 1 17 lHand finger5-1.l finger5-2.l finger5-3.l finger4-1.l finger4-2.l finger4-3.l finger3-1.l finger3-2.l finger3-3.l finger2-1.l finger2-2.l finger2-3.l lthumbBase lthumb finger1-2.l finger1-3.l --hide2DLocationOfJoints 0 1 lthumbBase --csv dataset/generated/ lhand_all.csv 2d+bvh " % (filename)
command3 = "python3 compressCSVFile.py dataset/generated/bvh_lhand_all.csv && mv dataset/generated/bvh_lhand_all.csv dataset/generated/bvh_lhand_all.csv.original && mv compressed.csv dataset/generated/bvh_lhand_all.csv "
havePayload = True
elif (datasetPart == "Upperbody"):
command1 = "rm dataset/generated/2d_upperbody_all.csv dataset/generated/bvh_upperbody_all.csv"
command2 = "./GroundTruthDumper --from dataset/headerWithHeadAndOneMotion.bvh --importCSVPoses %s --randomize2D 1000 4500 -45 %0.2f -45 45 %0.2f 45 --selectJoints 1 13 hip eye.r eye.l abdomen chest neck head rshoulder relbow rhand lshoulder lelbow lhand --hide2DLocationOfJoints 0 4 abdomen chest eye.r eye.l --csv dataset/generated/ upperbody_all.csv 2d+bvh " % (filename,minOrientation,maxOrientation)
havePayload = True
elif (datasetPart == "Lowerbody"):
command1 = "rm dataset/generated/2d_lowerbody_all.csv dataset/generated/bvh_lowerbody_all.csv"
command2 = "./GroundTruthDumper --from dataset/headerWithHeadAndOneMotion.bvh --importCSVPoses %s --randomize2D 1000 4500 -45 %0.2f -45 45 %0.2f 45 --selectJoints 1 14 hip abdomen chest neck rhip rknee rfoot lhip lknee lfoot toe1-2.r toe5-3.r toe1-2.l toe5-3.l --hide2DLocationOfJoints 0 6 abdomen chest toe1-2.r toe5-3.r toe1-2.l toe5-3.l --csv dataset/generated/ lowerbody_all.csv 2d+bvh " % (filename,minOrientation,maxOrientation)
havePayload = True
#------------------------------
if (havePayload):
if (doFinalCopy):
os.system(command1)
os.system(command2)
if (command3!=""):
os.system(command3)
else:
print("To copy data, please execute : ")
print(command1)
print(command2)
if (command3!=""):
print(command3)
#------------------------------
@@ -0,0 +1,585 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import gc
import os
import sys
import time
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.models import Sequential
from tensorflow.keras.models import model_from_json
from tensorflow.keras.utils import plot_model
import numpy as np
from readCSV import parseConfiguration,checkIfConfigurationHierarchyIsTheSameAsLabelList,readGroundTruthFile,selectOnlySpecificColumnsOfNumpyArray
from DNNModel import loadModel,combineModels,combineAsSingleModel,saveModel
from tools import bcolors,dumpListToFile,createDirectory,checkIfPathExists,notification,getRAMInformation
from DNNTraining import printTrainingVersion,setTensorflowBackendToHalfFloats
def doCombinedModelValidation(outputDirectoryForCombinedModels,groundTruth,merged):
if (groundTruth["in"].shape[0]!=groundTruth["out"].shape[0]):
print(bcolors.FAIL,"Cannot perform network validation, mismatched input/output..",bcolors.ENDC)
sys.exit(1)
#----------------------------------------------------------------------------------
print(bcolors.OKBLUE,"Doing network validation..",bcolors.ENDC)
print("We have ",groundTruth["in"].shape[0]," input samples")
print("We have ",groundTruth["in"].shape[1]," elements in each input sample")
print("We have ",groundTruth["out"].shape[0]," output samples")
print("We have ",groundTruth["out"].shape[1]," elements in each output sample")
#-------------------------------------------------------------------------------
numberOfOutputs = groundTruth["out"].shape[1]
#-------------------------------------------------------------------------------
outputScalars = [1.0] * numberOfOutputs
outputOffsets = [0.0] * numberOfOutputs
outputMinima = [-6000.0] * numberOfOutputs
outputMaxima = [6000.0] * numberOfOutputs
#-------------------------------------------------------------------------------
from readCSV import parseOutputNormalization
from tools import readListFromFile,convertListToLowerCase
#-------------------------------------------------------------------------------
outputs = convertListToLowerCase(readListFromFile(outputDirectoryForCombinedModels+"/neuralNetworkOutputs.list"))
outputOffsets = parseOutputNormalization(outputDirectoryForCombinedModels,"/outputOffsets.csv",outputs,outputOffsets)
outputScalars = parseOutputNormalization(outputDirectoryForCombinedModels,"/outputScalarsFraction.csv",outputs,outputScalars)
outputMinima = parseOutputNormalization(outputDirectoryForCombinedModels,"/outputMinima.csv",outputs,outputMinima)
outputMaxima = parseOutputNormalization(outputDirectoryForCombinedModels,"/outputMaxima.csv",outputs,outputMaxima)
#-------------------------------------------------------------------------------
losses = list()
for outputItem in range(0,groundTruth["out"].shape[1]):
losses.append(0.0)
#----------------------------------------------------------------------------------
for sample in range(0,groundTruth["in"].shape[0]):
networkInput = np.asarray([groundTruth["in"][sample]],dtype=np.float32)
print("Sample : ",sample," |",end='')
inferenceOutputs = merged(tf.cast(networkInput,dtype=tf.float32))
for outputItem in range(0,groundTruth["out"].shape[1]):
out = float(inferenceOutputs[0][outputItem])
#------------------------------------------------------------
out = (out * outputScalars[i]) + outputOffsets[i]
if (out>outputMaxima[i]):
out=outputMaxima[i]
if (out<outputMinima[i]):
out=outputMinima[i]
#------------------------------------------------------------
thisLoss = float(abs(out-groundTruth["out"][sample][outputItem]))
print("|",thisLoss,"|",end='')
losses[outputItem] += thisLoss
print(" ")
#----------------------------------------------------------------------------------
for outputItem in range(0,groundTruth["out"].shape[1]):
print("Output item ",outputItem," loss ~=> ",float(losses[outputItem]/groundTruth["out"].shape[1]) )
sys.exit(0)
#-----------------------------------------------------------------------------------------------------------------
def step1_DNNCombine(useCSVBackend,groundTruth):
printTrainingVersion()
print("""
███████╗███╗ ██╗███████╗███████╗███╗ ███╗██████╗ ██╗ ███████╗
██╔════╝████╗ ██║██╔════╝██╔════╝████╗ ████║██╔══██╗██║ ██╔════╝
█████╗ ██╔██╗ ██║███████╗█████╗ ██╔████╔██║██████╔╝██║ █████╗
██╔══╝ ██║╚██╗██║╚════██║██╔══╝ ██║╚██╔╝██║██╔══██╗██║ ██╔══╝
███████╗██║ ╚████║███████║███████╗██║ ╚═╝ ██║██████╔╝███████╗███████╗
╚══════╝╚═╝ ╚═══╝╚══════╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚══════╝
""")
print("DNNTrainer starting up..\n")
np.set_printoptions(precision=2)
np.set_printoptions(formatter={"float_kind": lambda x: "%g" % x})
#Defaults
#-------------------
useHalfFloats = 0
useNonCompressed = 1
useCompressed = 1
#-------------------
#This will be get populated using the --config argument
configuration = dict()
configurationPath=""
numberOfChannelsPerNSDMElement=2
#datasetDirectory="../../DNNTracker/dataset"
datasetDirectory="dataset/generated/"
#By default no training samples need to be loaded
trainingSamplesPercentage=0.0
#Default Names
#------------------------------------------------
hierarchyPartName = "body"
label = "unknown"
dataFile = "body"
testFile = "body_test"
outputMode = "bvh"
configuration['outputMode'] = "bvh"
doModelOptimization = False
doModelValidation = False
inputLabels = list()
outputLabels = list()
#------------------------------------------------
outputDirectoryForTrainedModels ="step0FrontBody"
outputDirectoryForCombinedModels="step1FrontBody"
filesPath=outputDirectoryForTrainedModels #"./"
#------------------------------------------------
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--mem"):
print("Will load more than 0 training samples.. ",sys.argv[i+1],"\n");
trainingSamplesPercentage=float(sys.argv[i+1])
if (sys.argv[i]=="--optimize"):
print("Will also attempt to optimize network\n");
trainingSamplesPercentage=1.0 #<- This should be like --mem 1.0
doModelOptimization = True
if (sys.argv[i]=="--validate"):
print("Will also attempt to validate network\n");
trainingSamplesPercentage=1.0 #<- This should be like --mem 1.0
doModelValidation = True
if (sys.argv[i]=="--config"):
configurationPath = sys.argv[i+1]
configuration = parseConfiguration(configurationPath)
label = configuration['OutputDirectory']
if (configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element set to ",numberOfChannelsPerNSDMElement)
if (configuration['precision']=="fp16"):
useHalfFloats=1
configuration['rememberWeights']=0
setTensorflowBackendToHalfFloats()
elif (configuration['precision']!="fp32"):
print(bcolors.WARNING,"Cannot use ",configuration['precision']," precision\n",bcolors.ENDC)
if (sys.argv[i]=="--lpdnn"):
print("Force Network Padding\n")
configuration['padEnsembleInput'] = 1
if (sys.argv[i]=="--3d"):
print("The network will generate 3D points instead of angles\n")
outputMode = "3d"
configuration['outputMode'] = "3d"
configuration['groupOutputs'] = 3
if (sys.argv[i]=="--halffloats"):
useHalfFloats=1
setTensorflowBackendToHalfFloats()
if (sys.argv[i]=="--from"):
print("\nCombining.. ",sys.argv[i+1],"\n");
outputDirectoryForTrainedModels = sys.argv[i+1]
if (sys.argv[i]=="--categoryall"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_all" % hierarchyPartName
outputDirectoryForTrainedModels = "step2_%s" % dataFile
startModel=0
endModel=6
print("stepAll has been reduced to a single encoder so no need to merge it we will just copy it")
#os.system('cp step0All/hip_Yrotation/model.h5 step0All/mergedModel.h5')
#os.system('cp step0All/hip_Yrotation/model.json step0All/mergedModel.json')
groundTruth = readGroundTruthFile(
configuration,
"Reference",
"%s/2d_%s.csv" % (datasetDirectory,dataFile),
"%s/%s_%s.csv" % (datasetDirectory,configuration['outputMode'],dataFile),
0,
numberOfChannelsPerNSDMElement,
0,#dont use radians
0,#dont use half floats
)
#combineAsSingleModel(outputDirectoryForTrainedModels,"hip_Yrotation",len(groundTruth['labelIn']),len(groundTruth['labelOut']),"mergedModel","all")
combineAsSingleModel(outputDirectoryForTrainedModels,"Category",len(groundTruth['labelIn']),len(groundTruth['labelOut']),"mergedModelCategory","all")
sys.exit(0)
#-----------------------------------------------
# New 4 way split
#-----------------------------------------------
if (sys.argv[i]=="--all"):
hierarchyPartName=sys.argv[i+1]
label="all"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
if (sys.argv[i]=="--back"):
hierarchyPartName=sys.argv[i+1]
label="back"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
if (sys.argv[i]=="--front"):
hierarchyPartName=sys.argv[i+1]
label="front"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
if (sys.argv[i]=="--left"):
hierarchyPartName=sys.argv[i+1]
label="left"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
if (sys.argv[i]=="--right"):
hierarchyPartName=sys.argv[i+1]
label="right"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
#Combine needs to read the decomposition files from the outputDirectoryForTrainedModels
#---------------------------------------------------------------------------------------------------
pathToDefaultDecompositionFilesFolder = configuration['doPCA'].split("/")
if (len(pathToDefaultDecompositionFilesFolder)>0):
#Resolve PCA name.. :(
x = pathToDefaultDecompositionFilesFolder[1].split("$")
if (len(x)>0):
#If there is a $ character this is our place holder to autocomplete our dataFile
print("PCA filename is resolved from ",configuration['doPCA'])
print(" to ")
configuration['doPCA']=outputDirectoryForTrainedModels+"/"+x[0]+dataFile+".pca"
print(configuration['doPCA'])
#Calculate number of channels per NSDM elements
#---------------------------------------------------------------------------------------------------
numberOfChannelsPerNSDMElement=2
if (configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
configuration['numberOfChannelsPerNSDMElement']=numberOfChannelsPerNSDMElement
#Eigenposes should be loaded before Train/Test files since they are used in the input transform step
#---------------------------------------------------------------------------------------------------
if ("eigenPoses" in configuration):
#We have eigenPoses Declared!
if (configuration['eigenPoses']==1):
#We have eigenPoses Active!
configuration['eigenPoseData'] = readGroundTruthFile(
configuration,
"Eigenposes",
"%s/2d_%s_eigenposes.csv" % (datasetDirectory,dataFile),
"%s/%s_%s_eigenposes.csv" % (datasetDirectory,configuration['outputMode'],dataFile), #configuration['outputMode'] is either bvh or 3d
1.0,
numberOfChannelsPerNSDMElement,
configuration['useRadians'],
useHalfFloats
)
#We only want headers so we ask for 0.0 memory usage which means just the labels and one record..
#groundTruth = readGroundTruthFile("Test" ,"../../DNNTracker/dataset/2d_test.csv","../../DNNTracker/dataset/bvh_test.csv",0.0,useNonCompressed,useCompressed,configuration['useRadians'],useHalfFloats)
#==============================================================================================================================
#==============================================================================================================================
#==============================================================================================================================
#The inputLabels/outputLabels are very important to create a combined network that has the
#correct outputs, there are 2 ways to load them, the old way was through the groundtruth file
#the new way is through the .list files, since neuralNetworkOutputs.list gets overwritten
#to enable quick copy of networks
#--------------------------------------------------------------------------------------------
inputLabelsNew=""; outputLabelsNew=""; inputLabelsOld=""; outputLabelsOld=""
#--------------------------------------------------------------------------------------------
from tools import checkIfFileExists,readListFromFile,convertListToLowerCase,checkIfListsAreTheSame
#--------------------------------------------------------------------------------------------
inputLabelsPath = outputDirectoryForTrainedModels+"/neuralNetworkInputs.list"
outputLabelsPath = outputDirectoryForTrainedModels+"/neuralNetworkOutputsOriginal.list"
if (checkIfFileExists(inputLabelsPath) and checkIfFileExists(outputLabelsPath) ):
print("Using labels from %s / %s..\n" % (inputLabelsPath,outputLabelsPath) )
inputLabelsNew = readListFromFile(inputLabelsPath)
outputLabelsNew = readListFromFile(outputLabelsPath)
#--------------------------------------------------------------------------------------------
#If we are using CSV backend AND ( new labels loading failed or we want to do model optimization ),
if (useCSVBackend) and ( (inputLabelsNew=="") or (outputLabelsNew=="") or ((doModelOptimization) and (trainingSamplesPercentage>0.0)) ):
groundTruth = readGroundTruthFile(
configuration,
"Reference",
"%s/2d_%s.csv" % (datasetDirectory,dataFile),
"%s/%s_%s.csv" % (datasetDirectory,configuration['outputMode'],dataFile),
trainingSamplesPercentage,
numberOfChannelsPerNSDMElement,
configuration['useRadians'],
useHalfFloats
)
inputLabelsOld = groundTruth['labelIn']
outputLabelsOld = groundTruth['labelOut']
#--------------------------------------------------------------------------------------------
#We need the labels for our input and output..!
#We used to get these from the ground truth file, however nowadays
#they also exist in the neuralNetworkInputs.list / neuralNetworkOutputs.list
#all this code exists in order to try to be backwards compatible :(
#--------------------------------------------------------------------------------------------
if (inputLabelsNew!="") and (outputLabelsNew!="") and (inputLabelsOld!="") and (outputLabelsOld!=""):
print(bcolors.OKGREEN,"We have both new and old input labels.. Selecting the new labels",bcolors.ENDC)
inputLabels = inputLabelsNew
outputLabels = outputLabelsNew
if (len(inputLabelsOld)!=len(inputLabelsNew)) or (len(outputLabelsOld)!=len(outputLabelsNew)):
print(bcolors.FAIL,"I/O labels mismatch between test label set and I/O .list files ..",bcolors.ENDC)
sys.exit(1)
if ( not checkIfListsAreTheSame(inputLabelsOld,inputLabelsNew) ):
print(bcolors.FAIL,"I/O labels mismatch between input test label set and I/O .list files ..",bcolors.ENDC)
sys.exit(1)
if ( not checkIfListsAreTheSame(outputLabelsOld,outputLabelsNew) ):
print(bcolors.FAIL,"I/O labels mismatch between output test label set and I/O .list files ..",bcolors.ENDC)
sys.exit(1)
elif (inputLabelsNew=="") and (outputLabelsNew=="") and (inputLabelsOld!="") and (outputLabelsOld!=""):
print(bcolors.OKGREEN,"We only have OLD labels from groundTruth, using them",bcolors.ENDC)
inputLabels = inputLabelsOld
outputLabels = outputLabelsOld
elif (inputLabelsNew!="") and (outputLabelsNew!="") and (inputLabelsOld=="") and (outputLabelsOld==""):
print(bcolors.OKGREEN,"We only have NEW labels from .list files, using them",bcolors.ENDC)
inputLabels = inputLabelsNew
outputLabels = outputLabelsNew
else:
print(bcolors.FAIL,"Weird combination of I/O labels, don't know what to do so stopping to avoid mistakes..",bcolors.ENDC)
sys.exit(1)
#--------------------------------------------------------------------------------------------
#==============================================================================================================================
#==============================================================================================================================
#==============================================================================================================================
numberOfOutputColumns=len(outputLabels)
#Shorthand to be able to do tricks without altering configuration
#-----------------------------------------------------------
numberOfOutputsOfEachEncoder = configuration['groupOutputs']
if (numberOfOutputsOfEachEncoder==0):
#This special case means that the encoder should span everything automatically..!
numberOfOutputsOfEachEncoder = numberOfOutputColumns #len(groundTruthTest['out'][0])
print(bcolors.WARNING + "step0_DNNTrainer.py : Setting numberOfOutputsOfEachEncoder = %u" % numberOfOutputsOfEachEncoder + bcolors.ENDC )
#--------------------------------------------------------------------------------------------
if ( len(inputLabels)==0 or len(outputLabels)==0 ):
print("I/O labels could not be parsed, we don't know what to do to combine encoders..")
sys.exit(1)
#--------------------------------------------------------------------------------------------
if (not checkIfConfigurationHierarchyIsTheSameAsLabelList(configuration,inputLabels,1)):
print("Inconsistent Configuration association compared to the inputLabelList")
sys.exit(1)
#--------------------------------------------------------------------------------------------
if ('probabilisticOutput' in configuration) and (configuration['probabilisticOutput']==1):
if (numberOfOutputsOfEachEncoder!=1):
print(bcolors.FAIL,"Overriding group outputs setting and setting it to 1!",bcolors.ENDC)
numberOfOutputsOfEachEncoder=1
#--------------------------------------------------------------------------------------------
startModel = 0 # We want to combine all labels so we start from zero..!
endModel = len(outputLabels) # We want to combine all labels so we start at label length zero..!
print("Will read from %s , start at %u and stop at %u ..\n" % (outputDirectoryForTrainedModels,startModel,endModel) )
print("Combined model will have input size of ",len(inputLabels)," and output size of ",len(outputLabels)," \n")
outputName="none"
expectedModelNames=list()
#----------------------------------------------------------------------------------------
#we take care of new potentially more complex naming scheme based on the output groupping
for outputType in range(startModel,endModel,numberOfOutputsOfEachEncoder):
#if we have multiple outputs groupped we want to concatenate all their names to keep track of all handled joints
if (numberOfOutputsOfEachEncoder==numberOfOutputColumns):
#Guard against : File name too long [Op:CreateSummaryFileWriter]
outputName="everything"
expectedModelNames.append(outputName)
elif (numberOfOutputsOfEachEncoder==1):
outputName=outputLabels[outputType]
expectedModelNames.append(outputName)
elif (numberOfOutputsOfEachEncoder>1):
outputName = ""
isFirst = 1
for nameToConcatenate in range(outputType,outputType+numberOfOutputsOfEachEncoder):
if (isFirst==0):
outputName=outputName+"-" #so that output is "3DX_hip_3DY_hip_3DZ_hip" instead of "3DX_hip3DY_hip3DZ_hip"
outputName = outputName + outputLabels[nameToConcatenate]
isFirst = 0
expectedModelNames.append(outputName)
#----------------------------------------------------------------------------------------
print("Expected model names are : ",expectedModelNames)
if (checkIfPathExists(outputDirectoryForCombinedModels)):
print("We found old combined output (%s), we will wipe it to make sure everything is clean! ",outputDirectoryForCombinedModels)
os.system('rm -rf %s/'% (outputDirectoryForCombinedModels))
os.system('mkdir %s/'% (outputDirectoryForCombinedModels))
padEnsembleInput=0
if 'padEnsembleInput' in configuration:
padEnsembleInput=int(configuration['padEnsembleInput'])
#Make a fresh merged Model
mergedModelInMemory,mergedOutputs,selectedColumns = combineModels(
configuration,
outputDirectoryForTrainedModels,
"mergedModel",
len(inputLabels),
len(outputLabels), #The outputs we get in total remain the same
expectedModelNames, # outputLabels
startModel,
len(expectedModelNames), #This is actually shrunk down from endModel,
label,
lpdnnPadding=padEnsembleInput
)
#Load fresh merged Model using its h5/json format
#no longer reloading merged
merged = mergedModelInMemory
#merged=loadModel(outputDirectoryForTrainedModels,"mergedModel")
gc.collect()
#If --optimize or --mem>0 try to optimize network
#------------------------------------------------------------------------------
if (doModelOptimization) and (trainingSamplesPercentage>0.0) and (numberOfOutputsOfEachEncoder==1) and (configuration['probabilisticOutput']==0):
print(bcolors.OKBLUE,"Doing network optimization..",bcolors.ENDC)
trainingSelectedOutput = selectOnlySpecificColumnsOfNumpyArray(groundTruth['out'],selectedColumns,useHalfFloats)
from DNNOptimize import pruneModel,clusterModel
optimized = pruneModel(merged,groundTruth['in'],trainingSelectedOutput)
#These 2 can't work together!
#optimized = clusterModel(merged,configuration,groundTruth['in'],trainingSelectedOutput)
#saveModel(outputDirectoryForTrainedModels,optimized,name="optimizedModel") <- RuntimeError: Unable to create link (name already exists) on clustering
#from DNNOptimize import quantizeModel
#Quantizing a tf.keras Model inside another tf.keras Model is not supported.
#optimized = quantizeModel(merged,groundTruth['in'],trainingSelectedOutput)
#saveModel(outputDirectoryForTrainedModels,optimized,name="optimizedQuantizedModel")
print("Overriding model with optimized version!")
merged=optimized
else:
print("To also optimize model please supply --optimize ( OR --mem VALUE with a value >0 )")
#------------------------------------------------------------------------------
print(bcolors.OKBLUE,"Saving Combined model to ",outputDirectoryForCombinedModels,"..",bcolors.ENDC)
startAt = time.time()
merged.save(outputDirectoryForCombinedModels, save_format='tf') # <- Actually Save Neural Network to File
endAt = time.time()
print(bcolors.OKGREEN,"Save operation took %0.2f mins "%((endAt-startAt)/60),bcolors.ENDC)
#We will also copy with it the two I/O lists to make our lifes easier
print(bcolors.OKBLUE,"Handle configuration files..",bcolors.ENDC)
#---------------------------------------------------------------------------------------------------------------------
os.system('cp %s/*.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/summary.html %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputMinima.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputMaxima.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputScalars.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputScalarsFraction.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputOffsets.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/neuralNetworkJoints.list %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/neuralNetworkInputs.list %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
#---------------------------------------------------------------------------------------------------------------------
configFileStandaloneName = os.path.basename(configurationPath)
os.system('cp %s/%s %s/' % (outputDirectoryForTrainedModels,configFileStandaloneName,outputDirectoryForCombinedModels))
#PLEASE KEEP IN MIND THAT THE BASH SCRIPTS ALSO DO THEIR OWN COPIES SO THIS IS
#IS CURRENTLY WAY MORE COMPLICATED THAT IT NEEDS TO..!
#Initially the idea was to directly grab the .pca file from the dataset/ dir however nowadays things are more complex
#os.system('cp %s/%s %s/' % (outputDirectoryForTrainedModels,pcaFileStandaloneName,outputDirectoryForCombinedModels))
#We will now copy *ALL* files hoping to cover everything!
pcaFileStandaloneName = os.path.basename(configuration['doPCA'])
os.system('cp %s/%s %s/' % (outputDirectoryForTrainedModels,pcaFileStandaloneName,outputDirectoryForCombinedModels))
os.system('cp %s/%s* %s/' % (outputDirectoryForTrainedModels,pcaFileStandaloneName,outputDirectoryForCombinedModels))
if (numberOfOutputsOfEachEncoder!=numberOfOutputColumns):
#Write culled list ..!
print("Overwriting neuralNetworkOutputs.list with culled output list")
dumpListToFile(outputDirectoryForCombinedModels+"/neuralNetworkOutputs.list" ,mergedOutputs)
else:
print("We are targeting everything at once so not copying instead of overwriting neuralNetworkOutputs.list with culled output list")
os.system('cp %s/neuralNetworkOutputs.list %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
if (numberOfOutputsOfEachEncoder==numberOfOutputColumns):
print("We won't mess around with outputs..") #Case when everything is selected at once..
elif (numberOfOutputsOfEachEncoder>1):
os.system('cp %s %s' % (outputDirectoryForCombinedModels+"/neuralNetworkOutputs.list",outputDirectoryForCombinedModels+"/neuralNetworkOutputsOriginal.list"))
from tools import splitTextBasedOnGroupNumber
splitTextBasedOnGroupNumber(numberOfOutputsOfEachEncoder,outputDirectoryForCombinedModels+"/neuralNetworkOutputsOriginal.list",outputDirectoryForCombinedModels+"/neuralNetworkOutputs.list")
#My PC doesn't have enough RAM for this..
#print(bcolors.OKBLUE,"Also Creating a TensorRT Model..",bcolors.ENDC)
#-----------------------------------------------------------------
#from DNNOptimize import convertToTensorRT
#convertToTensorRT(merged,precision="fp16")
#merged.save(outputDirectoryForCombinedModels+"/trt_fp16", save_format='tf') #save directory..
#convertToTensorRT(merged,precision="fp32")
#merged.save(outputDirectoryForCombinedModels+"/trt_fp32", save_format='tf') #save directory..
#-----------------------------------------------------------------
# Try to do validation
#-----------------------------------------------------------------------------------------------------------------
if (doModelValidation) and (trainingSamplesPercentage>0.0) and (numberOfOutputsOfEachEncoder==1):
doCombinedModelValidation(outputDirectoryForCombinedModels,groundTruth,merged)
#-----------------------------------------------------------------------------------------------------------------
RAM = getRAMInformation()
if (RAM["free"]<2000000):
print(bcolors.FAIL,"We do not have enough memory (we have ",RAM["free"],") to generate a TF-Lite model..",bcolors.ENDC)
print(" Please manually run : ",bcolors.OKGREEN," tflite_convert --saved_model_dir=%s --output_file=%s/model.tflite"% (outputDirectoryForCombinedModels,outputDirectoryForCombinedModels),bcolors.ENDC)
else:
print(bcolors.OKBLUE,"Also Creating a TF-Lite Model..",bcolors.ENDC)
gc.collect()
#------------------------------------------------------------------------------
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir=outputDirectoryForCombinedModels)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
if (doModelOptimization) and (trainingSamplesPercentage>0.0):
#If we gave a training sample set then we can enable post training quantization on TFLite
#converter.representative_dataset = groundTruth['in']
#converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
#converter.target_spec.supported_types = [tf.int8]
#converter.inference_input_type = tf.float32 # tf.int8 # or tf.uint8
#converter.inference_output_type = tf.float32 # tf.int8 # or tf.uint8
pass
tflite_model = converter.convert()
with open('%s/model.tflite' % outputDirectoryForCombinedModels, 'wb') as f:
f.write(tflite_model)
#------------------------------------------------------------------------------
#tf2onnx hogs a lot of memory, we will not use any inputs after this point
del groundTruth
gc.collect()
#Show signatures..
#https://www.tensorflow.org/guide/saved_model#the_savedmodel_format_on_disk
print(bcolors.OKBLUE,"Double-check tensorflow model signatures..",bcolors.ENDC)
os.system('saved_model_cli show --dir %s/ --tag_set serve --signature_def serving_default' % (outputDirectoryForCombinedModels))
#--------------------------------------------------------------------------------------------------------------------------------------
RAM = getRAMInformation()
if (RAM["free"]<2000000):
print(bcolors.FAIL,"We do not have enough memory (we have ",RAM["free"],") to generate an ONNX model..",bcolors.ENDC)
print(" Please manually run : ",bcolors.OKGREEN," python3 -m tf2onnx.convert --saved-model %s --opset 17 --tag serve --output %s/model.onnx " % (outputDirectoryForCombinedModels,outputDirectoryForCombinedModels),bcolors.ENDC)
print("See : https://onnxruntime.ai/docs/reference/compatibility.html for the best OPSET")
else:
print(" Please manually run : ",bcolors.OKGREEN," python3 -m tf2onnx.convert --saved-model %s --opset 17 --tag serve --output %s/model.onnx " % (outputDirectoryForCombinedModels,outputDirectoryForCombinedModels),bcolors.ENDC)
#This gets the main python script killed for some reason on cvrldemo..
#print(bcolors.OKBLUE,"Also Creating an ONNX Model..",bcolors.ENDC) #assuming python3 -m pip install tf2onnx
#--------------------------------------------------------------------------------------------------------------------------------------
#os.system("python3 -m tf2onnx.convert --saved-model %s --opset 14 --tag serve --output %s/model.onnx " % (outputDirectoryForCombinedModels,outputDirectoryForCombinedModels))
#--------------------------------------------------------------------------------------------------------------------------------------
notification("MocapNET Network Compilation","Done merging %s "%(outputDirectoryForCombinedModels))
print("To view training run : ",bcolors.OKGREEN," tensorboard --logdir %s/tensorboard/ --bind_all" % (outputDirectoryForTrainedModels),bcolors.ENDC)
print(bcolors.OKGREEN,"Done merging",bcolors.ENDC)
sys.exit(0)
if __name__ == '__main__':
useCSVBackend=1
emptyTrainData=dict()
step1_DNNCombine(useCSVBackend,emptyTrainData)
+739
View File
@@ -0,0 +1,739 @@
#!/usr/bin/python3
import os
import sys
import numpy as np
from numba import njit #Test
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
"""
Convert seconds to Hertz
"""
def secondsToHz(seconds):
if (seconds==0.0):
seconds=1.0
return float(1 / seconds)
@njit
def optimizedStD(data,mean,N):
#JiT compilation of this in place loop to speed it up
M2 = np.float32(0.0)
for row in data:
for x in row:
delta = x - mean
M2 += delta**2
return np.sqrt(M2 / N)
def calculateStandardDeviationInPlaceKnowingMean(data,mean):
N = data.shape[0] * data.shape[1]
if (N==0):
return np.NAN
#----------------------------------
return optimizedStD(data,np.float32(mean),N)
#----------------------------------
#M2 = 0.0
#for row in data:
# for x in row:
# delta = x - mean
# M2 += delta**2
#return np.sqrt(M2 / N)
def convertStandardDeviationToVariance(std):
return std ** 2
"""
This is a VERY commonly needed conversion, MocapNET is trained on a 1920x1080 frame to match popular cameras,
many image sources/sensors produce different kinds of image resolutions. The aspect ratio is very important
for good results, this function does the needed conversion..
"""
def transform_coordinate_wrt_target(x, y, width, height, targetWidth = 1920, targetHeight = 1080):
aspect_ratio = width / height
if aspect_ratio > targetWidth / targetHeight:
# The image is wider than the frame
scaled_width = targetWidth
scaled_height = int(targetWidth / aspect_ratio)
offset_x = 0
offset_y = (targetHeight - scaled_height) // 2
else:
# The image is taller than the frame
scaled_width = int(targetHeight * aspect_ratio)
scaled_height = targetHeight
offset_x = (targetWidth - scaled_width) // 2
offset_y = 0
new_x = (x / width) * scaled_width + offset_x
new_y = (y / height) * scaled_height + offset_y
return new_x, new_y
def img_resizeWithPadding(img,targetWidth,targetHeight):
import cv2
width = targetWidth
height = targetHeight
h, w = img.shape[:2]
pad_bottom, pad_right = 0, 0
ratio = w / h
if h > height or w > width:
# shrinking image algorithm
interp = cv2.INTER_AREA
else:
# stretching image algorithm
interp = cv2.INTER_CUBIC
w = width
h = round(w / ratio)
if h > height:
h = height
w = round(h * ratio)
pad_top = int(abs(height - h)/2)
pad_bottom = int(abs(height - h)/2)
pad_left = int(abs(width - w)/2)
pad_right = int(abs(width - w)/2)
scaled_img = cv2.resize(img, (w, h), interpolation=interp)
padded_img = cv2.copyMakeBorder(scaled_img,pad_top,pad_bottom,pad_left,pad_right,borderType=cv2.BORDER_CONSTANT,value=[0,0,0])
return padded_img
def img_resizeWithCrop(img, targetWidth,targetHeight):
import cv2
import numpy as np
interpolation=cv2.INTER_AREA
h, w = img.shape[:2]
min_size = np.amin([h,w])
# Centralize and crop
crop_img = img[int(h/2-min_size/2):int(h/2+min_size/2), int(w/2-min_size/2):int(w/2+min_size/2)]
resized = cv2.resize(crop_img, (targetWidth,targetHeight), interpolation=interpolation)
return resized
def normalizedCoordinatesAdaptForVerticalImage(sourceWidth,sourceHeight,targetWidth,targetHeight,nX,nY):
import numpy as np
h = sourceHeight
w = sourceWidth
min_size = np.amin([h,w])
nY = int(h/2-min_size/2) + int(nY*min_size)
nX = int(w/2-min_size/2) + int(nX*min_size)
return float(nX/sourceWidth),float(nY/sourceHeight)
def normalizedCoordinatesAdaptToResizedCrop(sourceWidth,sourceHeight,trainingWidth,trainingHeight,nX,nY):
if (sourceHeight>sourceWidth):
print("PoseNET.py normalizedCoordinatesAdaptToResizedCrop: FIX VERTICAL IMAGE")
import numpy as np
return nX,nY
"""
Split joint names based on configuration
"""
def splitTextBasedOnGroupNumber(groupNumber,sourceFile,targetFile):
import sys
#This function used to be this one liner..
#However some joints have additional '-' characters e.g. 3DZ_toe1-2.r so this whole next codeblock
#attempts to properly split them
#import os
#os.system('cat %s | sed \'s/-/\\n/g\' > %s' % (sourceFile,targetFile))
#return
#--------------------------------------------------------------------------------------------------------
if (groupNumber==0):
print(bcolors.FAIL," Cant split to ",groupNumber," groups ",bcolors.ENDC)
sys.exit(1)
#--------------------------------------------------------------------------------------------------------
fileR = open(sourceFile, 'r')
fileW = open(targetFile, 'w')
#--------------------------------------------------------------------------------------------------------
Lines = fileR.readlines()
for line in Lines:
lineNoNL = line.strip()
split = lineNoNL.split('-')
standaloneJoints = list()
if (lineNoNL!=""):
if (len(split)==groupNumber):
for joint in split:
standaloneJoints.append(joint)
elif (len(split)<groupNumber):
print(bcolors.FAIL," Could not split text `",lineNoNL,"` to ",groupNumber," groups (only got ",len(split),") ",bcolors.ENDC)
sys.exit(1)
else:
#Weird case
count = 0
increments = int(len(split) / groupNumber)
for jointNumber in range(0,groupNumber):
collectedJointName = split[count]
count = count + 1
for jointIncrement in range(1,increments):
collectedJointName = collectedJointName + '-' + split[count]
count = count + 1
standaloneJoints.append(collectedJointName)
for sJoint in standaloneJoints:
fileW.write(sJoint)
fileW.write("\n")
else:
print("Empty line skipped\n")
#--------------------------------------------------------------------------------------------------------
fileR.close()
fileW.close()
#--------------------------------------------------------------------------------------------------------
"""
Capitalize 3D X,Y,Z coordinate tags e.g. 3dx_tag -> 3DX_tag
"""
def capitalizeCoordinateTags(inputs):
out = dict()
keysList = list(inputs.keys())
for key in keysList:
keyOriginal = key
keyNew = ""
convert = False
tagList = key.split('_')
tag = tagList[0]
if (tag=="3dx"):
convert = True
keyNew="3DX_"+key[4:]
if (tag=="3dy"):
convert = True
keyNew="3DY_"+key[4:]
if (tag=="3dz"):
convert = True
keyNew="3DZ_"+key[4:]
if (convert):
#print("Convert ",keyOriginal," to ",keyNew)
out[keyNew]=inputs[keyOriginal]
else:
out[keyOriginal]=inputs[keyOriginal]
return out
"""
Model names will cause errors if they contain invalid characters, so we make sure everything
is named in accordance with tensorflow rules
"""
def tensorflowFriendlyModelName(rawName):
#Avoiding "Tensorflow %s is not valid scope name error" when creating a model
#'-', '\', '/', or '_'
filteredName = rawName
filteredName = filteredName.replace("-", ".")
filteredName = filteredName.replace("_", ".")
filteredName = filteredName.replace("/", ".")
filteredName = filteredName.replace("\\", ".")
return filteredName
"""
Send a system notification that will travel to all connected devices
"""
def notification(title,message):
#This needs a more proper sanitization!
title = title.strip("\"'")
message = message.strip("\"'")
try:
os.system('notify-send -a \"%s\" \"%s\"&' % (title,message))
except:
print("NOTIFICATION : ",title,message)
"""
Bytes to KB/MB/GB/TB converter
"""
def convert_bytes(num):
"""
this function will convert bytes to MB.... GB... etc
"""
step_unit = 1000.0 #1024 bad the size
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
if num < step_unit:
return "%3.1f %s" % (num, x)
num /= step_unit
"""
Retreive the available system RAM
"""
def getRAMInformation():
"""
Get node total memory and memory usage
"""
with open('/proc/meminfo', 'r') as mem:
ret = {}
tmp = 0
for i in mem:
sline = i.split()
if str(sline[0]) == 'MemTotal:':
ret['total'] = int(sline[1])
elif str(sline[0]) in ('MemFree:', 'Buffers:', 'Cached:'):
tmp += int(sline[1])
ret['free'] = int(tmp)
ret['used'] = int(ret['total']) - int(ret['free'])
return ret
"""
Count the number of lines by parsing the file inside python
"""
def getNumberOfLines(filename):
#import socket
#print("Hostname is ",socket.gethostname())
#if (socket.gethostname()=="ammar-kriti"):
# print(bcolors.FAIL,"RETURNING FIXED NUMBER OF LINES FOR SPEED IN MY SLOW PC",bcolors.ENDC)
# return 3858095
print("Counting number of lines in file ",filename)
with open(filename) as f:
return sum(1 for line in f)
"""
Count the number of lines by asking the shell/OS to do it using wc -l
"""
def getNumberOfLinesOS(filename):
#import socket
#print("Hostname is ",socket.gethostname())
#if (socket.gethostname()=="ammar-kriti"):
# print(bcolors.FAIL,"RETURNING FIXED NUMBER OF LINES FOR SPEED IN MY SLOW PC",bcolors.ENDC)
# return 3858095
print("Counting number of lines in file ",filename)
import subprocess
#Standard but more compatible
command = ('wc -l %s' % filename)
p = subprocess.Popen(command, universal_newlines=True,shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
text = p.stdout.read()
retcode = p.wait()
out = text.split( )
print("It was ",out[0])
return int(out[0])
"""
Check version against master server
"""
def checkVersion(MOCAPNET_VERSION):
import socket
os.system("wget -qO- \"http://ammar.gr/mocapnet/version/index.php?h=%s&v=%s\"&"%(socket.gethostname(),MOCAPNET_VERSION))
#http://ammar.gr/mocapnet/version/index.php?h=elina-kriti&v=4.0
"""
Check the number of times a specific keyword *pattern* appears inside the file with the given filename
"""
def getNumberOfOccurancesOS(filename,keyword):
print("Counting number of occurances of ",keyword," in file ",filename)
import subprocess
#Standard but more compatible
command = ('cat %s grep -o %s | wc -l' % (filename,keyword))
p = subprocess.Popen(command, universal_newlines=True,shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
text = p.stdout.read()
retcode = p.wait()
out = text.split()
print("It was ",out[0])
return int(out[0])
"""
Get the size of a file in disk
"""
def getFileSizeInKB(filename):
return int( os.path.getsize(filename)/1024 )
"""
Convert list to lowercase
"""
def convertListToLowerCase(theList):
lowercaseList = [item.lower() for item in theList]
return lowercaseList
"""
Dump a list to a file
"""
def dumpListToFile(filename,theList):
file=open(filename,'w')
for items in theList:
file.writelines(items+'\n')
file.close()
"""
Read a list from a file
"""
def readListFromFile(filename):
file=open(filename,'r')
Lines = file.readlines()
res = []
for x in Lines:
res.append(x.replace("\n", ""))
file.close()
print("List : ",filename," has ",len(res)," elements")
return res
"""
Dump a labeled mini CSV ( 2 rows ) to a file
"""
def dumpMiniCSVToFile(filename,theLabels,theValues,columns):
#Write CSV outputOffsets.csv
f = open(filename, 'w')
#------------------------------------------------------------------------
for column in range(columns):
if (column>0):
f.write(',')
f.write("%s"%(theLabels[column]))
f.write('\n')
#------------------------------------------------------------------------
for column in range(columns):
if (column>0):
f.write(',')
f.write("%f"%(theValues[column]))
f.write('\n')
#------------------------------------------------------------------------
f.close()
"""
Append a labeled CSV to a file
"""
def appendCSVToFile(filename,theValues,fID=0):
if (fID==0):
f = open(filename, 'w')
#------------------------------------------------------------------------
for column in range(len(theValues)):
if (column>0):
f.write(',')
f.write("label%u"%(column))
f.write('\n')
f.close()
#------------------------------------------------------------------------
#------------------------------------------------------------------------
f = open(filename, 'a')
#------------------------------------------------------------------------
for column in range(len(theValues)):
if (column>0):
f.write(',')
f.write("%f"%(theValues[column]))
f.write('\n')
#------------------------------------------------------------------------
f.close()
def saveCSVFileFromListOfDicts(filename,inputDicts):
labels = list()
#--------------------------
for frame in inputDicts:
for label in frame.keys():
if not label in labels:
labels.append(label)
#--------------------------
f = open(filename, 'w')
#Write header..
#------------------------------------------------------------------------
for column in range(len(labels)):
if (column>0):
f.write(',')
f.write("%s"%(labels[column]))
f.write('\n')
#------------------------------------------------------------------------
#Write body..
#------------------------------------------------------------------------
for frame in inputDicts:
for column in range(len(labels)):
if (column>0):
f.write(',')
if (labels[column] in frame):
f.write("%f"%(frame[labels[column]]))
else:
f.write("0")
f.write('\n')
#------------------------------------------------------------------------
f.close()
"""
Given a /path/to/a/specific/file.ext remove file.ext and return the base path
"""
def getDirectoryFromPath(path):
return os.path.dirname(path)
"""
Given a /path/to/a/specific/file.ext remove /path/to/a/specific/ and return file.ext
"""
def getFileFromPath(path):
return os.path.basename(path)
"""
Create a new directory if it does not exist
"""
def createDirectory(path):
if not os.path.exists(path):
os.makedirs(path)
"""
Check if a file exists
"""
def checkIfFileExists(filename):
return os.path.isfile(filename)
"""
Check if a path exists
"""
def checkIfPathExists(filename):
return os.path.exists(filename)
"""
Check if a path exists
"""
def checkIfPathIsDirectory(filename):
return os.path.isdir(filename)
"""
Check if an entry is part of a given list
"""
def checkIfEntryIsInList(theList,theEntry):
for listItem in theList:
if(theEntry==listItem): return 1
return 0
"""
Check if an entry is part of a given list
"""
def checkIfListsAreTheSame(theListA,theListB):
#----------------------------------------------
if (len(theListA)!=len(theListB)):
return 0
#----------------------------------------------
if (len(theListA)==0) and (len(theListB)==0):
return 1
#----------------------------------------------
for i in range(len(theListA)):
if theListA[i]!=theListB[i]:
return 0
#----------------------------------------------
return 1
def parseSerialNumberFromSummary(html_path):
import re
content = ""
with open(html_path, 'r', encoding='utf-8') as html_file:
content = html_file.read()
# Regular expression pattern to match the serial number
pattern = r'<td>Description<\/td>\s*<\/tr>\s*<tr>\s*<td>\s*([A-Za-z0-9]+)'
# Search for the pattern in the HTML content
match = re.search(pattern, content, re.DOTALL)
if match:
serial_number = match.group(1)
return serial_number
return "?"
def filterListOfStringsByRegex(string_list, regex_pattern):
import re
#Usage :
#input_list = ["apple", "banana", "cherry", "date", "elderberry"]
#pattern = r"^[a-c].*" # Matches strings starting with letters a, b, or c
#result = filterListOfStringsByRegex(input_list, pattern)
matched_strings = []
for string in string_list:
if re.match(regex_pattern, string):
matched_strings.append(string)
return matched_strings
def convertListOfRegexToListOfLists(master_string_list,regex_list):
string_list_output = []
for regex_pattern in regex_list:
string_list_output.append(filterListOfStringsByRegex(master_string_list,regex_pattern))
return string_list_output
"""
Check if an entry is part of a given list
"""
def getEntryIndexInList(theList,theEntry):
i=0
for listItem in theList:
if(theEntry.lower()==listItem.lower()):
return i
i=i+1
return -1
"""
Check if an entry is in a sublist of our configuration
"""
def checkIfEntryIsInConfigurationKey(configuration,theKey,theEntry):
for listItem in configuration[theKey]:
if(theEntry==listItem): return 1
return 0
"""
Check if a joint is declared in the configuration hierarchy
"""
def getConfigurationJointIsDeclaredInHierarchy(configuration,theEntry):
#-------------------------------------------------------------------------------------------
if (theEntry=="everything"):
print(bcolors.WARNING,"EVERYTHING.. is declared always.. ",bcolors.ENDC)
return 1
#-------------------------------------------------------------------------------------------
try:
out = theEntry.split('_')
theEntry=out[0]
except:
print("getConfigurationJointIsDeclaredInHierarchy could not split ",theEntry)
#-------------------------------------------------------------------------------------------
if 'banned' in configuration:
for listItem in configuration['banned']:
if(theEntry.lower()==listItem['output'].lower()):
print(bcolors.WARNING," Joint ",theEntry," is declared in banlist! ",bcolors.ENDC)
return 1
if 'hierarchy' in configuration:
for listItem in configuration['hierarchy']:
#print("Check ",theEntry," vs ",listItem['joint'])
if(theEntry.lower()==listItem['joint'].lower()):
print("The Joint ",theEntry," is : declared in hierarchy")
return 1
print("Joint is not declared in hierarchy..")
#-------------------------------------------------------------------------------------------
return 0
"""
Retrieve the configuration joint priority of a joint is declared in the configuration hierarchy
"""
def getConfigurationJointPriority(configuration,theEntry):
#-------------------------------------------------------------------------------------------
if (theEntry=="everything"):
print("EVERYTHING.. has a high priority always.. ")
return 1
#-------------------------------------------------------------------------------------------
try:
out = theEntry.split('_')
theEntry=out[0]
except:
print("getConfigurationJointPriority could not split ",theEntry)
#-------------------------------------------------------------------------------------------
if 'outputMode' in configuration:
if (configuration['outputMode'] == "3d"):
print(bcolors.WARNING,"We treat all joints as terribly important in 3D point mode!",bcolors.ENDC)
return 1
if 'banned' in configuration:
for listItem in configuration['banned']:
if(theEntry==listItem['output']):
print(bcolors.WARNING," Joint ",theEntry," is in banlist! ",bcolors.ENDC)
return 0
if 'hierarchy' in configuration:
for listItem in configuration['hierarchy']:
if(theEntry==listItem['joint']):
print("The Importance of Joint ",theEntry," is : ",listItem['importance'])
return listItem['importance']
print("The Importance of Joint ",theEntry," is : 0 ")
#-------------------------------------------------------------------------------------------
return 0
"""
Get the parent network from our configuration joint hierarchy
"""
def getParentNetwork(configuration,theEntry):
#-------------------------------------------------------------------------------------------
if (theEntry=="everything"):
print("EVERYTHING.. has no parent.. ")
return "none"
#-------------------------------------------------------------------------------------------
try:
out = theEntry.split('_')
theJoint=out[0]
theChannel=out[1]
except:
print("getParentNetwork could not split ",theEntry)
theJoint=theEntry
theChannel=0
#-------------------------------------------------------------------------------------------
print("Checking the parent of Joint(",theJoint,")/Channel(",theChannel,")")
for listItem in configuration['hierarchy']:
if(theJoint==listItem['joint']):
if (listItem['inheritNetwork']=="none"):
return "none"
parentNetwork="%s_%s" % (listItem['inheritNetwork'],theChannel)
if (parentNetwork==theEntry):
return "none"
else:
return parentNetwork
#-------------------------------------------------------------------------------------------
return "none"
if __name__ == '__main__':
print("Tools.py is a library!")
splitTextBasedOnGroupNumber(3,"tmp.tmp","tmpF.tmp")
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/python3
import numpy as np
import csv
import gc
import time
import array
import sys
def writeCSVFileHeader(filenameOutput,inputListLabels,inputStart,inputEnd):
inputNumber=0
fileCSV = open(filenameOutput,"w")
for entry in inputListLabels[inputStart:inputEnd]:
#if (inputNumber>=inputStart) and (inputNumber<inputEnd):
fileCSV.write(str(entry))
fileCSV.write(",")
#++inputNumber
fileCSV.write("\n")
fileCSV.close()
def writeCSVFileBody(filenameOutput,inputList,inputStart,inputEnd):
inputNumber=0
fileCSV = open(filenameOutput,"a")
for entry in inputList[inputStart:inputEnd]:
#if (inputNumber>=inputStart) and (inputNumber<inputEnd):
fileCSV.write(str(entry))
fileCSV.write(",")
#++inputNumber
fileCSV.write("\n")
fileCSV.close()
+285
View File
@@ -0,0 +1,285 @@
from __future__ import print_function, unicode_literals
import tensorflow as tf
import numpy as np
from data.BinaryDbReader import *
from data.BinaryDbReaderSTB import *
from utils.general import EvalUtil, get_stb_ref_curves, calc_auc, np2pyt, pyt2np
import torch
import torch.nn as nn
from torch.autograd import Variable
import sys
import os
import cv2 as cv
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
device=torch.device("cpu")
def writeCSVFileHeader(filenameOutput,inputListLabels,inputStart,inputEnd,channels):
inputNumber=0
fileCSV = open(filenameOutput,"w")
for entry in inputListLabels[inputStart:inputEnd*channels]:
#if (inputNumber>=inputStart) and (inputNumber<inputEnd):
fileCSV.write(str(entry))
fileCSV.write(",")
#++inputNumber
fileCSV.write("\n")
fileCSV.close()
def writeCSVFileBody(filenameOutput,inputList,inputStart,inputEnd,channels):
inputNumber=0
fileCSV = open(filenameOutput,"a")
for entry in inputList[inputStart:inputEnd]:
if (channels==1):
fileCSV.write(str(entry))
fileCSV.write(",")
else:
for ch in entry:
#if (inputNumber>=inputStart) and (inputNumber<inputEnd):
fileCSV.write(str(ch))
fileCSV.write(",")
#++inputNumber
fileCSV.write("\n")
fileCSV.close()
labelsHandSide=list()
labelsHandSide.append("left")
labelsHandSide.append("right")
writeCSVFileHeader("handSide.csv",labelsHandSide,0,2,1)
labels3D=list()
for i in range (0,22):
labels3D.append("3DX_%u" % i)
labels3D.append("3DY_%u" % i)
labels3D.append("3DZ_%u" % i)
#writeCSVFileHeader("dumped3D.csv",labels3D,0,21,3)
writeCSVFileHeader("ground3D.csv",labels3D,0,21,3)
labels2D=list()
for i in range (0,22):
labels2D.append("2DX_%u" % i)
labels2D.append("2DY_%u" % i)
writeCSVFileHeader("ground2D.csv",labels2D,0,21,2)
labels1D=list()
for i in range (0,22):
labels1D.append("visible_%u" % i)
writeCSVFileHeader("visibility.csv",labels1D,0,21,1)
os.system("rm images/*.png")
plt.ion()
# Experimental settings
hand_side_invariance = True
scale_invariance = True
dataset_name = 'RHD' #STB
# Only change this if you have moved the dataset to a different folder
path_to_db = 'data/'
# Load the correct model depending on the experiment
model_name = 'model_'
if scale_invariance and hand_side_invariance:
if dataset_name == 'RHD':
model_name += 'allInvar'
elif dataset_name == 'STB':
model_name += 'allInvar_RGB2RGB'
elif scale_invariance and not hand_side_invariance:
model_name += 'noHandInvar_scaleInvar'
elif not scale_invariance and hand_side_invariance:
model_name += 'handInvar_noScaleInvar'
else:
model_name += 'noHandInvar_noScaleInvar'
model_path = os.path.join('models', model_name)
sys.path.append(os.path.join(model_path, 'source_files'))
from models import *
# Create the experiment folder
try:
os.makedirs(model_path + '/eval_results')
except:
pass
# Load the selected dataset
if dataset_name == 'RHD':
path_to_db = os.path.join(path_to_db, 'bin/')
dataset = BinaryDbReader(shuffle=False, use_wrist_coord=False, hand_crop=True,path_to_db=path_to_db)
elif dataset_name == 'STB':
path_to_db = os.path.join(path_to_db, 'stb/')
dataset = BinaryDbReaderSTB(shuffle=False, use_wrist_coord=False, hand_crop=True,path_to_db=path_to_db)
else:
raise Exception("Unknown dataset")
# Build dataset
data = dataset.get()
# Build model
n_joints = 21
z_dim = 30
end_size = (256, 256)
# get keys as list
keys = list(data.keys())
#print keys
print(keys)
# RGB
rgb_enc = resnet18(z_dim, hand_side_invariance)
rgb_dec = rgb_decoder(z_dim)
VAE_RGB = VAE(z_dim, rgb_enc, rgb_dec)
#VAE_RGB.cuda()
VAE_RGB.eval()
# 3D
joint_3D_enc = joints_encoder(z_dim, [n_joints, 3])
joint_3D_dec = joints_decoder(z_dim, [n_joints, 3])
VAE_3D = VAE(z_dim, joint_3D_enc, joint_3D_dec)
#VAE_3D.cuda()
VAE_3D.eval()
# Load params for own models
checkpoint = torch.load(model_path + '/model_weights.pth')
VAE_RGB.load_state_dict(checkpoint['state_dict_VAERGB'])
VAE_3D.load_state_dict(checkpoint['state_dict_VAE3D'])
# Start TF
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.7)
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
tf.train.start_queue_runners(sess=sess)
colorlist_pred = ['#660000', '#b30000', '#ff0000', '#ff4d4d', '#ff9999']
colorlist_gt = ['#000066', '#0000b3', '#0000ff', '#4d4dff', '#9999ff']
# Plots all 5 fingers
def plot_fingers(points, plt_specs, c, ax):
for i in range(5):
start, end = i*4+1, (i+1)*4+1
to_plot = np.concatenate((points[start:end], points[0:1]), axis=0)
ax.plot(to_plot[:,0], to_plot[:,1], to_plot[:,2], plt_specs, color=c[i])
fig = None
#util_vae = EvalUtil()
# iterate dataset
for i in range(dataset.num_samples):
# Get required data
keypoint_xyz21, keypoint_vis21, keypoint_scale, img_crop, hand_side = sess.run([data['keypoint_xyz21'], data['keypoint_vis21'], data['keypoint_scale'], data['image_crop'], data['hand_side']])
keypoint_xyz21 = np.squeeze(keypoint_xyz21)
keypoint_vis21 = np.squeeze(keypoint_vis21)
keypoint_scale = np.squeeze(keypoint_scale)
img_crop = np.squeeze(img_crop)
#print(i," side ",hand_side)
writeCSVFileBody("handSide.csv",hand_side[0],0,2,1)
# Get VAE prediction
#img_res = cv.resize(img_crop, end_size)
#img_pyt = img_res.transpose(2, 0, 1).reshape((1, 3, end_size[0], end_size[1]))
#img_crop_var = Variable(np2pyt(img_pyt), volatile=True).cuda()
#if hand_side_invariance:
# hand_side_var = Variable(np2pyt(hand_side), volatile=True).cuda()
#else:
# hand_side_var = None
#coords_3D, _, _ = VAE_RGB(img_crop_var, VAE_3D, hand_side_var)
#coords_3D_np = np.squeeze(pyt2np(coords_3D))
# rescale to meters
#if scale_invariance:
# coords_3D_np *= keypoint_scale
# center gt
keypoint_xyz21 -= keypoint_xyz21[0, :]
#print(coords_3D_np)
#writeCSVFileBody("dumped3D.csv",coords_3D_np,0,22,3)
#------------------------------------------------
writeCSVFileBody("ground3D.csv",keypoint_xyz21,0,22,3)
writeCSVFileBody("visibility.csv",keypoint_vis21,0,22,1)
#Dump Images
plt.imsave("images/im%u.png"%i, img_crop+ 0.5)
#sys.exit(0)
# Feed it to the evaluater
#util_vae.feed(keypoint_xyz21, keypoint_vis21, coords_3D_np)
if (i % 100) == 0:
print('%d / %d images done: %.3f percent' % (i, dataset.num_samples, i*100.0/dataset.num_samples))
if not fig:
# visualize
fig = plt.figure(figsize=(15,10))
ax1 = fig.add_subplot(131)
ax2 = fig.add_subplot(132, projection='3d')
ax3 = fig.add_subplot(133, projection='3d')
ax1.clear()
ax2.clear()
ax3.clear()
# Plot the entire image plus the transformed 2D prediction
ax1.imshow(img_crop + 0.5)
ax1.set_title("Raw image")
ax1.axis('off')
# Plot the ground truth and the predictions
plot_fingers(keypoint_xyz21, '.-', colorlist_gt, ax2)
ax2.view_init(azim=-90.0, elev=-90.0)
ax2.set_title("Ground truth")
#plot_fingers(coords_3D_np, '.-', colorlist_pred, ax3)
ax3.view_init(azim=-90.0, elev=-90.0)
ax3.set_title(model_name)
ax2.set_xlim([-0.1, 0.1])
ax2.set_ylim([-0.1, 0.1])
ax2.set_zlim([-0.1, 0.1])
#ax2.set_aspect('equal')
ax2.set_xticklabels([])
ax2.set_yticklabels([])
ax2.set_zticklabels([])
ax3.set_xlim([-0.1, 0.1])
ax3.set_ylim([-0.1, 0.1])
ax3.set_zlim([-0.1, 0.1])
#ax3.set_aspect('equal')
ax3.set_xticklabels([])
ax3.set_yticklabels([])
ax3.set_zticklabels([])
plt.tight_layout()
plt.show()
plt.pause(0.001)
#plt.savefig(model_path + "/eval_results/prediction_RgbTo3D_" + dataset_name + "%05d" % i)
# Output results
mean, median, auc, pck_curve_all, threshs = util_vae.get_measures(0.0, 0.050, 20)
print('Evaluation results:')
print('Average mean EPE: %.3f mm' % (mean*1000))
print('Average median EPE: %.3f mm' % (median*1000))
print('Area under curve: %.3f' % auc)
pck_curve_all, threshs = pck_curve_all[8:], threshs[8:]*1000.0
auc_subset = calc_auc(threshs, pck_curve_all)
print('Area under curve between 20mm - 50mm: %.3f' % auc_subset)
curve_list = []
curve_list.append((threshs, pck_curve_all, model_name + ' (AUC=%.3f)' % auc_subset))
if type(dataset) == BinaryDbReaderSTB:
curve_list.extend(get_stb_ref_curves())
os.system("sed -i 's/True/1/g' visibility.csv")
os.system("sed -i 's/False/0/g' visibility.csv")
os.system("./rename_files.sh")
os.system("tar cvfjh \"%s.tar.bz2\" plot.py ground3D.csv visibility.csv images/" % dataset_name)
plt.ioff()
fig = plt.figure()
ax = fig.add_subplot(111)
for t, v, name in curve_list:
ax.plot(t, v*100, label=name)
ax.set_xlabel('threshold in mm')
ax.set_ylabel('% of correct keypoints')
plt.ylim([0.0, 100.0])
plt.grid()
plt.legend(loc='lower right')
plt.tight_layout(rect=(0.01, -0.05, 1.03, 1.03))
plt.show()
plt.pause(0.001)
plt.savefig(model_path + "/eval_results/pck_RgbTo3D_" + dataset_name)
@@ -0,0 +1,316 @@
#!/usr/bin/env python3
import numpy as np
import gc
import os
import sys
import csv
import time
import array
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import axes3d, Axes3D
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def pointListReturnXYZListForScatterPlot(A):
numberOfPoints=A.shape[0]
xs=list()
ys=list()
zs=list()
for i in range(0,int(numberOfPoints/3)):
xs.append(float(-1000*10*A[i*3+0]))
ys.append(float(1000*10*A[i*3+1]))
zs.append(float(1000*10*A[i*3+2]))
return xs,ys,zs
def checkIfFileExists(filename):
return os.path.isfile(filename)
def convert_bytes(num):
"""
this function will convert bytes to MB.... GB... etc
"""
step_unit = 1000.0 #1024 bad the size
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
if num < step_unit:
return "%3.1f %s" % (num, x)
num /= step_unit
def getNumberOfLines(filename):
print("Counting number of lines in file ",filename)
with open(filename) as f:
return sum(1 for line in f)
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
def readCSVFile(filename,memPercentage,csvDelimiter,useHalfFloats,groupOutput):
print("CSV file :",filename,"..\n")
if (not checkIfFileExists(filename)):
print( bcolors.WARNING + "Input file "+filename+" does not exist, cannot read ground truth.." + bcolors.ENDC)
print("Current Directory was "+os.getcwd())
sys.exit(0)
start = time.time()
dtypeSelected=np.dtype(np.float32)
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
if (useHalfFloats):
dtypeSelected=np.dtype(np.float16)
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
progress=0.0
sampleNumber=0
receivedHeader=0
inputNumberOfColumns=0
inputLabels=list()
#-------------------------------------------------------------------------------------------------
numberOfSamplesInput=getNumberOfLines(filename)-2
print(" Input file has ",numberOfSamplesInput," training samples\n")
#-------------------------------------------------------------------------------------------------
numberOfSamples = numberOfSamplesInput
numberOfSamplesLimit=int(numberOfSamples*memPercentage)
#-------------------------------------------------------------------------------------------------
if (memPercentage==0.0):
print("readGroundTruthFile was asked to occupy 0 memory so this probably means we just want one record")
numberOfSamplesLimit=2
if (memPercentage>1.0):
print("Memory Limit will be interpreted as a raw value..")
numberOfSamplesLimit=int(memPercentage)
#-------------------------------------------------------------------------------------------------
thisInput = array.array('f')
#---------------------------------
fi = open(filename, "r")
readerIn = csv.reader( fi , delimiter=csvDelimiter, skipinitialspace=True)
for rowIn in readerIn:
#------------------------------------------------------
if (not receivedHeader): #use header to get labels
#------------------------------------------------------
inputNumberOfColumns=len(rowIn)
#Make sure CSV files that end with delimiter are correctly handled..
if (inputNumberOfColumns>0):
if (rowIn[inputNumberOfColumns-1]==''):
inputNumberOfColumns=inputNumberOfColumns-1
#-----------------------------------------------------
inputLabels = list(rowIn[i] for i in range(0,inputNumberOfColumns) )
print("Number of Input elements : ",len(inputLabels))
#------------------------------------------------------
if (memPercentage==0):
print("Will only return labels\n")
return {'labels':inputLabels};
#i=0
#print("class Input(Enum):")
#for label in inputLabels:
# print(" ",label," = ",i," #",int(i/3))
# print(" ",label,"=",int(i/3))
# i=i+1
#---------------------------------
# Allocate Lists
#---------------------------------
for i in range(inputNumberOfColumns):
thisInput.append(0.0)
#---------------------------------
#---------------------------------
# Allocate Numpy Arrays
#---------------------------------
inputSize=0
startCompressed=0
inputSize=inputSize+inputNumberOfColumns
startCompressed=inputNumberOfColumns
npInputBytesize=0+numberOfSamplesLimit * inputSize * dtypeSelectedByteSize
print(" Input file on disk has a shape of [",numberOfSamples,",",inputSize,"]")
print(" Input we will read has a shape of [",numberOfSamplesLimit,",",inputSize,"]")
print(" Input will occupy ",convert_bytes(npInputBytesize)," of RAM\n")
npInput = np.full([numberOfSamplesLimit,inputSize],fill_value=0,dtype=dtypeSelected,order='C')
#----------------------------------------------------------------------------------------------------------
receivedHeader=1
#sys.exit(0)
else:
#-------------------------------------------
# First convert our string INPUT to floats
#-------------------------------------------
for i in range(inputNumberOfColumns):
thisInput[i]=float(rowIn[i])
#-------------------------------------------
for num in range(0,inputNumberOfColumns):
npInput[sampleNumber,num]=float(thisInput[num]);
#-------------------------------------------
sampleNumber=sampleNumber+1
if (numberOfSamples>0):
progress=sampleNumber/numberOfSamplesLimit
if (sampleNumber%1000==0) :
progressString = "%0.2f"%float(100*progress)
print("\rReading from disk (",sampleNumber,") - ",progressString," % \r", end="", flush=True)
if (numberOfSamplesLimit<=sampleNumber):
print("\rStopping reading file to obey memory limit given by parameter --mem ",memPercentage,"\n")
break
#-------------------------------------------
fi.close()
del readerIn
gc.collect()
print("\n read, Samples: ",sampleNumber,", was expecting ",numberOfSamples," samples\n")
print(npInput.shape)
totalNumberOfBytes=npInput.nbytes;
totalNumberOfGigaBytes=totalNumberOfBytes/1073741824;
print("Size Occupied by data = ",totalNumberOfGigaBytes," GB \n")
end = time.time()
print("Time elapsed : ",(end-start)/60," mins")
#---------------------------------------------------------------------
if (groupOutput==0):
#New better dictionary
output = dict()
for i in range(0,len(inputLabels)):
lowerCaseName = inputLabels[i].lower()
#print("Joint ",lowerCaseName)
output[lowerCaseName]=list()
for frameID in range(0,len(npInput)):
output[lowerCaseName].append(npInput[frameID][i])
return output
else:
#This is the old dictionary way (better for tensorflow training)
return {'label':inputLabels, 'body':npInput };
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
drawPlot=1
ground=readCSVFile("ground3D.csv",1.0,',',0,1)
if (drawPlot):
print("Using matplotlib:",matplotlib.__version__)
# === Plot and animate ===
fig = plt.figure()
fig.set_size_inches(19.2, 10.8, forward=True)
ax = fig.add_subplot(1, 2, 1, projection='3d')
ax2 = fig.add_subplot(1, 2, 2)
#ax3 = fig.add_subplot(2, 2, 3)
#ax4 = fig.add_subplot(2, 2, 4)
fig.subplots_adjust(left=0.05, bottom=0.05, right=0.95, top=0.95)
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
ax.set_zlabel('Z Axis')
ax.view_init(90, 90)
print("Ground truth file has %u elements ",len(ground['body']))
for i in range(0,len(ground['body'])):
if (drawPlot):
plt.cla()
ax.cla()
ax2.cla()
#ax3.cla()
#ax4.cla()
categories = np.array([0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20
])
color0=(0.0, 1.0, 1.0, 1.0) #Palm
color1=(0.6, 0.0, 0.0, 1.0) #Thumb
color2=(0.8, 0.0, 0.0, 1.0) #Finger 1.2
color3=(1.0, 0.0, 0.0, 1.0) #Finger 1.3
color4=(0.0, 1.0, 1.0, 1.0) #BaseOfFourFingers
color5=(0.0, 1.0, 0.0, 1.0) #Finger 2.3
color6=(0.0, 0.8, 0.0, 1.0) #Finger 2.2
color7=(0.0, 0.6, 0.0, 1.0) #Finger 2.1
color8=(0.0, 0.4, 0.0, 1.0) #Metacarpal 1
color9=(0.0, 0.0, 1.0, 1.0) #Finger 3.3
color10=(0.0, 0.0, 0.8, 1.0) #Finger 3.2
color11=(0.0, 0.0, 0.6, 1.0) #Finger 3.1
color12=(0.0, 0.0, 0.4, 1.0) #Metacarpal 2
color13=(0.0, 1.0, 1.0, 1.0) #Finger 4.3
color14=(0.0, 0.8, 0.8, 1.0) #Finger 4.2
color15=(0.0, 0.6, 0.6, 1.0) #Finger 4.1
color16=(0.0, 0.4, 0.4, 1.0) #Metacarpal 3
color17=(1.0, 1.0, 0.0, 1.0) #Finger 5.3
color18=(0.8, 0.8, 0.0, 1.0) #Finger 5.2
color19=(0.6, 0.6, 0.0, 1.0) #Finger 5.1
color20=(0.4, 0.4, 0.0, 1.0) #Metacarpal 4
colormap = np.array([color0,color1,color2,color3,color4,color5,color6,color7,color8,color9,color10,color11,color12,color13,color14,color15,color16,color17,color18,color19,color20])
xs, ys, zs = pointListReturnXYZListForScatterPlot(ground['body'][i])
ax.scatter(xs, ys, zs, c=colormap[categories])
img = plt.imread("images/im%u.png" % i)
ax2.imshow(img)
#-------------------------
ax.set_xlim(auto=False,left=-600,right=300)
ax.set_ylim(auto=False,bottom=-1600,top=200)
ax.set_zlim(auto=False,bottom=2000,top=6000)
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
ax.set_zlabel('Z Axis')
#-------------------------
plt.show(block=False)
#plt.savefig('p%05u.png'%i)
#fig.canvas.draw()
plt.pause(0.001)
@@ -0,0 +1,16 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$DIR"
python3 -m venv venv
source venv/bin/activate
pip install tensorflow==1.3.0
pip install numpy==1.14.5
pip install scipy==1.1.0
pip install matplotlib==1.5.3
pip install torch==0.3.1
pip install opencv-python==3.4.1.15
python evaluate_model.py
exit 0
@@ -0,0 +1,33 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$DIR"
HAND="r"
FILE="ground3D.csv"
#cp ground3D.csv $FILE
sed -i "s/_0,/_${HAND}hand,/g" $FILE
sed -i "s/_1,/_${HAND}thumb,/g" $FILE
sed -i "s/_2,/_finger1.2.${HAND},/g" $FILE
sed -i "s/_3,/_finger1.3.${HAND},/g" $FILE
sed -i "s/_4,/_${HAND}baseOfFourFingers,/g" $FILE
sed -i "s/_5,/_finger2.3.${HAND},/g" $FILE
sed -i "s/_6,/_finger2.2.${HAND},/g" $FILE
sed -i "s/_7,/_finger2.1.${HAND},/g" $FILE
sed -i "s/_8,/_metacarpal1.${HAND},/g" $FILE
sed -i "s/_9,/_finger3.3.${HAND},/g" $FILE
sed -i "s/_10,/_finger3.2.${HAND},/g" $FILE
sed -i "s/_11,/_finger3.1.${HAND},/g" $FILE
sed -i "s/_12,/_metacarpal2.${HAND},/g" $FILE
sed -i "s/_13,/_finger4.3.${HAND},/g" $FILE
sed -i "s/_14,/_finger4.2.${HAND},/g" $FILE
sed -i "s/_15,/_finger4.1.${HAND},/g" $FILE
sed -i "s/_16,/_metacarpal3.${HAND},/g" $FILE
sed -i "s/_17,/_finger5.3.${HAND},/g" $FILE
sed -i "s/_18,/_finger5.2.${HAND},/g" $FILE
sed -i "s/_19,/_finger5.1.${HAND},/g" $FILE
sed -i "s/_20,/_metacarpal4.${HAND},/g" $FILE
exit 0