mirror of
https://github.com/storytold/storyteller-ml.git
synced 2026-10-15 00:03:06 +00:00
slightly tweaked mocapnet alt container
This commit is contained in:
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 @@
|
||||
face
|
||||
+2
@@ -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
|
||||
|
+2
@@ -0,0 +1,2 @@
|
||||
head_reyebrow_2,head_reyebrow_4,head_leyebrow_2,head_leyebrow_4
|
||||
102,121,40,59
|
||||
|
+2
@@ -0,0 +1,2 @@
|
||||
head_reye,head_leye
|
||||
1023,485
|
||||
|
@@ -0,0 +1 @@
|
||||
face
|
||||
+2
@@ -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
|
||||
|
+2
@@ -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
|
||||
|
+2
@@ -0,0 +1,2 @@
|
||||
head_reye,head_leye
|
||||
1023,485
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
mouth
|
||||
+2
@@ -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
|
||||
|
@@ -0,0 +1 @@
|
||||
reye
|
||||
+2
@@ -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
|
||||
|
+2
@@ -0,0 +1,2 @@
|
||||
head_reyebrow_0,head_reyebrow_1,head_reyebrow_2,head_reyebrow_3,head_reyebrow_4
|
||||
96,93,102,111,121
|
||||
|
+2
@@ -0,0 +1,2 @@
|
||||
head_reye
|
||||
764
|
||||
|
@@ -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
@@ -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.
|
||||
|
||||

|
||||
|
||||
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
@@ -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 |
@@ -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)
|
||||
+1196
File diff suppressed because it is too large
Load Diff
+177
@@ -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
@@ -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>λ</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
@@ -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")
|
||||
@@ -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")
|
||||
+1035
File diff suppressed because it is too large
Load Diff
+469
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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")
|
||||
+622
@@ -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
@@ -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()
|
||||
|
||||
|
||||
+1068
File diff suppressed because it is too large
Load Diff
+287
@@ -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)
|
||||
+1303
File diff suppressed because it is too large
Load Diff
+124
@@ -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
|
||||
|
||||
+556
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user