Add MocapNET

This commit is contained in:
Justin John
2023-12-15 04:22:41 +05:30
parent 8434144ded
commit 65e8934d5e
336 changed files with 100584 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -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")
@@ -0,0 +1,738 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import os
import sys
import gc
import time
import json
import tensorflow as tf
from tensorflow import keras
#from tensorflow.keras.backend.tensorflow_backend import set_session
#from tensorflow.keras import backend as K
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.models import Sequential
from tensorflow.keras.models import model_from_json
from tensorflow.keras.utils import plot_model
import tensorflow.keras.callbacks
import numpy as np
from numba import njit #Test
from tools import bcolors,checkIfFileExists
def printTrainingVersion():
print("""
███╗ ███╗ ██████╗ ██████╗ █████╗ ██████╗ ███╗ ██╗███████╗████████╗
████╗ ████║██╔═══██╗██╔════╝██╔══██╗██╔══██╗████╗ ██║██╔════╝╚══██╔══╝
██╔████╔██║██║ ██║██║ ███████║██████╔╝██╔██╗ ██║█████╗ ██║
██║╚██╔╝██║██║ ██║██║ ██╔══██║██╔═══╝ ██║╚██╗██║██╔══╝ ██║
██║ ╚═╝ ██║╚██████╔╝╚██████╗██║ ██║██║ ██║ ╚████║███████╗ ██║
╚═╝ ╚═╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝
""")
#-----------------------------
#BMVC 21 paper was submitted with Keras 2.2.4/Tensorflow 1.14/Numpy 1.16.2
#-----------------------------
print("")
print("Tensorflow version : ",tf.__version__)
#print("Keras version : ",keras.__version__) <- no longer available in TF-2.13
print("Numpy version : ",np.__version__)
#-----------------------------
from tensorflow.python.platform import build_info as tf_build_info
print("TF/CUDA version : ",tf_build_info.build_info['cuda_version'])
print("TF/CUDNN version : ",tf_build_info.build_info['cudnn_version'])
#-----------------------------
print("")
#-----------------------------
def forceCPU():
print(bcolors.WARNING,"User selected to use CPU mode",bcolors.ENDC)
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" # see issue #152
os.environ["CUDA_VISIBLE_DEVICES"] = ""
def limitGPUMemory():
print("Limiting GPU memory usage for multiple instances..\n")
config = tf.compat.v1.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.2
config.gpu_options.visible_device_list = "0"
set_session(tf.compat.v1.Session(config=config))
def setTensorflowBackendToHalfFloats():
dtype='float16'
#WARNING:tensorflow:Mixed precision compatibility check (mixed_float16): WARNING
#Your GPU may run slowly with dtype policy mixed_float16 because it does not have compute capability
#of at least 7.0. Your GPU: Quadro P6000, compute capability 6.1
from tensorflow.keras.mixed_precision import experimental as mixed_precision
policy = mixed_precision.Policy('mixed_float16')
mixed_precision.set_policy(policy)
tf.keras.backend.set_floatx(dtype)
# default is 1e-7 which is too small for float16. Without adjusting the epsilon, we will get NaN predictions because of divide by zero problems
tf.keras.backend.set_epsilon(1e-4)
print('Compute dtype: %s' % policy.compute_dtype)
print('Variable dtype: %s' % policy.variable_dtype)
print("\nUsing Half-Floats for training ")
def getRSquared(groundTruth, neuralNetworkOutput):
"""
Computes the R-squared metric.
https://en.wikipedia.org/wiki/Coefficient_of_determination
Parameters:
-- groundTruth (numpy.ndarray): 1D array representing the ground truth.
-- neuralNetworkOutput (numpy.ndarray): 1D array representing the neural network output.
Returns:
-- float: R-squared metric.
"""
# Compute the mean of the ground truth
mean_ground_truth = np.mean(groundTruth)
# Compute the sum of squares of the residuals
ss_residuals = np.sum((groundTruth - neuralNetworkOutput) ** 2)
# Compute the sum of squares of the total variation
ss_total = np.sum((groundTruth - mean_ground_truth) ** 2)
# Compute the R-squared metric
r_squared = 1 - (ss_residuals / ss_total)
return r_squared
@njit
def getRSquaredInPlace(groundTruth,mean_ground_truth,N,neuralNetworkOutput):
"""
Computes the R-squared metric.
https://en.wikipedia.org/wiki/Coefficient_of_determination
Parameters:
-- groundTruth (numpy.ndarray): 1D array representing the ground truth.
-- neuralNetworkOutput (numpy.ndarray): 1D array representing the neural network output.
Returns:
-- float: R-squared metric.
"""
#N = groundTruth.shape[0]
if N == 0:
return np.NAN
# Compute the mean of the ground truth
#mean_ground_truth = np.mean(groundTruth)
ss_residuals = np.float32(0.0)
ss_total = np.float32(0.0)
for i in range(N):
#--------------------------------------
gt = np.float32(groundTruth[i][0]) #groundTruth is a tensorflow array so each element is also an array -> thus we need [0]
nn_out = np.float32(neuralNetworkOutput[i][0]) #neuralNetworkOutput is a tensorflow array so each element is also an array -> thus we need [0]
#--------------------------------------
delta = gt - nn_out
ss_residuals += delta ** 2
#--------------------------------------
delta = gt - mean_ground_truth
ss_total += delta ** 2
# Compute the R-squared metric
r_squared = np.float32(1 - (ss_residuals / ss_total))
return r_squared
def getRSquaredForNeuralNetwork(mocapNETNetwork,networkInput,groundtruthOutput):
import time
startAt = time.time()
#-----------------------------------------------------
try:
print("Extracting R² : Getting neural network response..")
predictions = mocapNETNetwork.predict(networkInput)
#Since the groundtruth is very large and the machines I use don't have
#enough RAM this is an in place R^2 calculation to make sure the computer doesn't enter a page swapping
#loop that makes training grind to a halt..!
print("Extracting R² : Calculating..")
mean_ground_truth = np.float32(np.mean(groundtruthOutput))
#print("groundtruthOutput: ",groundtruthOutput)
rSQ = getRSquaredInPlace(groundtruthOutput,mean_ground_truth,groundtruthOutput.shape[0],predictions)
#This is faster (if you have spare memory..)
#rSQ = getRSquared(groundtruthOutput,predictions)
del predictions
#except:
except Exception as e:
print("Failed to extract R² ..")
print("Error was : ",e)
rSQ = np.NAN
#-----------------------------------------------------
#-----------------------------------------------------
endAt = time.time()
print("R² = ",rSQ," it took ",(endAt-startAt)/60," mins to compute")
return rSQ
def logTrainingResults(
filename,
configuration,
outputType,
outputName,
history,
metrics
):
if (outputType==0):
numberOfModelParametersStr="?"
if 'modelParameters' in configuration:
numberOfModelParametersStr="%u" % int(configuration['modelParameters'])
#First record - Start of File
inputProcessing=""
if (configuration['eNSRM']):
inputProcessing=inputProcessing+" eNSRM"
if ('NSRMNormalizeAngles' in configuration) and (configuration['NSRMNormalizeAngles']):
if (configuration['NSRMNormalizeAngles']==1):
inputProcessing=inputProcessing+" NSRMNormalizeAngles" #Half
elif (configuration['NSRMNormalizeAngles']==2):
inputProcessing=inputProcessing+" NSRMNormalizeAnglesFull"
else:
inputProcessing=inputProcessing+" NSRMNormalizeAnglesUNKNOWN"
if (configuration['EDM']):
inputProcessing=inputProcessing+" EDM"
if (configuration['eigenPoses']):
inputProcessing=inputProcessing+" eigenPoses"
if (configuration['autobuilder']):
inputProcessing=inputProcessing+" autobuilder"
if ( (configuration['decompositionType']!="") and (configuration['doPCA']!="") and ( int(configuration['PCADimensionsKept'])>0 ) ):
inputProcessing=inputProcessing+" %s(%u)"%(configuration['decompositionType'],configuration['PCADimensionsKept'])
if (configuration['PCAAlsoKeepRawData']):
inputProcessing=inputProcessing+"+PCA_RawData"
inputProcessing=inputProcessing+" act("+configuration['activationFunction']+")"
inputProcessing=inputProcessing+" rand("+configuration['weightRandomizationFunction']+")"
inputProcessing=inputProcessing+" "+configuration['optimizer']
if (configuration['balanced2DInputs']):
inputProcessing=inputProcessing+" balanced2DInputs"
if (configuration['useQuadLoss']!=0):
inputProcessing=inputProcessing+" quadLoss"
if (configuration['setConstantSeedForReproducibleTraining']!=1):
inputProcessing=inputProcessing+" random seed"
if (configuration['include2DInputVisibilityFlags']==0):
inputProcessing=inputProcessing+" novis2Dflag"
experimentDescription=""
experimentDescription=experimentDescription+"group %u"%(configuration["groupOutputs"])
if (configuration['useRadians']):
experimentDescription=experimentDescription+" radians"
#--------------------------------------------------------------------
if ('outputValueDistribution' in configuration):
if (configuration['outputValueDistribution']=='balanced'):
experimentDescription=experimentDescription+" balanced offset"
elif (configuration['outputValueDistribution']=='positive'):
experimentDescription=experimentDescription+" positive offset"
elif (configuration['outputValueDistribution']=='negative'):
experimentDescription=experimentDescription+" negative offset"
#--------------------------------------------------------------------
if ('outputNormalizationStrategy' in configuration):
experimentDescription=experimentDescription+" outputNormalizationStrategy="+configuration['outputNormalizationStrategy']
#--------------------------------------------------------------------
if (float(configuration['outputMultiplier'])!=1.0):
experimentDescription=experimentDescription+" outputScaling=%0.2f" % float(configuration['outputMultiplier'])
experimentDescription=experimentDescription+" NNDepth=%u"%configuration['neuralNetworkDepth']
#FIRST! RECORD!
with open(filename, 'w') as f:
f.write("""
<html>
<head>
<meta charset=\"UTF-8\">
<title>Training summary of experiment %s for %s </title>
</head>
<body>
"""%(configuration['label'],configuration['hierarchyPartName']))
#Add the hostname..
import socket
f.write("%s<br>\n"%socket.gethostname())
f.write("""
<table border=1>
<tr>
<td>Date</td>
<td>Part</td>
<td>BatchSize</td>
<td>Epochs</td>
<td>&lambda;</td>
<td>Remember</td>
<td>Occlusions</td>
<td>Input Processing</td>
<td>Hard Mining</td>
</tr>
<tr>
<td>%s</td>
<td>%s</td>
<td>%u</td>
<td>%u/%u/%u</td>
<td>%0.2f</td>
<td>c %u/p %u</td>
<td>%u</td>
<td>%s</td>
<td></td>
</tr>
</table>
"""% (
configuration['date'],
configuration['hierarchyPartName'],
configuration['defaultBatchSize'],
configuration["defaultNumberOfEpochs"],configuration["highNumberOfEpochs"],configuration["veryHighNumberOfEpochs"],
configuration["lamda"],
configuration["rememberConsecutiveWeights"],configuration["rememberWeights"],
configuration["ignoreOcclusions"]==0,
inputProcessing
)
)
f.write("""
<table border=1>
<tr>
<td>Serial</td>
<td>Start</td>
<td>End</td>
<td>Training Samples</td>
<td>Model Size</td>
<td>Dropout/L.R</td>
<td>Description</td>
</tr>
<tr>
<td>%s</td>
<td>%u</td>
<td>%u</td>
<td>%u</td>
<td>%s</td>
<td>%0.2f/%0.5f</td>
<td>%s</td>
</tr>
</table>
<table border=1>
<tr>
<td>Joint</td>
<td>R² / Start Loss / M.A.E</td>
<td>R² / End Loss / M.A.E</td>
<td>Tr.Epochs</td>
<td>Min/Max</td>
<td>Offset</td>
<td>Scalar</td>
<td>Scalar Fr.</td>
</tr>
"""% (
configuration['label'],
configuration['startPosition'],
configuration['endPosition'],
configuration['trainingSamples'],
numberOfModelParametersStr,
configuration['dropoutRate'],
configuration['learningRate'],
experimentDescription
)
)
f.close()
#----------------------------------
try:
lowestLossAchievedAt = 0
if ("loss" in history.history) and ("mae" in history.history):
# Initialize variables to store the initial and lowest loss
initial_loss = history.history['loss'][0]
lowest_loss = initial_loss
initial_mae = history.history['mae'][0]
lowest_mae = initial_mae
# Iterate through the history object
count = 0
for i, loss in enumerate(history.history['loss']):
# Update the lowest loss if a lower value is found
if loss < lowest_loss:
lowest_loss = loss
lowestLossAchievedAt = count
count = count + 1
lowest_mae = history.history['mae'][lowestLossAchievedAt]
#By default don't scale
#----------------------------------------------------------------------------
outputMinimumValue = 0.0
outputMaximumValue = 0.0
outputOffsetValue = 0.0
outputScalarValues = 1.0
outputScalarFractionValues = 1.0
#----------------------------------------------------------------------------
for v in range(0,len(configuration["outputOffsetLabels"])):
if (outputName.lower()==configuration["outputOffsetLabels"][v].lower()):
#we found a rule!
outputMinimumValue = float(configuration["outputOffsetMinima"][v])
outputMaximumValue = float(configuration["outputOffsetMaxima"][v])
outputOffsetValue = float(configuration["outputOffsetValues"][v])
outputScalarValues = float(configuration["outputScalarValues"][v])
outputScalarFractionValues = float(configuration["outputScalarFractionValues"][v])
#----------------------------------------------------------------------------
initialVAL = ""
lowestVAL = ""
if ("val_loss" in history.history) and ("val_mae" in history.history):
initial_VALloss = history.history['val_loss'][0]
lowest_VALloss = history.history['val_loss'][lowestLossAchievedAt]
initial_VALmae = history.history['val_mae'][0]
lowest_VALmae = history.history['val_mae'][lowestLossAchievedAt]
initial_VALmae = initial_VALmae * outputScalarFractionValues
lowest_VALmae = lowest_VALmae * outputScalarFractionValues
#--------------------------------------
initialVAL = " - "
if ("test_rsquared_start" in metrics):
initialVAL = " - R² %0.2f/"%(metrics["test_rsquared_start"])
initialVAL = initialVAL + "%0.4f/%0.4f" % (initial_VALloss,initial_VALmae)
#--------------------------------------
lowestVAL = " - "
if ("test_rsquared_end" in metrics):
lowestVAL = " - R² %0.2f/"%(metrics["test_rsquared_end"])
lowestVAL = lowestVAL + "%0.4f/%0.4f" % (lowest_VALloss,lowest_VALmae)
#Every output now gets scaled always
initial_mae = initial_mae * outputScalarFractionValues
lowest_mae = lowest_mae * outputScalarFractionValues
with open(filename, 'a') as f:
f.write("<tr><td>")
f.write(outputName)
f.write("</td>")
#------------------------------------------------
#Start Loss
f.write("<td>")
if ("train_rsquared_start" in metrics):
f.write("R² %0.2f/"%(metrics["train_rsquared_start"]))
f.write("%0.4f/%0.4f%s"%(initial_loss,initial_mae,initialVAL))
f.write("</td>")
#------------------------------------------------
#End Loss
f.write("<td>")
if ("train_rsquared_end" in metrics):
f.write("R² %0.2f/"%(metrics["train_rsquared_end"]))
f.write("%0.4f/%0.4f%s"%(lowest_loss,lowest_mae,lowestVAL))
f.write("</td>")
#------------------------------------------------
#Training Epochs ----------------------------
f.write("<td>")
f.write("%u"%(lowestLossAchievedAt))
f.write("</td>")
#Min/Max ----------------------------
f.write("<td>")
f.write("%0.4f/%0.4f"%(outputMinimumValue,outputMaximumValue))
f.write("</td>")
#Offset -----------------------------
f.write("<td>")
f.write("%0.4f"%(outputOffsetValue))
f.write("</td>")
#Scalar -----------------------------
f.write("<td>")
f.write("%0.4f"%(outputScalarValues))
f.write("</td>")
f.write("<td>")
f.write("%0.4f"%(outputScalarFractionValues))
f.write("</td>")
#------------------------------------------------
f.write("</tr>")
f.close()
except:
print("An exception occurred in logTrainingResults")
def regularTraining(tensorboardLabel,mocapNETNetwork,numberOfEpochs,batchSize,earlyStoppingPatience,trainInput,trainOutput,testInput,testOutput,minD,modelIsTrivial=False,haveTestSet=False,useHalfFloats=False):
#We use a checkpoint system to return best model..
if (os.path.isfile("bestW.hdf5")):
print(bcolors.WARNING,"Found a forgotten checkpoint file, erasing it to avoid trouble",bcolors.ENDC)
os.system('rm bestW.hdf5')
#whatToMonitor='mean_absolute_error'
#minimumDelta=0.05
whatToMonitor='loss'
metrics = dict()
if (useHalfFloats):
print("Early stopping will use MAE instead of loss due to half floats..")
whatToMonitor='mae'
minimumDelta=minD
#To see use :
#tensorboard --logdir step0_upperbody_all/tensorboard --bind_all
#------------------------------------------------------------------------
tensorboard = keras.callbacks.TensorBoard(log_dir=tensorboardLabel,histogram_freq=1)
#------------------------------------------------------------------------
earlystopper = keras.callbacks.EarlyStopping(
monitor=whatToMonitor,
min_delta=minimumDelta,
patience=earlyStoppingPatience,
verbose=1,
mode='auto'
)
#-------------------------------------------------------------------------
checkpointer = keras.callbacks.ModelCheckpoint(
filepath="bestW.hdf5",
monitor=whatToMonitor,
mode='min',
verbose=1,
save_freq='epoch',
save_best_only=True,
save_weights_only=True
)
#------------------------------------------------------------------------
callbacks = [
earlystopper,
checkpointer,
tensorboard
]
#------------------------------------------------------------------------
print("regularTraining begins -> BatchSize=%u / NumberOfEpochs=%u "%(batchSize,numberOfEpochs))
#------------------------------------------------------------------------
if (haveTestSet==False):
#Train without any test data ( probably to conserve memory )
if (not modelIsTrivial):
metrics["train_rsquared_start"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
history = mocapNETNetwork.fit(
trainInput,trainOutput,
epochs=numberOfEpochs,
batch_size=batchSize,
shuffle=True,
#steps_per_epoch=5, #<- Use more steps per epoch?
callbacks=callbacks
)
if (not modelIsTrivial):
metrics["train_rsquared_end"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
else:
#Train with test data
if (not modelIsTrivial):
metrics["train_rsquared_start"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
metrics["test_rsquared_start"] = getRSquaredForNeuralNetwork(mocapNETNetwork,testInput,testOutput)
history = mocapNETNetwork.fit(
trainInput,trainOutput,
epochs=numberOfEpochs,
batch_size=batchSize,
shuffle=True,
validation_data=(testInput,testOutput),
#validation_split=0.2,
callbacks=callbacks
)
if (not modelIsTrivial):
metrics["train_rsquared_end"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
metrics["test_rsquared_end"] = getRSquaredForNeuralNetwork(mocapNETNetwork,testInput,testOutput)
#------------------------------------------------------------------------
if (checkIfFileExists('bestW.hdf5')):
print("We use the best possible model from our ModelCheckpoint")
mocapNETNetwork.load_weights('bestW.hdf5')
os.system('rm bestW.hdf5') #Get rid of the checkpoint as soon as we are done reading it
else:
print("No bestW.hdf5 file found, just using last iteration..")
#------------------------------------------------------------------------
return history,mocapNETNetwork,metrics
#-------------------------------------------------------------------------------------------------------------------------------------------------
def compareTrainingOutputs(groundTruth,neuralOutput):
if (len(groundTruth)!=len(neuralOutput)):
print("Outputs have a different size")
return np.nan
values = len(groundTruth)
losses = (groundTruth[:]-neuralOutput[:])**2
return losses
#----------------------------------------------------
def appendHistory(baseHistory,historyToAppend):
#print("baseHistory -> ",type(baseHistory))
#print("baseHistory Contents -> ",baseHistory)
#print("historyToAppend -> ",type(historyToAppend))
#print("historyToAppend Contents -> ",historyToAppend)
#print("baseHistory.history -> ",type(baseHistory.history))
#print("historyToAppend.history -> ",type(historyToAppend.history))
#-----------------------------------------------------------------------------------------------------------
if ("mae" in baseHistory.history) and ("mae" in historyToAppend.history):
baseHistory.history['mae'] = baseHistory.history['mae'] + historyToAppend.history['mae']
if ("loss" in baseHistory.history) and ("loss" in historyToAppend.history):
baseHistory.history['loss'] = baseHistory.history['loss'] + historyToAppend.history['loss']
if ("val_loss" in baseHistory.history) and ("val_loss" in historyToAppend.history):
baseHistory.history['val_loss'] = baseHistory.history['val_loss'] + historyToAppend.history['val_loss']
if ("val_mae" in baseHistory.history) and ("val_mae" in historyToAppend.history):
baseHistory.history['val_mae'] = baseHistory.history['val_mae'] + historyToAppend.history['val_mae']
#-----------------------------------------------------------------------------------------------------------
return baseHistory
def getLossManually(mocapNETNetwork,trainInput,trainOutput):
predictions = mocapNETNetwork.predict(trainInput)
losses = compareTrainingOutputs(predictions,trainOutput)
#print(losses)
print("Calculating Loss Statistics :")
#--------------------------
maximum = np.max(losses)
minimum = np.min(losses)
median = np.median(losses)
mean = np.mean(losses)
from tools import calculateStandardDeviationInPlaceKnowingMean,convertStandardDeviationToVariance
std = calculateStandardDeviationInPlaceKnowingMean(losses,mean) #np.std(losses)
var = convertStandardDeviationToVariance(std) #np.var(losses)
#--------------------------
titleString="Min=%0.2f,Max=%0.2f,Median=%0.2f,Mean=%0.2f,Std=%0.2f,Var=%0.2f" % (minimum,maximum,median,mean,std,var)
print(bcolors.WARNING," %s " % titleString,bcolors.ENDC)
#difficultyRating = 1.5
difficultyRating = 5.0 # 4.0 1.5 2.8
badScoreAbove = mean + difficultyRating * np.sqrt(std)
print("Threshold for difficult poses is ",badScoreAbove)
difficultPosesIndexes=list()
numberOfTrainingSamples = len(trainInput)
for z in range(0,numberOfTrainingSamples):
if (np.any(losses[z]>badScoreAbove)):
difficultPosesIndexes.append(z)
del losses
return difficultPosesIndexes,mean,std
def onlineHardExampleMiningTraining(tensorboardLabel,mocapNETNetwork,numberOfEpochs,numberOfHardEpochs,numberOfNormalEpochsAfterHard,batchSize,earlyStoppingPatience,trainInput,trainOutput,testInput,testOutput,minD,modelIsTrivial=False,haveTestSet=False,useHalfFloats=False):
#First do a regular training..
halfEpochs=int(numberOfEpochs/2)
if (numberOfEpochs==1):
halfEpochs=numberOfEpochs
print(" Online Hard Example Mining Training session .. ")
metrics = dict()
if (not modelIsTrivial):
metrics["train_rsquared_start"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
dtypeSelected=np.float32
if (useHalfFloats):
dtypeSelected=np.float16
totalHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,halfEpochs,batchSize,earlyStoppingPatience,trainInput,trainOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats)
if (numberOfEpochs==1):
print(" Trivial output will not mine etc. ")
return totalHistory
bestTrainingMAE=0.0
successfulUpdates=0
REGULAR_EPOCHS_AFTER_HARD=numberOfNormalEpochsAfterHard
HARD_EPOCHS=numberOfHardEpochs
miningEpochs = int(halfEpochs/2)
print("Getting initial state of network")
difficultPosesIndexes,mean,std = getLossManually(mocapNETNetwork,trainInput,trainOutput)
print("Backing up model with mae ",mean)
mocapNETNetwork.save_weights("modelBackup.h5")
bestTrainingMAE=mean
for i in range(0,miningEpochs):
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
numberOfTrainingSamples = len(trainInput)
inputSize = len (trainInput[1])
outputSize = len (trainOutput[1])
ratioOfDatasetThatIsDifficult = float ( len(difficultPosesIndexes) / numberOfTrainingSamples )
#If more than 10% of the dataset is difficult
if (ratioOfDatasetThatIsDifficult>0.5):
print(bcolors.FAIL," More than half of the dataset is hard (%u samples) so we train on all samples as hard %u/%u" % (len(difficultPosesIndexes),i,miningEpochs),bcolors.ENDC)
regularHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,HARD_EPOCHS,batchSize,5,trainInput,trainOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats) #difficultInput,difficultOutput
totalHistory = appendHistory(totalHistory,regularHistory)
elif (ratioOfDatasetThatIsDifficult>0.1):
difficultInput = np.full([len(difficultPosesIndexes),inputSize],fill_value=0,dtype=dtypeSelected,order='C')
difficultOutput = np.full([len(difficultPosesIndexes),outputSize],fill_value=0,dtype=dtypeSelected,order='C')
for z in range(0,len(difficultPosesIndexes)):
for field in range(0,inputSize):
difficultInput[z,field]=trainInput[difficultPosesIndexes[z],field]
for field in range(0,outputSize):
difficultOutput[z,field]=trainOutput[difficultPosesIndexes[z],field]
print(bcolors.OKBLUE," Will now train on %u difficult samples %u/%u" % (len(difficultPosesIndexes),i,miningEpochs),bcolors.ENDC)
newHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,HARD_EPOCHS,batchSize,5,difficultInput,difficultOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats)
totalHistory = appendHistory(totalHistory,newHistory)
del difficultInput
del difficultOutput
if (mean<bestTrainingMAE):
print(bcolors.OKGREEN,"Inter-success... beat previous model with mae ",bestTrainingMAE," with this model that has ",mean," mae",bcolors.ENDC)
successfulUpdates=successfulUpdates+1
mocapNETNetwork.save_weights("modelBackup.h5")
bestTrainingMAE=mean
print(" Will now train on all samples not to forget them" )
regularHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,REGULAR_EPOCHS_AFTER_HARD,batchSize,earlyStoppingPatience,trainInput,trainOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats)
totalHistory = appendHistory(totalHistory,regularHistory)
else:
print(bcolors.OKGREEN,"The training has gone pretty well for all samples..",bcolors.ENDC)
regularHistory,mocapNETNetwork = regularTraining(tensorboardLabel,mocapNETNetwork,1,batchSize,1,trainInput,trainOutput,testInput,testOutput,minD,haveTestSet=haveTestSet,useHalfFloats=useHalfFloats)
totalHistory = appendHistory(totalHistory,regularHistory)
break
#Tensorflow leaves the existing models on GPU, as a result we run out of memory,
#try to collect garbage now..
gc.collect()
#Check what happened..
difficultPosesIndexes,mean,std = getLossManually(mocapNETNetwork,trainInput,trainOutput)
#-----------------------
if (mean<bestTrainingMAE):
print(bcolors.OKGREEN,"We beat previous model with mae ",bestTrainingMAE," with this model that has ",mean," mae",bcolors.ENDC)
successfulUpdates=successfulUpdates+1
mocapNETNetwork.save_weights("modelBackup.h5")
bestTrainingMAE=mean
else:
print(bcolors.FAIL,"We scored worse than mae ",bestTrainingMAE,", current score was ",mean," mae",bcolors.ENDC)
#-----------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
if (successfulUpdates==0):
print(bcolors.FAIL,"This OHME code was a waste of time",bcolors.ENDC)
print("Using the best model that had a mae of %0.2f after %u updates"%(bestTrainingMAE,successfulUpdates))
mocapNETNetwork.load_weights("modelBackup.h5")
if (not modelIsTrivial):
metrics["train_rsquared_end"] = getRSquaredForNeuralNetwork(mocapNETNetwork,trainInput,trainOutput)
del difficultPosesIndexes
return totalHistory,mocapNETNetwork,metrics
#-------------------------------------------------------------------------------------------------------------------------------------------------
@@ -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")
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,469 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import onnxruntime as ort
import onnx
import os
import sys
import time
#-------------------------------------------------------------------------------------------
from readCSV import parseConfiguration,parseConfigurationInputJointMap,transformNetworkInput,initializeDecompositionForExecutionEngine,readGroundTruthFile,readCSVFile,parseOutputNormalization
from NSDM import NSDMLabels,createNSDMUsingRules,inputIsEnoughToCreateNSDM,performNSRMAlignment
from EDM import EDMLabels,createEDMUsingRules
from tools import bcolors,eprint,checkIfFileExists,readListFromFile,convertListToLowerCase,secondsToHz,capitalizeCoordinateTags,getEntryIndexInList,parseSerialNumberFromSummary
#-------------------------------------------------------------------------------------------
from BVH.bvhConverter import BVH
#-------------------------------------------------------------------------------------------
#from Smooth.smoothing import Smooth
#-------------------------------------------------------------------------------------------
from principleComponentAnalysis import PCA
#-------------------------------------------------------------------------------------------
import numpy as np
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETONNXSubProblem():
def __init__(self,
context,
configPath:str,
modelPath:str,
partName:str,
completelyDisablePCACode = 0
):
#self.options = context.sess_options
self.options = ort.SessionOptions()
#-------------------------------------------------------------------------------
self.useOutputLimits = True #Careful, this should always be on!
self.partName = partName
self.configPath = configPath
self.configuration = parseConfiguration(configPath)
self.part = self.configuration["OutputDirectory"]
self.inputName = "input_all"
self.modelPath = modelPath
self.modelDirectory = os.path.dirname(self.modelPath)
self.frameNumber = 0
#-------------------------------------------------------------------------------
onnxModelForCheck = onnx.load(modelPath)
onnx.checker.check_model(onnxModelForCheck)
print("ONNX devices available : ", ort.get_device())
providers = ['CPUExecutionProvider']
#providers = ['CUDAExecutionProvider']
self.model = ort.InferenceSession(modelPath, providers=providers, sess_options=self.options)
for i in range(0,len(self.model.get_inputs())):
print("ONNX INPUTS ",self.model.get_inputs()[i].name)
self.inputName = self.model.get_inputs()[i].name
self.model_input_name = self.model.get_inputs()
#-------------------------------------------------------------------------------
self.inputsWithNSRM = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkInputs.list"))
self.inputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkJoints.list"))
self.outputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkOutputs.list"))
self.configuration = parseConfigurationInputJointMap(self.configuration,self.inputs)
self.serial = parseSerialNumberFromSummary(self.modelDirectory+"/summary.html")
#-------------------------------------------------------------------------------
self.inputReadyForTF = np.empty([2, 1])
self.NSRM = np.empty([2, 2])
#-------------------------------------------------------------------------------
self.emptyList = [0.0] * len(self.inputsWithNSRM)
self.emptyInput = np.asarray([self.emptyList],dtype=np.float32)
self.emptyList = [0.0] * len(self.outputs)
self.emptyOutput = np.asarray([self.emptyList],dtype=np.float32)
#-------------------------------------------------------------------------------
self.outputScalars = [1.0] * len(self.outputs)
self.outputOffsets = [0.0] * len(self.outputs)
self.outputMinima = [-6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
self.outputMaxima = [6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
#-------------------------------------------------------------------------------
self.outputOffsets = parseOutputNormalization(self.modelDirectory,"/outputOffsets.csv",self.outputs,self.outputOffsets)
self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalarsFraction.csv",self.outputs,self.outputScalars)
self.outputMinima = parseOutputNormalization(self.modelDirectory,"/outputMinima.csv",self.outputs,self.outputMinima)
self.outputMaxima = parseOutputNormalization(self.modelDirectory,"/outputMaxima.csv",self.outputs,self.outputMaxima)
#-------------------------------------------------------------------------------
if (self.outputs[0]=="depth"):
self.outputs[0]="hip_zposition"
#-------------------------------------------------------------------------------
print("Output Mapping :")
for jointID in range(0,len(self.outputs)):
#self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
#print(" - Output ",self.outputs[jointID]," limits [",self.outputMinima[jointID],",",self.outputMaxima[jointID],"] scalar ",self.outputScalars[jointID]," offset ",self.outputOffsets[jointID])
print("Out %s|Min %0.2f|Max %0.2f|Scalar %0.2f|Offset %0.2f"%(self.outputs[jointID],self.outputMinima[jointID],self.outputMaxima[jointID],self.outputScalars[jointID],self.outputOffsets[jointID]))
#-------------------------------------------------------------------------------
self.incompleteInput = 1
#-------------------------------------------------------------------------------
self.simulated = False
#-------------------------------------------------------------------------------
self.output = dict()
self.outputMinimumValue = dict()
self.outputMaximumValue = dict()
#-------------------------------------------------------------------------------
self.disablePCACode = completelyDisablePCACode
if (not self.disablePCACode):
self.decompositionEngine = initializeDecompositionForExecutionEngine(self.configuration,self.modelDirectory,self.partName,disablePCACode=self.disablePCACode)
#-------------------------------------------------------------------------------
#The default compatibility setting is the BMVC2019 2channel NSDM, however nowadays we use NSRM
numberOfChannelsPerNSDMElement=2
if (self.configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
#-------------------------------------------------------------------------------
if ("eigenPoses" in self.configuration):
if (self.configuration['eigenPoses']==1):
self.configuration['eigenPoseData'] = readGroundTruthFile(
self.configuration,
"Eigenposes",
"%s/2d_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.partName),
"%s/%s_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.configuration['outputMode'],self.partName), #configuration['outputMode'] is either bvh or 3d
1.0,
numberOfChannelsPerNSDMElement,
int(self.configuration['useRadians']),#useRadians,
0,#useHalfFloats
externalDecomposition=self.decompositionEngine
)
#-------------------------------------------------------------------------------
print("\n\n")
print("Inputs :",self.inputs)
print("Outputs :",self.outputs)
#-------------------------------------------------------------------------------
def getModel(self):
return self.model
def getModelFlops(self):
print("ONNX has no flops calculator")
return 0
def getModelParameters(self):
print("ONNX has no model parameters calculator")
return 0
def test(self):
#-------------------------------------------
thisInputONNX = { self.inputName : self.emptyInput}
output_names_onnx = [otp.name for otp in self.model.get_outputs()]
predictions = self.model.run(output_names_onnx,thisInputONNX)[0][0]
#-------------------------------------------
return 1
def prepareInput(self,input2D :dict,configuration : dict):
from readCSV import prepareInputG
thisFullInput, self.NSRM, thisInput, angleToRotate, missingRatio = prepareInputG(input2D,configuration,self.inputs,self.inputsWithNSRM,self.part,self.decompositionEngine,self.disablePCACode)
#appendCSVToFile(self.inputName+".csv",thisFullInput,fID=self.frameNumber) # <-----------------
inputReadyForTF = np.asarray([thisFullInput],dtype=np.float32)
return inputReadyForTF,missingRatio
def logProbabilisticOutput(self,outputFromNN,resolution=60,increment=6.0,numberOfJoints=30):
xs=list()
#----------------------------------
value = -180.0
inc = increment
for r in range(0,resolution):
xs.append(value)
value=value+inc
#----------------------------------
ys=list()
#----------------------------------
for j in range(0,numberOfJoints):
rs=list()
for r in range(0,resolution):
rs.append(outputFromNN[(j*resolution) + r])
ys.append(rs)
#----------------------------------
# Importing packages
import matplotlib.pyplot as plt
#plt.figure(figsize=(80,80))
plt.clf()
plt.title("Output Distributions %s "%(self.partName))
# Define data values
#print("Should plot %u lines"%numberOfJoints)
for j in range(0,numberOfJoints):
plt.plot(xs, ys[j], label='%s (#%u)' %(self.outputs[j],j))
#print("Plot %u"%j)
plt.legend()
#plt.show() #<-This blocks
plt.draw()
plt.pause(0.01)
"""
Convert a dictionary of 2D inputs to MocapNET output
(Whatever that may be [it is listed in self.inputs and self.outputs])
"""
def castProbabilisticOutputToDiscreteOutput(self, outputFromNN):
if ('probabilisticOutput' in self.configuration) and (self.configuration['probabilisticOutput']==1):
print(bcolors.OKGREEN,"DOING PROBABILISTIC OUTPUT",bcolors.ENDC)
#Resolution incrementation
inc = 10.0
#-------------------------
minV = -180.0
maxV = 180.0
resolution = 0 #<- gets automatically calculated as a function of inc..
#-------------------------
i = minV
while(i<maxV):
resolution = resolution + 1
i=i+inc
#-------------------------
numberOfJoints = int(len(outputFromNN) / resolution)
#Draw plot!
self.logProbabilisticOutput(outputFromNN,resolution=resolution,increment=inc,numberOfJoints=numberOfJoints)
pickedOutput = list()
for j in range(0,numberOfJoints):
bestChoice = 0
bestValue = 0
value = minV
for r in range(0,resolution):
if (outputFromNN[(j*resolution) + r]>bestValue):
bestValue = outputFromNN[(j*resolution + r)]
bestChoice = value
value=value+inc
pickedOutput.append(bestChoice)
#pickedOutput[0] = 0
#pickedOutput[1] = 0
pickedOutput[2] = -160
pickedOutput[3] = 0
pickedOutput[4] = 0
pickedOutput[5] = 0
return pickedOutput
return outputFromNN
"""
Convert a dictionary of 2D inputs to MocapNET output
(Whatever that maybe [it is listed in self.inputs and self.outputs])
"""
def predict(self, input2D:dict):
#print("Predict ",self.partName)
self.inputReadyForTF,missingRatio = self.prepareInput(input2D,self.configuration)
if (missingRatio>0.3):
eprint("Not running ",self.partName," due to missing joints ")#,input2D)
return self.output
#Turns out on some decompositions like FastICA there are a lot of zeros!
#-----------------------------------------------
#Save cycles by not executing an empty data blob
#-----------------------------------------------
self.incompleteInput = 0 #<- This needs to be set to 0 to mark input is received..!
#Cast and then run input through MocapNET
thisInputONNX = { self.inputName : self.inputReadyForTF }
output_names_onnx = [otp.name for otp in self.model.get_outputs()]
predictions = self.model.run(output_names_onnx,thisInputONNX)[0][0]
#predictions = self.model(self.inputReadyForTF,training=False)
#PROBABILISTIC MODE
if ('probabilisticOutput' in self.configuration) and (self.configuration['probabilisticOutput']==1):
predictions = self.castProbabilisticOutputToDiscreteOutput(predictions)
self.output = dict()
if (len(predictions)!=len(self.outputs)):
print(bcolors.FAIL,"Something bad happened.. the network regressed a different number of parameters (",len(predictions),") than what we expected (",len(self.outputs),") ",bcolors.ENDC)
raise IOError
#Go on with it
return self.output
#Values to list..
outputValueList = list()
for i in range (len(self.outputs)):
outputValueList.append(float(predictions[i]))
#==============================================================================================================
# THIS SHOULD BE COMMON IN TENSORFLOW/TF-LITE/ONNX
#==============================================================================================================
#Gather our numpy array output in the form of a labeled dictionary
if (self.useOutputLimits):
#Take into account output offsets/scaling
for i in range (len(self.outputs)):
#This should be the exact oposite of the operation in readCSV.py line 550
recoveredValue = (float(outputValueList[i]) * float(self.outputScalars[i])) + float(self.outputOffsets[i])
#---------------------------------------------------------------
if (recoveredValue > self.outputMaxima[i]):
recoveredValue = self.outputMaxima[i]
if (recoveredValue < self.outputMinima[i]):
recoveredValue = self.outputMinima[i]
#---------------------------------------------------------------
element = self.outputs[i]
self.output[element] = recoveredValue
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#---------------------------------------------------------------
else:
#Not using limits
for i in range (len(self.outputs)):
element = self.outputs[i]
self.output[element] = float(outputValueList[i])
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#==============================================================================================================
#==============================================================================================================
self.frameNumber = self.frameNumber + 1
return self.output
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class PoseNETONNX():
def __init__(
self,
modelPath:str="movenet/model.onnx",
targetWidth = 192,
targetHeight = 192,
trainingWidth = 1920,
trainingHeight = 1080,
):
#Tensorflow attempt to be reasonable
#------------------------------------------
from holisticPartNames import getPoseNETBodyNameList
self.jointNames = getPoseNETBodyNameList()
#------------------------------------------
import onnxruntime as ort
import onnx
onnxModelForCheck = onnx.load(modelPath)
onnx.checker.check_model(onnxModelForCheck)
print("ONNX devices available : ", ort.get_device())
providers = ['CPUExecutionProvider']
#providers = ['CUDAExecutionProvider']
self.options = ort.SessionOptions()
self.model = ort.InferenceSession(modelPath, providers=providers, sess_options=self.options)
for i in range(0,len(self.model.get_inputs())):
print("ONNX INPUTS ",self.model.get_inputs()[i].name)
self.inputName = self.model.get_inputs()[i].name
self.model_input_name = self.model.get_inputs()
#------------------------------------------
self.output = dict()
self.hz = 0.0
self.targetWidth = targetWidth
self.targetHeight = targetHeight
self.trainingWidth = trainingWidth
self.trainingHeight = trainingHeight
#------------------------------------------
def get2DOutput(self):
return self.output
def convertImageToMocapNETInput(self,image,doFlipX=False,threshold=0.05):
import tensorflow as tf
import numpy as np
import time
import cv2
sourceWidth = image.shape[1]
sourceHeight = image.shape[0]
currentAspectRatio=self.targetWidth/self.targetHeight
trainedAspectRatio=self.trainingWidth/self.trainingHeight
#Do resize on OpenCV end
#----------------------------------------------------------------
from tools import img_resizeWithCrop,normalizedCoordinatesAdaptForVerticalImage,normalizedCoordinatesAdaptToResizedCrop
imageTransformed = img_resizeWithCrop(image,self.targetWidth,self.targetHeight)
#imageTransformed = img_resizeWithPadding(image,self.targetWidth,self.targetHeight)
imageTransformed = cv2.cvtColor(imageTransformed,cv2.COLOR_BGR2RGB)
#----------------------------------------------------------------
#Hand image to Tensorflow
#----------------------------------------------------------------
imageONNX = np.expand_dims(imageTransformed, axis=0)
#-------------------------------------------------------------------
start = time.time()
#-------------------------------------------------------------------
#-------------------------------------------------------------------
thisInputONNX = { self.inputName : imageONNX.astype('int32')}
#Run input through MocapNET
output_names_onnx = [otp.name for otp in self.model.get_outputs()]
keypoints_with_scores = self.model.run(output_names_onnx,thisInputONNX)[0][0]
predictions = keypoints_with_scores[0]
#-------------------------------------------------------------------
#-------------------------------------------------------------------
seconds = time.time() - start
self.hz = 1 / (seconds+0.0001)
#print("MoveNET ONNX Framerate : ",round(self.hz,2)," fps ")
currentAspectRatio=sourceWidth/sourceHeight #We "change" aspect ratio by restoring points
for pointID in range(0,len(predictions)):
#Joints have y,x,acc order
nX,nY = normalizedCoordinatesAdaptToResizedCrop(sourceWidth,sourceHeight,self.targetWidth,self.targetHeight,predictions[pointID][1],predictions[pointID][0])
nX,nY = normalizedCoordinatesAdaptForVerticalImage(sourceWidth,sourceHeight,self.trainingWidth,self.trainingHeight,nX,nY)
predictions[pointID][1]=nX
predictions[pointID][0]=nY
from holisticPartNames import processPoseNETLandmarks
self.output = processPoseNETLandmarks(self.jointNames,predictions,currentAspectRatio,trainedAspectRatio,threshold=threshold,doFlipX=doFlipX)
#----------------------------------------------------------------
from MocapNETVisualization import drawPoseNETLandmarks
self.image = drawPoseNETLandmarks(predictions,image,threshold=threshold,jointLabels=self.jointNames)
#----------------------------------------------------------------
return self.output,image
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETONNX():
def __init__(self ):
print("""
██████╗ ███╗ ██╗███╗ ██╗██╗ ██╗
██╔═══██╗████╗ ██║████╗ ██║╚██╗██╔╝
██║ ██║██╔██╗ ██║██╔██╗ ██║ ╚███╔╝
██║ ██║██║╚██╗██║██║╚██╗██║ ██╔██╗
╚██████╔╝██║ ╚████║██║ ╚████║██╔╝ ██╗
╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═══╝╚═╝ ╚═╝""")
self.sess_options = ort.SessionOptions()
self.sess_options.log_severity_level = 3 #<- log_level
self.sess_options.intra_op_num_threads = 4
#self.sess_options.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL
self.sess_options.execution_mode = ort.ExecutionMode.ORT_PARALLEL
self.sess_options.inter_op_num_threads = 4
self.sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
mnet = MocapNETONNX()
print("Survived Test!")
#-------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,419 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import tensorflow as tf
import os
import sys
import time
#-------------------------------------------------------------------------------------------
from readCSV import parseConfiguration,parseConfigurationInputJointMap,transformNetworkInput,initializeDecompositionForExecutionEngine,readGroundTruthFile,readCSVFile,parseOutputNormalization
from NSDM import NSDMLabels,createNSDMUsingRules,inputIsEnoughToCreateNSDM,performNSRMAlignment
from EDM import EDMLabels,createEDMUsingRules
from tools import bcolors,checkIfFileExists,readListFromFile,convertListToLowerCase,secondsToHz,getEntryIndexInList,parseSerialNumberFromSummary
#-------------------------------------------------------------------------------------------
from BVH.bvhConverter import BVH
#-------------------------------------------------------------------------------------------
#from Smooth.smoothing import Smooth
#-------------------------------------------------------------------------------------------
from principleComponentAnalysis import PCA
#-------------------------------------------------------------------------------------------
import numpy as np
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETTFLiteSubProblem():
def __init__(self,
context,
configPath:str,
modelPath:str,
partName:str,
numberOfThreads = 4,
completelyDisablePCACode = 0
):
#-------------------------------------------------------------------------------
self.useOutputLimits = True #Careful, this should always be on!
self.partName = partName
self.configPath = configPath
self.configuration = parseConfiguration(configPath)
self.part = self.configuration["OutputDirectory"]
self.inputName = "input_all"
self.modelPath = modelPath
self.modelDirectory= os.path.dirname(self.modelPath)
self.frameNumber = 0
#-------------------------------------------------------------------------------
#The default compatibility setting is the BMVC2019 2channel NSDM, however nowadays we use NSRM
numberOfChannelsPerNSDMElement=2
if (self.configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
if ("eigenPoses" in self.configuration):
if (self.configuration['eigenPoses']==1):
self.configuration['eigenPoseData'] = readGroundTruthFile(
self.configuration,
"Eigenposes",
"%s/2d_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.partName ),
"%s/%s_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.configuration['outputMode'],self.partName), #configuration['outputMode'] is either bvh or 3d
1.0,
numberOfChannelsPerNSDMElement,
0,#useRadians,
0,#useHalfFloats
externalDecomposition=self.decompositionEngine
)
#-------------------------------------------------------------------------------
self.model = tf.lite.Interpreter(
model_path=self.modelPath,
num_threads=numberOfThreads
)
self.model.allocate_tensors()
self.input_details = self.model.get_input_details()
self.output_details = self.model.get_output_details()
# check the type of the input tensor
self.floating_model = self.input_details[0]['dtype'] == np.float32
#-------------------------------------------------------------------------------
self.inputsWithNSRM = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkInputs.list"))
self.inputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkJoints.list"))
self.outputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkOutputs.list"))
self.configuration = parseConfigurationInputJointMap(self.configuration,self.inputs)
self.serial = parseSerialNumberFromSummary(self.modelDirectory+"/summary.html")
#-------------------------------------------------------------------------------
self.inputReadyForTF = np.empty([2, 1])
self.NSRM = np.empty([2, 2])
#-------------------------------------------------------------------------------
self.outputScalars = [1.0] * len(self.outputs)
self.outputOffsets = [0.0] * len(self.outputs)
self.outputMinima = [-6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
self.outputMaxima = [6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
#-------------------------------------------------------------------------------
self.outputOffsets = parseOutputNormalization(self.modelDirectory,"/outputOffsets.csv",self.outputs,self.outputOffsets)
#self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalars.csv",self.outputs,self.outputScalars)
#for jointID in range(0,len(self.outputs)):
# self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalarsFraction.csv",self.outputs,self.outputScalars)
self.outputMinima = parseOutputNormalization(self.modelDirectory,"/outputMinima.csv",self.outputs,self.outputMinima)
self.outputMaxima = parseOutputNormalization(self.modelDirectory,"/outputMaxima.csv",self.outputs,self.outputMaxima)
#-------------------------------------------------------------------------------
if (self.outputs[0]=="depth"):
self.outputs[0]="hip_zposition"
#-------------------------------------------------------------------------------
print("Output Mapping :")
for jointID in range(0,len(self.outputs)):
#self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
#print("Output ",self.outputs[jointID]," min ",self.outputMinima[jointID]," max ",self.outputMaxima[jointID]," scalar ",self.outputScalars[jointID]," offset ",self.outputOffsets[jointID])
print("Out %s|Min %0.2f|Max %0.2f|Scalar %0.2f|Offset %0.2f"%(self.outputs[jointID],self.outputMinima[jointID],self.outputMaxima[jointID],self.outputScalars[jointID],self.outputOffsets[jointID]))
#-------------------------------------------------------------------------------
self.incompleteInput = 1
#-------------------------------------------------------------------------------
self.simulated = False
#-------------------------------------------------------------------------------
self.output = dict()
self.outputMinimumValue = dict()
self.outputMaximumValue = dict()
#-------------------------------------------------------------------------------
self.disablePCACode = completelyDisablePCACode
if (not self.disablePCACode):
self.decompositionEngine = initializeDecompositionForExecutionEngine(self.configuration,self.modelDirectory,self.partName,disablePCACode=self.disablePCACode)
#-------------------------------------------------------------------------------
print("\n\n")
print("Model Dir :",self.modelDirectory)
print("Inputs :",self.inputs)
print("Outputs :",self.outputs)
#-------------------------------------------------------------------------------
def getModel(self):
return self.model
def getModelFlops(self):
print("TF-Lite has no flops calculator")
return 0
def getModelParameters(self):
model = self.model
#concrete_func = model.signatures["serving_default"]
#print( concrete_func.inputs[0] )
#print( concrete_func.inputs[0].shape )
#inputShape = str(concrete_func.inputs[0].shape)
#inputShape = inputShape.strip("() ")
#inputShape = inputShape.replace(",", "x")
#inputShape = inputShape.replace("None", "1")
#inputShape = inputShape.strip(' ')
#print("Input Shape is : ",inputShape)
#------------------------------------------
totalParameters = 0
try:
trainableParams = np.sum([np.prod(v.get_shape()) for v in model.trainable_weights])
totalParameters = int(totalParameters + nonTrainableParams)
except:
print("Could not get model trainable parameters for TF-Lite model..!")
try:
nonTrainableParams = np.sum([np.prod(v.get_shape()) for v in model.non_trainable_weights])
totalParameters = int(totalParameters + nonTrainableParams)
except:
print("Could not get model non-trainable parameters for TF-Lite model..!")
return totalParameters
def test(self):
#-------------------------------------------
emptyList = [0.0] * len(self.inputsWithNSRM)
emptyInput =np.asarray([emptyList],dtype=np.float32)
#-------------------------------------------
#print("Running zeros ")
self.model.set_tensor(self.input_details[0]['index'],emptyInput)
self.model.invoke()
predictions = self.model.get_tensor(self.output_details[0]['index'])
#-------------------------------------------
return 1
def prepareInput(self,input2D :dict,configuration : dict):
from readCSV import prepareInputG
thisFullInput, self.NSRM, thisInput, angleToRotate, missingRatio = prepareInputG(input2D,configuration,self.inputs,self.inputsWithNSRM,self.part,self.decompositionEngine,self.disablePCACode)
inputReadyForTF = np.asarray([thisFullInput],dtype=np.float32)
return inputReadyForTF,missingRatio
"""
Convert a dictionary of 2D inputs to MocapNET output
(Whatever that maybe [it is listed in self.inputs and self.outputs])
"""
def predict(self,input2D :dict):
self.inputReadyForTF,missingRatio = self.prepareInput(input2D,self.configuration)
if (missingRatio>0.3):
print("Not running ",self.partName," due to missing joints ")
return self.output
#Turns out on some decompositions like FastICA there are a lot of zeros!
#-----------------------------------------------
#Save cycles by not executing an empty data blob
#-----------------------------------------------
self.incompleteInput = 0 #<- This needs to be set to 0 to mark input is received..!
#totalData = 1
#zeroData = 0
#for element in self.inputReadyForTF[0].tolist():
# #print("ELEMENT ",element)
# totalData = totalData + 1
# if ( (element<0.005) and (element>-0.005) ):
# zeroData=zeroData + 1
#missingRatio = zeroData/totalData
#print("Missing Ratio : ",missingRatio)
#if (missingRatio>0.4):
# print(bcolors.FAIL,"Not executing NN with empty data ",bcolors.ENDC)
# #Reset armature..!
# for k in self.output.keys():
# self.output[k]=0.0
# self.incompleteInput = 1
# return self.output
#-----------------------------------------------
self.model.set_tensor(self.input_details[0]['index'],self.inputReadyForTF)
self.model.invoke()
predictions = self.model.get_tensor(self.output_details[0]['index'])
self.output = dict()
if (len(predictions[0])!=len(self.outputs)):
print(bcolors.FAIL,"Something bad happened.. the ",self.partName," network regressed a different number of parameters (",len(predictions[0]),") than what we expected (",len(self.outputs),") ",bcolors.ENDC)
raise IOError
return self.output
#Values to list..
outputValueList = list()
for i in range (len(self.outputs)):
outputValueList.append(float(predictions[0][i]))
#==============================================================================================================
# THIS SHOULD BE COMMON IN TENSORFLOW/TF-LITE/ONNX
#==============================================================================================================
#Gather our numpy array output in the form of a labeled dictionary
if (self.useOutputLimits):
#Take into account output offsets/scaling
for i in range (len(self.outputs)):
#This should be the exact oposite of the operation in readCSV.py line 550
recoveredValue = (float(outputValueList[i]) * float(self.outputScalars[i])) + float(self.outputOffsets[i])
#---------------------------------------------------------------
if (recoveredValue > self.outputMaxima[i]):
recoveredValue = self.outputMaxima[i]
if (recoveredValue < self.outputMinima[i]):
recoveredValue = self.outputMinima[i]
#---------------------------------------------------------------
element = self.outputs[i]
self.output[element] = recoveredValue
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#---------------------------------------------------------------
else:
#Not using limits
for i in range (len(self.outputs)):
element = self.outputs[i]
self.output[element] = float(outputValueList[i])
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#==============================================================================================================
#==============================================================================================================
self.frameNumber = self.frameNumber + 1
return self.output
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class PoseNETTFLite():
def __init__(
self,
modelPath:str="movenet/lite-model_movenet_singlepose_lightning_tflite_int8_4.tflite",
targetWidth = 192,
targetHeight = 192,
numberOfThreads = 4,
trainingWidth = 1920,
trainingHeight = 1080,
):
#Tensorflow attempt to be reasonable
#------------------------------------------
from holisticPartNames import getPoseNETBodyNameList
self.jointNames = getPoseNETBodyNameList()
#------------------------------------------
import tensorflow as tf
# Initialize the TFLite interpreter
self.interpreter = tf.lite.Interpreter(model_path=modelPath,num_threads=numberOfThreads)
self.interpreter.allocate_tensors()
#------------------------------------------
self.output = dict()
self.hz = 0.0
self.targetWidth = targetWidth
self.targetHeight = targetHeight
self.trainingWidth = trainingWidth
self.trainingHeight = trainingHeight
#------------------------------------------
def get2DOutput(self):
return self.output
def convertImageToMocapNETInput(self,image,doFlipX=False,threshold=0.05):
import tensorflow as tf
import numpy as np
import time
import cv2
sourceWidth = image.shape[1]
sourceHeight = image.shape[0]
currentAspectRatio=self.targetWidth/self.targetHeight
trainedAspectRatio=self.trainingWidth/self.trainingHeight
#Do resize on OpenCV end
#----------------------------------------------------------------
from tools import img_resizeWithCrop,normalizedCoordinatesAdaptForVerticalImage,normalizedCoordinatesAdaptToResizedCrop
imageTransformed = img_resizeWithCrop(image,self.targetWidth,self.targetHeight)
#imageTransformed = img_resizeWithPadding(image,self.targetWidth,self.targetHeight)
imageTransformed = cv2.cvtColor(imageTransformed,cv2.COLOR_BGR2RGB)
#----------------------------------------------------------------
#Prepare image for Tensorflow
#----------------------------------------------------------------
imageTF = np.expand_dims(imageTransformed, axis=0).astype('int32')
#----------------------------------------------------------------
# TF Lite format expects tensor type of float32.
input_image = tf.cast(imageTF, dtype=tf.uint8) # tf.float32
input_details = self.interpreter.get_input_details()
output_details = self.interpreter.get_output_details()
#-------------------------------------------------------------------
start = time.time()
#-------------------------------------------------------------------
#-------------------------------------------------------------------
self.interpreter.set_tensor(input_details[0]['index'], input_image.numpy())
self.interpreter.invoke()
keypoints_with_scores = self.interpreter.get_tensor(output_details[0]['index']) # Output is a [1, 1, 17, 3] numpy array.
predictions = keypoints_with_scores[0][0]
#-------------------------------------------------------------------
#-------------------------------------------------------------------
seconds = time.time() - start
self.hz = 1 / (seconds+0.0001)
#print("MoveNET TFLite Framerate : ",round(self.hz,2)," fps ")
currentAspectRatio=sourceWidth/sourceHeight #We "change" aspect ratio by restoring points
for pointID in range(0,len(predictions)):
#Joints have y,x,acc order
nX,nY = normalizedCoordinatesAdaptToResizedCrop(sourceWidth,sourceHeight,self.targetWidth,self.targetHeight,predictions[pointID][1],predictions[pointID][0])
nX,nY = normalizedCoordinatesAdaptForVerticalImage(sourceWidth,sourceHeight,self.trainingWidth,self.trainingHeight,nX,nY)
predictions[pointID][1]=nX
predictions[pointID][0]=nY
from holisticPartNames import processPoseNETLandmarks
self.output = processPoseNETLandmarks(self.jointNames,predictions,currentAspectRatio,trainedAspectRatio,threshold=threshold,doFlipX=doFlipX)
#------------------------------------------------
from MocapNETVisualization import drawPoseNETLandmarks
self.image = drawPoseNETLandmarks(predictions,image,threshold=threshold,jointLabels=self.jointNames)
#------------------------------------------------
return self.output,image
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETTFLite():
def __init__(self,):
print("""
████████╗███████╗ ██╗ ██╗████████╗███████╗
╚══██╔══╝██╔════╝ ██║ ██║╚══██╔══╝██╔════╝
██║ █████╗█████╗██║ ██║ ██║ █████╗
██║ ██╔══╝╚════╝██║ ██║ ██║ ██╔══╝
██║ ██║ ███████╗██║ ██║ ███████╗
╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚══════╝""")
#-------------------------------------------------------------------------------
#do nothing :P
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
mnet = MocapNETTFLite()
print("Survived Test!")
#-------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,530 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
#-------------------------------------------------------------------------------------------
from readCSV import parseConfiguration,parseConfigurationInputJointMap,transformNetworkInput,initializeDecompositionForExecutionEngine,readGroundTruthFile,readCSVFile,parseOutputNormalization
from NSDM import NSDMLabels,createNSDMUsingRules,inputIsEnoughToCreateNSDM,performNSRMAlignment
from EDM import EDMLabels,createEDMUsingRules
from tools import bcolors,checkIfFileExists,readListFromFile,convertListToLowerCase,secondsToHz,getEntryIndexInList,parseSerialNumberFromSummary
#-------------------------------------------------------------------------------------------
from BVH.bvhConverter import BVH
#-------------------------------------------------------------------------------------------
#from Smooth.smoothing import Smooth
#-------------------------------------------------------------------------------------------
from principleComponentAnalysis import PCA
#-------------------------------------------------------------------------------------------
import time
import os
import numpy as np
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class MocapNETTensorflowSubProblem():
def __init__(self,
context,
configPath:str,
modelPath:str,
partName:str,
device:str="/device:GPU:0",
doPerformanceProfiling = False,
tensorboard = 0,
completelyDisablePCACode = 0
):
#-------------------------------------------------------------------------------
self.useOutputLimits = True #Careful, this should always be on!
self.partName = partName
self.configPath = configPath
from readCSV import parseConfiguration
self.configuration = parseConfiguration(configPath)
self.part = partName#self.configuration["OutputDirectory"]
self.modelPath = modelPath
self.modelDirectory= os.path.dirname(self.modelPath)
from DNNModel import loadNewModel
self.model = loadNewModel(modelPath)
self.device = device
self.frameNumber = 0
#-------------------------------------------------------------------------------
#The default compatibility setting is the BMVC2019 2channel NSDM, however nowadays we use NSRM
numberOfChannelsPerNSDMElement=2
if (self.configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
if ("eigenPoses" in self.configuration):
if (self.configuration['eigenPoses']==1):
self.configuration['eigenPoseData'] = readGroundTruthFile(
self.configuration,
"Eigenposes",
"%s/2d_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.partName ),
"%s/%s_%s_eigenposes.csv" % (os.path.dirname(self.modelPath),self.configuration['outputMode'],self.partName), #configuration['outputMode'] is either bvh or 3d
1.0,
numberOfChannelsPerNSDMElement,
0,#useRadians,
0,#useHalfFloats
externalDecomposition=self.decompositionEngine
)
#-------------------------------------------------------------------------------
import tensorflow as tf
rmsprop=tf.keras.optimizers.RMSprop(learning_rate=0.002, rho=0.9, epsilon=tf.keras.backend.epsilon())
self.model.compile(
optimizer=rmsprop,
loss='mse',
metrics=['mae', 'acc'],
jit_compile=True #<- this may cause trouble on non-XLA builds?
)
self.modelKeras = self.model
#print("MocapNET Model for ",partName," has the following signatures ",self.model.signatures)
self.model = self.model.signatures['serving_default']
self.profile = doPerformanceProfiling
self.tensorboard = tensorboard
#-------------------------------------------------------------------------------
self.inputsWithNSRM = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkInputs.list"))
self.inputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkJoints.list"))
self.outputs = convertListToLowerCase(readListFromFile(self.modelDirectory+"/neuralNetworkOutputs.list"))
self.configuration = parseConfigurationInputJointMap(self.configuration,self.inputs)
self.serial = parseSerialNumberFromSummary(self.modelDirectory+"/summary.html")
#-------------------------------------------------------------------------------
self.inputReadyForTF = np.empty([2, 1])
self.NSRM = np.empty([2, 2])
#-------------------------------------------------------------------------------
self.outputScalars = [1.0] * len(self.outputs)
self.outputOffsets = [0.0] * len(self.outputs)
self.outputMinima = [-6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
self.outputMaxima = [6000.0] * len(self.outputs) #huge limit that essentially doesn't limit anything
#-------------------------------------------------------------------------------
self.outputOffsets = parseOutputNormalization(self.modelDirectory,"/outputOffsets.csv",self.outputs,self.outputOffsets)
#self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalars.csv",self.outputs,self.outputScalars)
#for jointID in range(0,len(self.outputs)):
# self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
self.outputScalars = parseOutputNormalization(self.modelDirectory,"/outputScalarsFraction.csv",self.outputs,self.outputScalars)
self.outputMinima = parseOutputNormalization(self.modelDirectory,"/outputMinima.csv",self.outputs,self.outputMinima)
self.outputMaxima = parseOutputNormalization(self.modelDirectory,"/outputMaxima.csv",self.outputs,self.outputMaxima)
#-------------------------------------------------------------------------------
if (self.outputs[0]=="depth"):
self.outputs[0]="hip_zposition"
#-------------------------------------------------------------------------------
print("Output Mapping :")
for jointID in range(0,len(self.outputs)):
#self.outputScalars[jointID] = 1 / float(self.outputScalars[jointID])
#print("Output ",self.outputs[jointID]," min ",self.outputMinima[jointID]," max ",self.outputMaxima[jointID]," scalar ",self.outputScalars[jointID]," offset ",self.outputOffsets[jointID])
print("Out %s|Min %0.2f|Max %0.2f|Scalar %0.2f|Offset %0.2f"%(self.outputs[jointID],self.outputMinima[jointID],self.outputMaxima[jointID],self.outputScalars[jointID],self.outputOffsets[jointID]))
#-------------------------------------------------------------------------------
self.networkInputList = [0.0] * len(self.inputsWithNSRM)
self.networkInput = np.asarray([self.networkInputList],dtype=np.float32)
#-------------------------------------------------------------------------------
self.incompleteInput = 1
#-------------------------------------------------------------------------------
self.simulated = False
#-------------------------------------------------------------------------------
self.output = dict()
self.outputMinimumValue = dict()
self.outputMaximumValue = dict()
#-------------------------------------------------------------------------------
self.disablePCACode = completelyDisablePCACode
if (not self.disablePCACode):
self.decompositionEngine = initializeDecompositionForExecutionEngine(self.configuration,self.modelDirectory,self.partName,disablePCACode=self.disablePCACode)
#-------------------------------------------------------------------------------
print("\n\n")
print("Inputs :",self.inputs)
print("Outputs :",self.outputs)
#-------------------------------------------------------------------------------
def getModel(self):
return self.modelKeras
def getModelFlops(self):
import tensorflow as tf
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2_as_graph
model = self.modelKeras
concrete = tf.function(lambda inputs: model(inputs))
concrete_func = concrete.get_concrete_function(
[tf.TensorSpec([1, *inputs.shape[1:]]) for inputs in model.inputs])
frozen_func, graph_def = convert_variables_to_constants_v2_as_graph(concrete_func)
with tf.Graph().as_default() as graph:
tf.graph_util.import_graph_def(graph_def, name='')
run_meta = tf.compat.v1.RunMetadata()
opts = tf.compat.v1.profiler.ProfileOptionBuilder.float_operation()
flops = tf.compat.v1.profiler.profile(graph=graph, run_meta=run_meta, cmd="op", options=opts)
totalFLOPS = int(flops.total_float_ops)
return totalFLOPS
return 0
def getModelParameters(self):
model = self.modelKeras
#------------------------------------------------------------------------------------------
trainableParams = np.sum([np.prod(v.get_shape()) for v in model.trainable_weights])
nonTrainableParams = np.sum([np.prod(v.get_shape()) for v in model.non_trainable_weights])
totalParameters = int(trainableParams + nonTrainableParams)
return totalParameters
def test(self):
#-------------------------------------------
emptyList = [0.0] * len(self.inputsWithNSRM)
emptyInput =np.asarray([emptyList],dtype=np.float32)
#-------------------------------------------
#print(bcolors.FAIL,"Running zeros ",bcolors.ENDC)
import tensorflow as tf
outputs = self.model(tf.cast(emptyInput,dtype=tf.float32)) #,training=False
#print("Outputs : ",outputs)
#print("Output Keys", outputs.keys())
outKey = list(outputs.keys())[0]
outputsRaw = outputs[outKey]
predictions = outputsRaw
#predictions = self.model(emptyInput,training=False)
#print("MocapNET result = ",predictions)
#-------------------------------------------
return 1
def prepareInput(self,input2D :dict,configuration : dict):
from readCSV import prepareInputG
thisFullInput, self.NSRM, thisInput, angleToRotate, missingRatio = prepareInputG(input2D,configuration,self.inputs,self.inputsWithNSRM,self.part,self.decompositionEngine,self.disablePCACode)
#i=0
#for value in thisFullInput:
# self.networkInput[i]=value
# i=i+1
#import tensorflow as tf
#self.networkInput = tf.convert_to_tensor(self.networkInputNumpy)
self.networkInput = np.asarray([thisFullInput],dtype=np.float32)
return self.networkInput,missingRatio
#-----------------------------
#inputReadyForTF = np.asarray([thisFullInput],dtype=np.float32)
#return inputReadyForTF
"""
Convert a dictionary of 2D inputs to MocapNET output
(Whatever that maybe [it is listed in self.inputs and self.outputs])
"""
def predict(self,input2D :dict):
#This call works @ 400Hz
#--------------------------------------------------------------------------------------
self.inputReadyForTF,missingRatio = self.prepareInput(input2D,self.configuration)
if (missingRatio>0.3):
print("Not running ",self.partName," due to missing joints ")
return self.output
#Turns out on some decompositions like FastICA there are a lot of zeros!
#-----------------------------------------------
#Save cycles by not executing an empty data blob
#-----------------------------------------------
self.incompleteInput = 0 #<- This needs to be set to 0 to mark input is received..!
#totalData = 1
#zeroData = 0
#for element in self.inputReadyForTF[0].tolist():
# #print("ELEMENT ",element)
# totalData = totalData + 1
# if ( (element<0.005) and (element>-0.005) ):
# zeroData=zeroData + 1
#missingRatio = zeroData/totalData
#print("Missing Ratio : ",missingRatio)
#if (missingRatio>0.4):
# print(bcolors.FAIL,"Not executing NN with empty data ",bcolors.ENDC)
# #Reset armature..!
# for k in self.output.keys():
# self.output[k]=0.0
#
# self.incompleteInput = 1
# return self.output
#--------------------------------------------------------------------------------------
predictions = list()
self.output = dict()
#--------------------------------------------------------------------------------------
if (self.profile):
#Run input through MocapNET and Profile code (slower)
print(bcolors.WARNING,"WARNING: Profiling NN enabled, execution will be slower",bcolors.ENDC)
predictions = self.modelKeras.predict(self.inputReadyForTF,callbacks = [self.tensorboard])
else:
#As stated in https://github.com/keras-team/keras/blob/v2.8.0/keras/engine/training.py#L1825-L2012 :
# and https://keras.io/getting_started/faq/#whats-the-difference-between-model-methods-predict-and-call
import tensorflow as tf
with tf.device(self.device):
#with tf.device('/device:CPU:0'):
inferenceOutputs = self.model(tf.cast(self.inputReadyForTF,dtype=tf.float32)) # ,training=False We shouldn't run predict to get as fast results as possible
#print("Outputs : ",outputs)
#print("Output Keys", outputs.keys())
outKey = list(inferenceOutputs.keys())[0]
outputsRaw = inferenceOutputs[outKey]
#outputsRaw = outputs['result_all']
predictions = outputsRaw
#--------------------------------------------------------------------------------------
if (len(predictions)>0):
if(len(predictions[0])!=len(self.outputs)):
print(bcolors.FAIL,"Something bad happened.. the network regressed a different number of parameters than what we expected",bcolors.ENDC)
raise IOError
return self.output
#Values to list..
outputValueList = list()
for i in range (len(self.outputs)):
outputValueList.append(float(predictions[0][i]))
#==============================================================================================================
# THIS SHOULD BE COMMON IN TENSORFLOW/TF-LITE/ONNX
#==============================================================================================================
#Gather our numpy array output in the form of a labeled dictionary
if (self.useOutputLimits):
#Take into account output offsets/scaling
for i in range (len(self.outputs)):
#This should be the exact oposite of the operation in readCSV.py line 550
recoveredValue = (float(outputValueList[i]) * float(self.outputScalars[i])) + float(self.outputOffsets[i])
#---------------------------------------------------------------
if (recoveredValue > self.outputMaxima[i]):
recoveredValue = self.outputMaxima[i]
if (recoveredValue < self.outputMinima[i]):
recoveredValue = self.outputMinima[i]
#---------------------------------------------------------------
element = self.outputs[i]
self.output[element] = recoveredValue
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#---------------------------------------------------------------
else:
#Not using limits
for i in range (len(self.outputs)):
element = self.outputs[i]
self.output[element] = float(outputValueList[i])
self.outputMinimumValue[element] = float(self.outputMinima[i])
self.outputMaximumValue[element] = float(self.outputMaxima[i])
#==============================================================================================================
#==============================================================================================================
self.frameNumber = self.frameNumber + 1
return self.output
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
class PoseNET():
def __init__(
self,
modelPath:str="movenet/",
targetWidth = 192,
targetHeight = 192,
trainingWidth = 1920,
trainingHeight = 1080,
):
#Tensorflow attempt to be reasonable
#------------------------------------------
from holisticPartNames import getPoseNETBodyNameList
self.jointNames = getPoseNETBodyNameList()
import tensorflow as tf
self.model = tf.saved_model.load(modelPath)
self.movenet = self.model.signatures['serving_default']
#------------------------------------------
self.output = dict()
self.hz = 0.0
self.targetWidth = targetWidth
self.targetHeight = targetHeight
self.trainingWidth = trainingWidth
self.trainingHeight = trainingHeight
#------------------------------------------
def get2DOutput(self):
return self.output
def convertImageToMocapNETInput(self,image,doFlipX=False,threshold=0.05):
import tensorflow as tf
import numpy as np
import time
import cv2
sourceWidth = image.shape[1]
sourceHeight = image.shape[0]
currentAspectRatio=self.targetWidth/self.targetHeight
trainedAspectRatio=self.trainingWidth/self.trainingHeight
#Do resize on OpenCV end
#----------------------------------------------------------------
from tools import img_resizeWithCrop,normalizedCoordinatesAdaptForVerticalImage,normalizedCoordinatesAdaptToResizedCrop
imageTransformed = img_resizeWithCrop(image,self.targetWidth,self.targetHeight)
#imageTransformed = img_resizeWithPadding(image,self.targetWidth,self.targetHeight)
imageTransformed = cv2.cvtColor(imageTransformed,cv2.COLOR_BGR2RGB)
#----------------------------------------------------------------
#Prepare image for Tensorflow
#----------------------------------------------------------------
imageTF = np.expand_dims(imageTransformed, axis=0).astype('int32')
#----------------------------------------------------------------
start = time.time()
# TF Lite format expects tensor type of float32.
#-------------------------------------------------------------------
#-------------------------------------------------------------------
outputs = self.movenet(tf.cast(imageTF, dtype=tf.int32))
keypoints_with_scores = outputs['output_0']
predictionsRaw = keypoints_with_scores[0][0]
#-------------------------------------------------------------------
#-------------------------------------------------------------------
seconds = time.time() - start
self.hz = 1 / (seconds+0.0001)
#print("MoveNET Framerate : ",round(self.hz,2)," fps ")
currentAspectRatio=sourceWidth/sourceHeight #We "change" aspect ratio by restoring points
predictions=list()
for pointID in range(0,len(predictionsRaw)):
#Joints have y,x,acc order
thisPoint = list()
thisPoint.append(float(predictionsRaw[pointID][0])) #y
thisPoint.append(float(predictionsRaw[pointID][1])) #x
thisPoint.append(float(predictionsRaw[pointID][2])) #score
nX,nY = normalizedCoordinatesAdaptToResizedCrop(sourceWidth,sourceHeight,self.targetWidth,self.targetHeight,thisPoint[1],thisPoint[0])
nX,nY = normalizedCoordinatesAdaptForVerticalImage(sourceWidth,sourceHeight,self.trainingWidth,self.trainingHeight,nX,nY)
thisPoint[0]= nY #Just update coords
thisPoint[1]= nX #Just update coords
predictions.append(thisPoint)
#-------------------------------------------------------------------
from holisticPartNames import processPoseNETLandmarks
self.output = processPoseNETLandmarks(self.jointNames,predictions,currentAspectRatio,trainedAspectRatio,threshold=threshold,doFlipX=doFlipX)
from MocapNETVisualization import drawPoseNETLandmarks
self.image = drawPoseNETLandmarks(predictions,image,threshold=threshold,jointLabels=self.jointNames)
#------------------------------------------------
return self.output,image
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
def get_available_devices():
from tensorflow.python.client import device_lib
local_device_protos = device_lib.list_local_devices()
return [x.name for x in local_device_protos if x.device_type == 'GPU' or x.device_type == 'CPU']
class MocapNETTensorflow():
def __init__(self,
doPerformanceProfiling = False,
):
print("""
████████╗███████╗███╗ ██╗███████╗ ██████╗ ██████╗ ███████╗██╗ ██████╗ ██╗ ██╗
╚══██╔══╝██╔════╝████╗ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝██║ ██╔═══██╗██║ ██║
██║ █████╗ ██╔██╗ ██║███████╗██║ ██║██████╔╝█████╗ ██║ ██║ ██║██║ █╗ ██║
██║ ██╔══╝ ██║╚██╗██║╚════██║██║ ██║██╔══██╗██╔══╝ ██║ ██║ ██║██║███╗██║
██║ ███████╗██║ ╚████║███████║╚██████╔╝██║ ██║██║ ███████╗╚██████╔╝╚███╔███╔╝
╚═╝ ╚══════╝╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚══════╝ ╚═════╝ ╚══╝╚══╝""")
self.doPerformanceProfiling = doPerformanceProfiling
#Tensorflow attempt to be reasonable
#------------------------------------------
import gc
gc.collect() #Do garbage collection before allocating TF stuff
import os
os.environ['TF_ENABLE_GPU_GARBAGE_COLLECTION']='false'
#Make sure CUDA cache is not disabled!
os.environ['CUDA_CACHE_DISABLE'] = '0'
#Try to presist cudnn
os.environ['TF_USE_CUDNN_BATCHNORM_SPATIAL_PERSISTENT'] = '1'
#Try to allocate as little memory as possible
os.environ['TF_FORCE_GPU_ALLOW_GROWTH'] = 'true'
#Use seperate threads so execution is not throttled by CPU
os.environ['TF_GPU_THREAD_MODE'] = 'gpu_private'
#0 = all messages are logged (default behavior)
#1 = INFO messages are not printed
#2 = INFO and WARNING messages are not printed
#3 = INFO, WARNING, and ERROR messages are not printed
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '0'
#improve the stability of the auto-tuning process used to select the fastest convolution algorithms
os.environ['TF_AUTOTUNE_THRESHOLD'] = '1'
#------------------------------------------
import tensorflow as tf
devices = get_available_devices()
print("Available Tensorflow devices are : ",devices)
self.device = '/device:CPU:0'
for device in devices:
if (device.find("GPU")!=-1):
self.device = device
print("Selecting device : ",self.device)
#If enabled, an op will be placed on CPU if any of the following are true
#1 - there's no GPU implementation for the OP
#2 - no GPU devices are known or registered
#3 - need to co-locate with reftype input(s) which are from CPU
tf.config.set_soft_device_placement(True)
#Only give the warning when not profiling otherwise we will get an error!
if (not doPerformanceProfiling):
tf.config.experimental.set_device_policy('explicit')
try:
tf.config.run_functions_eagerly(True)
tf.config.experimental.set_synchronous_execution(False)
except:
#Invalid device or cannot modify virtual devices once initialized.
pass
try:
physical_devices = tf.config.list_physical_devices('CPU')
tf.config.experimental.set_memory_growth(physical_devices[0], True)
physical_devices = tf.config.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(physical_devices[0], True)
except:
#Invalid device or cannot modify virtual devices once initialized.
pass
try:
tf.config.threading.set_intra_op_parallelism_threads(8)
tf.config.threading.set_inter_op_parallelism_threads(8)
except:
#Most probably : RuntimeError: Intra op parallelism cannot be modified after initialization
pass
if (doPerformanceProfiling):
import tensorflow as tf
self.tensorboard = tf.keras.callbacks.TensorBoard(log_dir = "profiling",histogram_freq = 1)
#tensorboard --bind_all --logdir profiling
from DNNModel import startProfiling
startProfiling()
else:
self.tensorboard=0
def __del__(self):
if (self.doPerformanceProfiling):
from DNNModel import stopProfiling
stopProfiling()
print("To see profile results \nUse :\n tensorboard --logdir profiling ")
print('TFLite stopped.')
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
mnet = MocapNETTensorflow()
print("Survived Test!")
#-------------------------------------------------------------------------------------------------------------------------------------------------------
File diff suppressed because it is too large Load Diff
+521
View File
@@ -0,0 +1,521 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import numpy as np
from enum import Enum
goFromDegreesToRad=np.float32(np.pi/180.0)
goFromRadToDegrees=np.float32(180.0/np.pi)
def getJoint2DDistancePoints(aX,aY,bX,bY):
xDistance=np.float32(bX-aX)
yDistance=np.float32(bY-aY)
return np.float32(np.sqrt( (xDistance*xDistance) + (yDistance*yDistance) ))
def getNumberOfSquaredCompressedSquaredJoints():
countList=len(getBodyNoHandsList())
numberOfSquaredCompressedJoints=countList*countList*2
return numberOfSquaredCompressedJoints
def getAngleToAlignToZero(iX,iY,jX,jY,NSRMNormalizeAngles=0):
#---------------------------------------------
if ( (iX==jX) and (iY==jY) ):
return np.float32(0.0)
#---------------------------------------------
#We have points a, b and c and we want to calculate angle b
aX= iX*100
aY= iY*100
#---------------------------------------------
bX= jX*100
bY= jY*100
#---------------------------------------------
lengthBetweenAAndB = getJoint2DDistancePoints(aX,aY,bX,bY)
#---------------------------------------------
cX= bX
cY= bY - lengthBetweenAAndB
#---------------------------------------------
#fprintf(stderr,"We want to align A(%0.2f,%0.2f) to C(%0.2f,%0.2f) with pivot B(%0.2f,%0.2f)\n",aX,aY,cX,cY,bX,bY)
#fprintf(stderr,"length AB = %0.2f\n",lengthBetweenAAndB);
#fprintf(stderr,"bY = %0.2f\n",bY);
#fprintf(stderr,"cY = %0.2f = %0.2f - %0.2f\n",cY,bY,lengthBetweenAAndB);
#Calulate vector a->b
abX = bX - aX
abY = bY - aY
#calculate vector c->b
cbX = bX - cX
cbY = bY - cY
#---------------------------------------------
dot = np.float32( (abX * cbX) + (abY * cbY) ) # dot product
cross = np.float32( (abX * cbY) - (abY * cbX) ) # cross product
#---------------------------------------------
alpha = np.arctan2(cross,dot) #arctan2 returns a value in the range [-pi, pi]
#---------------------------------------------
#fprintf(stderr,"Angle is %0.2f rad or %0.2f degrees \n",alpha,alpha*goFromRadToDegrees);
if (NSRMNormalizeAngles==2):
return np.float32( (2.0*alpha) / np.pi) # Normalize output in range [-1..1]
if (NSRMNormalizeAngles==1):
#This should actually be (2*alpha) / np.pi
#arctan(R) -> [ -pi/2 , pi/2]
return np.float32(alpha / np.pi) # Normalize output in range [-1/2..1/2]
else:
return np.float32(alpha) # Output in range [-pi..pi]
"""
This is the new function to make resolving 2D coordinates on a vector easier and safer (but slower :P)
"""
def getJoint2DXYV(rules,positions,jointName):
#------------------------------------------------------------------------------------------
x = np.float32(0.0)
y = np.float32(0.0)
visibility = np.float32(0.0)
#------------------------------------------------------------------------------------------
positionDataLength = len(positions)
if (positionDataLength==0):
print("getJoint2DXYV cannot resolve positions for joint ",jointName," with no vector data")
return x,y,visibility
if (not rules['inputJointMap'].checkJointListDimensions(positions)):
print("getJoint2DXYV cannot resolve positions for joint ",jointName," input joint map has a different dimension size..")
return x,y,visibility
#Get correct indexes for jointName
#--------------------------------------------------------
jID_X = rules['inputJointMap'].getJointID_2DX(jointName)
jID_Y = rules['inputJointMap'].getJointID_2DY(jointName)
jID_Vis = rules['inputJointMap'].getJointID_Visibility(jointName)
#--------------------------------------------------------
if ( (positionDataLength<=jID_X) or (positionDataLength<=jID_Y) or (positionDataLength<=jID_Vis) ):
print("getJoint2DXYV cannot get positions for joint ",jointName," with a vector data of only ",positionDataLength)
return x,y,visibility
#--------------------------------------------------------
if ( (jID_X==-1) or (jID_Y==-1) or (jID_Vis==-1) ):
print("getJoint2DXYV could not resolve joint ",jointName," with vector data of ",positionDataLength)
return x,y,visibility
#--------------------------------------------------------
#print("getJoint2DXYV(%s->%u/%u/%u) length %u"%(jointName,jID_X,jID_Y,jID_Vis,positionDataLength))
#Pedantic behavior on missing data
if (positions[jID_X]==0.0) or (positions[jID_Y]==0.0) or (positions[jID_Vis]==0.0):
return x,y,visibility
#------------------------------------
x = np.float32(positions[jID_X])
y = np.float32(positions[jID_Y])
visibility = np.float32(positions[jID_Vis])
#------------------------------------
return x,y,visibility
def rotate2DPointsTest(cx,cy,jX,jY,angleToRotateInRadians):
#-----------------------------------------------
s = np.float32( np.sin(angleToRotateInRadians) )
c = np.float32( np.cos(angleToRotateInRadians) )
#-----------------------------------------------
jX = np.float32(jX - cx)
jY = np.float32(jY - cy)
#-----------------------------------------------
xnew = np.float32( (jX * c) - (jY * s) )
ynew = np.float32( (jX * s) + (jY * c) )
#-----------------------------------------------
return xnew + cx , ynew + cy
def rotate2DPointsBasedOnJointAsCenter(rules,positions,angleToRotateInRadians,jointNameCenter):
if (len(positions)==0):
print("rotate2DPointsBasedOnJointAsCenter cannot work without input.. \n")
return positions
s = np.float32( np.sin(angleToRotateInRadians) )
c = np.float32( np.cos(angleToRotateInRadians) )
#--------------------------------------------------------
cx,cy,cVisibility = getJoint2DXYV(rules,positions,jointNameCenter)
#--------------------------------------------------------
if (cVisibility==0.0):
print("rotate2DPointsBasedOnJointAsCenter: cannot work without pivot joint .. \n")
return positions
result = positions
for jID in range(0,int(len(rules['NSDM'])) ):
#--------------------------------------------------------
jointName=rules['NSDM'][jID]['joint']
jX,jY,jVisibility = getJoint2DXYV(rules,positions,jointName)
#--------------------------------------------------------
#printf("Rotating point %0.2f,%0.2f using pivot %0.2f,%0.2f by %0.2f deg -> "%(jX,jY,cx,cy,angle))
#Translate point back to origin:
jX = np.float32(jX - cx)
jY = np.float32(jY - cy)
#Rotate point
xnew = np.float32( (jX * c) - (jY * s) )
ynew = np.float32( (jX * s) + (jY * c) )
#Translate point back:
jID_X = rules['inputJointMap'].getJointID_2DX(jointName)
jID_Y = rules['inputJointMap'].getJointID_2DY(jointName)
jID_Vis = rules['inputJointMap'].getJointID_Visibility(jointName)
#----------------------------------------------------------------
result[jID_X] = np.float32(xnew + cx)
result[jID_Y] = np.float32(ynew + cy)
result[jID_Vis] = np.float32(jVisibility)
#printf("%0.2f,%0.2f\n"%(result[jID*3+0],result[jID*3+1]));
return result
def performNSRMAlignment(thisInput,configuration):
angleToRotateInRadians = 0.0
NSRMUseAlignmentToPivot = configuration['eNSRM']
NSRMNormalizeAngles = 0
if ("NSRMNormalizeAngles" in configuration) and (configuration["NSRMNormalizeAngles"]==1):
NSRMNormalizeAngles = 1
if (NSRMUseAlignmentToPivot==1):
pivotPoint = configuration['Alignment'][0]['jointStart']
referencePoint = configuration['Alignment'][0]['jointEnd']
#-----------------------------------------------------------------------------------------------
if (pivotPoint!=referencePoint):
pivotX,pivotY,pivotVisibility = getJoint2DXYV(configuration,thisInput,pivotPoint)
#--------------------------------------------------------------------------------------------
referenceX,referenceY,referenceVisibility = getJoint2DXYV(configuration,thisInput,referencePoint)
#--------------------------------------------------------------------------------------------
if ((pivotVisibility!=0) and (referenceVisibility!=0)):
angleToRotateInRadians = getAngleToAlignToZero(pivotX,pivotY,referenceX,referenceY,NSRMNormalizeAngles)
rotatedInput = rotate2DPointsBasedOnJointAsCenter(configuration,thisInput,angleToRotateInRadians,pivotPoint)
return angleToRotateInRadians,rotatedInput
else:
print("Pivot Point ",pivotPoint," and Reference Point ",referencePoint," are the same\n")
#-----------------------------------------------------------------------------------------------
return angleToRotateInRadians,thisInput
def getCompositeLabel(jointA,jointB,xOffset,yOffset,virtualPointType):
labelI=jointA
labelIX=""
labelIY=""
if (virtualPointType==1):
if (xOffset<0):
labelIX="minus"
elif (xOffset>0):
labelIX="plus"
#----------------------------------
if (yOffset<0):
labelIY="minus"
elif (yOffset>0):
labelIY="plus"
#----------------------------------
labelI="virtual_"+jointA+"_x_"+labelIX+str(xOffset).replace('.','_').replace('-','_')+"_y_"+labelIY+str(yOffset).replace('.','_').replace('-','_')
elif (virtualPointType==2):
#----------------------------------
labelI="halfway_"+jointA+"_and_"+jointB
return labelI
def NSDMLabels(rules):
result=list()
useXY=1
useAngles=0
if (rules['NSDMAlsoUseAlignmentAngles']==1):
useXY=0
useAngles=1
numberOfNSDMRules=len(rules['NSDM'])
print("Rules Number ",numberOfNSDMRules)
for i in range(0,numberOfNSDMRules):
for j in range(0,numberOfNSDMRules):
if (i==j):
if (i==0):
result.append("NSRM-angleUsedFor2DRotation_%u"%(i))
else:
result.append("NSRM-scaleBetween_"+rules['NSDM'][i]['joint']+"_and_"+rules['NSDM'][i]['joint'])
else:
#-----------------------------------------------------------------
labelI = getCompositeLabel(
rules['NSDM'][i]['joint'],
rules['NSDM'][i]['halfWayFromThisAnd'],
rules['NSDM'][i]['xOffset'],
rules['NSDM'][i]['yOffset'],
rules['NSDM'][i]['isVirtual']
)
#-----------------------------------------------------------------
labelJ = getCompositeLabel(
rules['NSDM'][j]['joint'],
rules['NSDM'][j]['halfWayFromThisAnd'],
rules['NSDM'][j]['xOffset'],
rules['NSDM'][j]['yOffset'],
rules['NSDM'][j]['isVirtual']
)
#-----------------------------------------------------------------
if (useXY):
result.append("NSDM-%sX-%sX"%(labelI,labelJ))
result.append("NSDM-%sY-%sY"%(labelI,labelJ))
if (useAngles):
result.append("NSRM-%sY-%sY-Angle"%(labelI,labelJ))
#-----------------------------------------------------------------
#print("NSDM matrix will look like this ",result)
return result;
def inputIsEnoughToCreateNSDM(rules,thisInput):
numberOfNSDMRules=len(rules['NSDM'])
numberOfJointIDs =len(thisInput)
for i in range(0,numberOfNSDMRules):
jointName=rules['NSDM'][i]['joint']
if (not rules['inputJointMap'].getJointID_Exists(jointName)):
return False
return True
def getListOfMissingNSRMJoints(rules,thisInput):
missingList=list()
numberOfNSDMRules=len(rules['NSDM'])
numberOfJointIDs =len(thisInput)
for i in range(0,numberOfNSDMRules):
jointName=rules['NSDM'][i]['joint']
if (not rules['inputJointMap'].getJointID_Exists(jointName)):
missingList.append(jointName)
else:
iX,iY,iVisibility = getJoint2DXYV(rules,thisInput,jointName)
if (iVisibility==0.0):
missingList.append(jointName)
return missingList
def getCompositePoint(rules,i,thisInput):
#-----------------------------------------------------------
if (len(thisInput)==0):
print("getCompositePoint called with no input for element ",i)
return np.float32(0.0),np.float32(0.0),np.float32(0.0),1
#--------------------------------------------------------
invalidPoint = 0
jointName = rules['NSDM'][i]['joint']
#-----------------------------------------------------------
iX,iY,iVisibility = getJoint2DXYV(rules,thisInput,jointName)
#-----------------------------------------------------------
if ( iX!=0.0 and iY!=0.0 and iVisibility!=0.0 ):
#---------------------------------------------------------------------------
# Synthetic Points
#---------------------------------------------------------------------------
if (rules['NSDM'][i]['isVirtual']==1):
iX=iX+rules['NSDM'][i]['xOffset']
iY=iY+rules['NSDM'][i]['yOffset']
elif (rules['NSDM'][i]['isVirtual']==2):
secondTargetJointName=rules['NSDM'][i]['halfWayFromThisAnd']
secondTargetX,secondTargetY,secondTargetVisibility = getJoint2DXYV(rules,thisInput,secondTargetJointName)
if ((secondTargetX!=0.0) or (secondTargetY!=0.0)):
iX=np.float32((iX+secondTargetX)/2)
iY=np.float32((iY+secondTargetY)/2)
else:
invalidPoint = 1
iX = np.float32(0.0)
iY = np.float32(0.0)
iVisibility = np.float32(0.0)
#---------------------------------------------------------------------------
else:
#Added : Fixed bug! 11/5/2023
#If either of X,Y is zero we treat the point as completely invisible
invalidPoint = 1
iX = np.float32(0.0)
iY = np.float32(0.0)
iVisibility = np.float32(0.0)
#-----------------------------------------------------------
return iX,iY,iVisibility,invalidPoint
def createNSDMUsingRules(rules,thisInput,angleUsedToRotateInput):
result=list()
#-----------------------------------------------------------------------------------------------------
if (len(thisInput)==0):
print("createNSDMUsingRules called with no input")
return result
if (not rules['inputJointMap'].checkJointListDimensions(thisInput)):
print("createNSDMUsingRules called with incorrect input size ")
return thisInput
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
NSRMNormalizeAngles = 0
if ("NSRMNormalizeAngles" in rules) and (rules["NSRMNormalizeAngles"]==1):
NSRMNormalizeAngles = 1
doNormalization = (rules['NSDMNormalizationMasterSwitch']==1)
useXY = True
useAngles = False
if (rules['eNSRM']==1) or (rules['NSDMAlsoUseAlignmentAngles']==1):
useXY = False
useAngles = True
doNormalization = False
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
# ..Main NSRM parameters ..
#-----------------------------------------------------------------------------------------------------
numberOfNSDMRules=len(rules['NSDM'])
for i in range(0,numberOfNSDMRules):
#---------------------------------------------------------------------------
iX,iY,iVisibility,iInvalidPoint = getCompositePoint(rules,i,thisInput)
#---------------------------------------------------------------------------
for j in range(0,numberOfNSDMRules):
#---------------------------------------------------------------------------
jX,jY,jVisibility,jInvalidPoint = getCompositePoint(rules,j,thisInput)
#---------------------------------------------------------------------------
if (iInvalidPoint or jInvalidPoint):
#If any of the two joints is invalid, invalidate all output
if (useXY):
result.append(np.float32(0.0))
result.append(np.float32(0.0))
if (useAngles):
result.append(np.float32(0.0))
else:
if (useXY):
result.append(np.float32(iX-jX))
result.append(np.float32(iY-jY))
if (useAngles):
result.append(getAngleToAlignToZero(iX,iY,jX,jY,NSRMNormalizeAngles))
#---------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
# ..New eNSRM diagonal parameters ..
#-----------------------------------------------------------------------------------------------------
if (rules['eNSRM']==1):
elementID=0
#------------------------------------------------------------
iJointName=rules['NSDM'][0]['joint'] #Pivot point
iX,iY,iVisibility = getJoint2DXYV(rules,thisInput,iJointName)
#------------------------------------------------------------
for j in range(0,numberOfNSDMRules):
elementID = j * numberOfNSDMRules + j # Calculate diagonal elementID based on j
#---------------------------------------------------------------
jJointName = rules['NSDM'][j]['joint']
jX,jY,jVisibility = getJoint2DXYV(rules,thisInput,jJointName)
#---------------------------------------------------------------
if (jVisibility!=0.0) and (iVisibility!=0.0):
#Populate diagonal elements with distance from our pivot point
result[elementID] = getJoint2DDistancePoints(iX,iY,jX,jY)
else:
result[elementID] = np.float32(0.0)
#---------------------------------------------------------------
#Overwrite first (null) element of NSRM matrix with the angle used to rotate the input
result[0]=np.float32(angleUsedToRotateInput);
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
if (doNormalization):
#normalization is made for NSDM not xNSRM
#Normalizing results.. ---------------------------------------
numberOfNSDMScalingRules=len(rules['NormalizeNSDMBasedOn'])
if (numberOfNSDMScalingRules>0):
numberOfDistanceSamples=0
sumOfDistanceSamples=0.0
for i in range(0,numberOfNSDMScalingRules):
#------------------------------------------------------------------------
iJointName=rules['NormalizeNSDMBasedOn'][i]['jointStart']
iX,iY,iVisibility = getJoint2DXYV(rules,thisInput,iJointName)
#------------------------------------------------------------------------
jJointName=rules['NormalizeNSDMBasedOn'][i]['jointEnd']
jX,jY,jVisibility = getJoint2DXYV(rules,thisInput,jJointName)
#------------------------------------------------------------------------
if (iJointName==jJointName):
print("Error: Normalization Rule ",i," points to same start/end joint ",iJointID," == ",jJointID)
distance = getJoint2DDistancePoints(iX,iY,jX,jY)
if (distance>0.0):
numberOfDistanceSamples=numberOfDistanceSamples+1
sumOfDistanceSamples=sumOfDistanceSamples+distance
#-------------------------------------------------------------------------------------------------
scaleDistance=1.0
#-------------------------------------------------------------------------------------------------
if (numberOfDistanceSamples>0):
scaleDistance=sumOfDistanceSamples/numberOfDistanceSamples
#-------------------------------------------------------------------------------------------------
#print("NSDM Scale = ",scaleDistance," \n")
if (scaleDistance!=1.0):
for i in range(0,len(result)):
result[i]=np.float32(result[i]/scaleDistance)
#-------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------------
if (useXY):
for i in range(0,len(result)):
if (result[i]!=0.0):
result[i]=np.float32(0.5+result[i])
#-------------------------------------------------------------------------------------------------
#print(result)
#print("Result has ", len(result), " elements " )
#print("Result should have ", int( 2 * len(bodyWithoutHands) * len(bodyWithoutHands) ), " elements " )
return result;
if __name__ == '__main__':
print("NSDM.py is a library it cannot be run standalone")
sign = 1.0 #This is positive +1.0
iX=0.5; iY=0.5; jX=1.0; jY=1.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=0.5; jY=1.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=0.0; jY=1.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=1.0; jY=0.5
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=1.0; jY=0.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
iX=0.5; iY=0.5; jX=0.0; jY=0.0
a = getAngleToAlignToZero(iX,iY,jX,jY)
print("Points A(%0.2f,%0.2f) -> B(%0.2f,%0.2f) => angle %0.4f" %(iX,iY,jX,jY,a))
jX,jY = rotate2DPointsTest(iX,iY,jX,jY,sign * a)
print("Rotated it goes to -> B(%0.2f,%0.2f) => angle to align %0.4f" %(jX,jY,getAngleToAlignToZero(iX,iY,jX,jY)))
@@ -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)
#-----------------------------------------------------------
@@ -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)
@@ -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
@@ -0,0 +1,81 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
class JointDataMapper:
#-----------------------------------------------------------------
def __init__(self, csvFilename, configuration , jointLabels):
self.filename = csvFilename
self.jointLabelToJointIDMap = dict()
self.numberOfExpectedLabels = len(jointLabels)
jID = 0
for jointDescription in jointLabels:
self.jointLabelToJointIDMap[jointDescription.lower()]=jID
jID = jID+1
#-----------------------------------------------------------------
def checkJointListDimensions(self,jointLabels):
return self.numberOfExpectedLabels == len(jointLabels)
#-----------------------------------------------------------------
def getJointID_2DX(self,jointName):
nname = "2dx_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_2DX: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_2DY(self,jointName):
nname = "2dy_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_2DY: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_2DZ(self,jointName):
nname = "2dz_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_2DZ: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_3DX(self,jointName):
nname = "3dx_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_3DX: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_3DY(self,jointName):
nname = "3dy_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_3DY: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_3DZ(self,jointName):
nname = "3dz_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_3DZ: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_Visibility(self,jointName):
nname = "visible_"+jointName.lower()
if (not nname in self.jointLabelToJointIDMap):
print("getJointID_Visibility: Error resolving ",nname)
return -1
return self.jointLabelToJointIDMap[nname]
#-----------------------------------------------------------------
def getJointID_Exists(self,jointName):
nnameX = "2dx_"+jointName.lower()
nnameY = "2dy_"+jointName.lower()
if ((nnameX in self.jointLabelToJointIDMap) and (nnameY in self.jointLabelToJointIDMap)):
return True
return False
#-----------------------------------------------------------------
if __name__ == '__main__':
print("jointMap.py is a library it cannot be run standalone")
@@ -0,0 +1,622 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
#pip install mediapipe pandas pillow matplotlib opencv-python
import cv2
import mediapipe as mp
import numpy as np
import time
import sys
import os
from readCSV import parseConfiguration,zeroOutXYJointsThatAreInvisible,performNSRMAlignment
from NSDM import NSDMLabels,createNSDMUsingRules
from tools import secondsToHz,eprint
from MocapNET import MocapNET
mp_drawing = mp.solutions.drawing_utils
mp_holistic = mp.solutions.holistic
mp_face_mesh = mp.solutions.face_mesh
#------------------------------------------------------------------------------------------------
LEFT_EYE = [362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385,384, 398 ]
LEFT_IRIS = [474,475, 476, 477]
RIGHT_EYE = [33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161 , 246 ]
RIGHT_IRIS = [469, 470, 471, 472]
#------------------------------------------------------------------------------------------------
#I have added a seperate list with the joints
from holisticPartNames import getHolisticBodyNameList, getHolisticFaceNameList, getHolisticLHandNameList, getHolisticRHandNameList, processPoseLandmarks, guessLandmarks
#------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MEDIAPIPE_BODY_LANDMARK_NAMES = getHolisticBodyNameList()
MEDIAPIPE_FACE_LANDMARK_NAMES = getHolisticFaceNameList()
MEDIAPIPE_LHAND_LANDMARK_NAMES = getHolisticLHandNameList()
MEDIAPIPE_RHAND_LANDMARK_NAMES = getHolisticRHandNameList()
#------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class MediaPipePose():
def __init__(self,doMediapipeVisualization = False):
#Tensorflow attempt to be reasonable
#------------------------------------------
self.mp = mp_holistic.Holistic(static_image_mode=True)
#------------------------------------------
self.doMediapipeVisualization = doMediapipeVisualization
self.output = dict()
#------------------------------------------
def get2DOutput(self):
return self.output
def processIncomingBodyOnlyLandmarks(self,body,currentAspectRatio,trainedAspectRatio):
#This function runs ~10000Hz
#-----------------------------------------------
mnetPose2D = dict()
#------------------------------------------------------------------------------------
processPoseLandmarks(mnetPose2D,MEDIAPIPE_BODY_LANDMARK_NAMES ,body,currentAspectRatio,trainedAspectRatio)
#------------------------------------------------------------------------------------
guessLandmarks(mnetPose2D) #Some landmarks ( neck, hip need to be guessed by others )
#-----------------------------------------------
return mnetPose2D
def processIncomingAllLandmarks(self,landmarks,currentAspectRatio,trainedAspectRatio):
#This function runs ~10000Hz
#-----------------------------------------------
mnetPose2D = dict()
#------------------------------------------------------------------------------------
processPoseLandmarks(mnetPose2D,MEDIAPIPE_BODY_LANDMARK_NAMES ,landmarks.pose_landmarks,currentAspectRatio,trainedAspectRatio)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_LHAND_LANDMARK_NAMES,landmarks.left_hand_landmarks,currentAspectRatio,trainedAspectRatio,threshold=0.001)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_RHAND_LANDMARK_NAMES,landmarks.right_hand_landmarks,currentAspectRatio,trainedAspectRatio,threshold=0.001)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_FACE_LANDMARK_NAMES ,landmarks.face_landmarks,currentAspectRatio,trainedAspectRatio)
#------------------------------------------------------------------------------------
guessLandmarks(mnetPose2D) #Some landmarks ( neck, hip need to be guessed by others )
#-----------------------------------------------
return mnetPose2D
def convertImageToMocapNETInput(self,image):
#holistic = self.mp
if (type(image)==type(None)):
print("Invalid Image given, can't do anything with it")
return dict() , image
width = image.shape[1]
height = image.shape[0]
if ((width==0) or (height==0)):
print("Cannot work with empty image")
return dict() , image
#Try to speed up by scaling down image
#if ( (width>1024) or (height>720) ):
# width = int(image.shape[1]/2)
# height = int(image.shape[0]/2)
# image = cv2.resize(image, (width,height))
#The aspect ratios involved
currentAspectRatio = width/height
trainedAspectRatio = 1920/1080
#-----------------------------------------------
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_pose = mp.solutions.pose
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
mocapNETInput = dict()
with mp_pose.Pose(static_image_mode=True,smooth_landmarks=True,model_complexity=0,enable_segmentation=True,min_detection_confidence=0.5) as pose:
# with mp_holistic.Holistic(static_image_mode=True) as holistic:
start = time.time()
#-----------------------------------------------
results = pose.process(image)
#results = holistic.process(image)
#Draw the pose annotation on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
if (self.doMediapipeVisualization):
try:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACEMESH_TESSELATION) #This used to be called FACE_CONNECTIONS
except:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACE_CONNECTIONS) #This used to be called FACE_CONNECTIONS
mp_drawing.draw_landmarks(image, results.left_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
mp_drawing.draw_landmarks(image, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
mp_drawing.draw_landmarks(
image,
results.pose_landmarks,
mp_pose.POSE_CONNECTIONS,
landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style()
)
#Body only
#-----------------------------------------------
mocapNETInput = self.processIncomingBodyOnlyLandmarks(results.pose_landmarks,currentAspectRatio,trainedAspectRatio)
#mocapNETInput = self.processIncomingAllLandmarks(results,currentAspectRatio,trainedAspectRatio)
#-----------------------------------------------
end = time.time()
# Time elapsed
seconds = end - start
if (seconds==0.0):
seconds=1.0
# Calculate frames per second
fps = 1 / seconds
#print("Mediapipe Pose Only 2D Joint Estimation Framerate : ",round(fps,2)," fps \n", end="", flush=True)
self.output = mocapNETInput
return mocapNETInput,image
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
class MediaPipeHolistic():
def __init__(self,doMediapipeVisualization = False):
#Tensorflow attempt to be reasonable
#------------------------------------------
self.mp = mp_holistic.Holistic(
static_image_mode=False,
model_complexity=1, #1 = default complexity, 2 = high complexity
min_detection_confidence=0.2,
min_tracking_confidence=0.2
)
#------------------------------------------
#self.mpHands = mp.solutions.hands.Hands(
# min_detection_confidence=0.5,
# min_tracking_confidence=0.5
# )
#------------------------------------------
self.mpFace = mp_face_mesh.FaceMesh(
max_num_faces=1,
refine_landmarks=True,
min_detection_confidence=0.3,
min_tracking_confidence=0.3
)
#------------------------------------------
self.doMediapipeVisualization = doMediapipeVisualization
self.output = dict()
#------------------------------------------
def get2DOutput(self):
return self.output
def processIncomingHolisticLandmarks(self,face,lhand,rhand,body,currentAspectRatio,trainedAspectRatio):
mnetPose2D = dict()
#------------------------------------------------------------------------------------
processPoseLandmarks(mnetPose2D,MEDIAPIPE_BODY_LANDMARK_NAMES ,body ,currentAspectRatio,trainedAspectRatio,useVisibility=False)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_LHAND_LANDMARK_NAMES,lhand,currentAspectRatio,trainedAspectRatio,useVisibility=False)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_RHAND_LANDMARK_NAMES,rhand,currentAspectRatio,trainedAspectRatio,useVisibility=False)
processPoseLandmarks(mnetPose2D,MEDIAPIPE_FACE_LANDMARK_NAMES ,face ,currentAspectRatio,trainedAspectRatio,useVisibility=False)
#------------------------------------------------------------------------------------
guessLandmarks(mnetPose2D) #Some landmarks ( neck, hip need to be guessed by others )
#------------------------------------------------------------------------------------
return mnetPose2D
def convertImageToMocapNETInput(self,image):
holisticEstimator = self.mp
faceEstimator = self.mpFace
#handEstimator = self.mpHands
if (type(image)==type(None)):
print("Invalid Image given, can't do anything with it")
return dict() , image
#-----------------------------------------
width = image.shape[1]
height = image.shape[0]
if ((width==0) or (height==0)):
print("Cannot work with empty image")
return dict() , image
#-----------------------------------------
currentAspectRatio = width/height
trainedAspectRatio = 1920/1080
#-----------------------------------------
start = time.time()
#--------------------------------------------------------------------------------------------------
# To improve performance, optionally mark the image as not writeable to pass by reference.
image.flags.writeable = False
#==============================================
#================= MEDIAPIPE ==================
#==============================================
results = holisticEstimator.process(image)
resultsF = faceEstimator.process(image) #Extra Face
#resultsH = handEstimator.process(image)
#==============================================
# Draw the hand annotations on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
#--------------------------------------------------------------------------------------------------
end = time.time()
# Time elapsed
seconds = end - start
if (seconds==0.0):
seconds=1.0
# Calculate frames per second
fps = 1 / seconds
#print("Mediapipe Holistic 2D Joint Estimation Framerate : ",round(fps,2)," fps \n", end="", flush=True)
#annotated_image = image.copy()
annotated_image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) #Our annotated image must be BGR to show correctly
#--------------------------------------------------------------------------------------------------
if (self.doMediapipeVisualization):
#Compensate for name mediapipe change..
try:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACEMESH_TESSELATION) #This used to be called FACE_CONNECTIONS
except:
mp_drawing.draw_landmarks(annotated_image, results.face_landmarks , mp_holistic.FACE_CONNECTIONS) #This used to be called FACE_CONNECTIONS
#--------------------------------------------------------------------------------------------------
mp_drawing.draw_landmarks(annotated_image, results.left_hand_landmarks , mp_holistic.HAND_CONNECTIONS)
mp_drawing.draw_landmarks(annotated_image, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS)
#--------------------------------------------------------------------------------------------------
#for hand_landmarks in resultsH.multi_hand_landmarks:
# mp_drawing.draw_landmarks(annotated_image, hand_landmarks, mp_hands.HAND_CONNECTIONS)
#--------------------------------------------------------------------------------------------------
# Use mp_holistic.UPPER_BODY_POSE_CONNECTIONS for drawing below when upper_body_only is set to True.
mp_drawing.draw_landmarks(annotated_image, results.pose_landmarks , mp_holistic.POSE_CONNECTIONS)
#--------------------------------------------------------------------------------------------------
mocapNETInput = self.processIncomingHolisticLandmarks(
results.face_landmarks,
results.left_hand_landmarks,
results.right_hand_landmarks,
results.pose_landmarks,
currentAspectRatio,
trainedAspectRatio
)
#EYES
#--------------------------------------------------------------------------------------------
img_h, img_w = image.shape[:2]
if resultsF.multi_face_landmarks:
mesh_points=np.array([np.multiply([p.x, p.y], [img_w, img_h]).astype(int) for p in resultsF.multi_face_landmarks[0].landmark])
(l_cx, l_cy), l_radius = cv2.minEnclosingCircle(mesh_points[LEFT_IRIS])
(r_cx, r_cy), r_radius = cv2.minEnclosingCircle(mesh_points[RIGHT_IRIS])
center_left = np.array([l_cx, l_cy], dtype=np.int32)
center_right = np.array([r_cx, r_cy], dtype=np.int32)
#cv2.circle(annotated_image, center_left, int(l_radius), (255,0,0), -1, cv2.LINE_AA)
#cv2.circle(annotated_image, center_right, int(r_radius), (255,0,0), -1, cv2.LINE_AA)
#--------------------------------------------------------
from holisticPartNames import normalize2DPointWhileAlsoMatchingTrainingAspectRatio
#--------------------------------------------------------
lEyex2D = float(l_cx/img_w) #Dont Flip X
lEyey2D = float(l_cy/img_h)
lEyex2D,lEyey2D = normalize2DPointWhileAlsoMatchingTrainingAspectRatio(lEyex2D,lEyey2D,currentAspectRatio)
lEyeVis = 0.0
if ( (lEyex2D!=0.0) or (lEyey2D!=0.0) ):
lEyeVis = 1.0
mocapNETInput["2dx_head_leye"] = lEyex2D
mocapNETInput["2dy_head_leye"] = lEyey2D
mocapNETInput["visible_head_leye"] = lEyeVis
mocapNETInput["2dx_endsite_eye.l"] = lEyex2D
mocapNETInput["2dy_endsite_eye.l"] = lEyey2D
mocapNETInput["visible_endsite_eye.l"] = lEyeVis
#--------------------------------------------------------
rEyex2D = float(r_cx/img_w) #Dont Flip X
rEyey2D = float(r_cy/img_h)
rEyex2D,rEyey2D = normalize2DPointWhileAlsoMatchingTrainingAspectRatio(rEyex2D,rEyey2D,currentAspectRatio)
rEyeVis = 0.0
if ( (rEyex2D!=0.0) or (rEyey2D!=0.0) ):
rEyeVis = 1.0
mocapNETInput["2dx_head_reye"] = rEyex2D
mocapNETInput["2dy_head_reye"] = rEyey2D
mocapNETInput["visible_head_reye"] = rEyeVis
mocapNETInput["2dx_endsite_eye.r"] = rEyex2D
mocapNETInput["2dy_endsite_eye.r"] = rEyey2D
mocapNETInput["visible_endsite_eye.r"] = rEyeVis
#--------------------------------------------------------
else:
#print("UNABLE TO GET EYES")
pass
#don't populate them at all..
#mocapNETInput["2dx_head_leye"] = 0.0
#mocapNETInput["2dy_head_leye"] = 0.0
#mocapNETInput["visible_head_leye"] = 0.0
#mocapNETInput["2dx_head_reye"] = 0.0
#mocapNETInput["2dy_head_reye"] = 0.0
#mocapNETInput["visible_head_reye"] = 0.0
#--------------------------------------------------------
#--------------------------------------------------------------------------------------------------
#from MocapNETVisualization import drawMocapNETInput
#drawMocapNETInput(mocapNETInput,annotated_image)
#--------------------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------------
self.output = mocapNETInput
#--------------------------------------------------------------------------------------------
return mocapNETInput,annotated_image
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
def streamPosesFromCameraToMocapNET():
engine = "onnx"
headless = False
doProfiling = False
multiThreaded = False
videoFilePath = "webcam"
videoWidth = 1280
videoHeight = 720
saveVideo = False
doBody = True
doFace = False
doREye = False
doMouth = False
doHands = False
aspectCorrection = 1.0
scale = 1.0
addNoise = 0.0
doNNEveryNFrames = 0
frameSkip = 0
doHCDPostProcessing = 1
hcdLearningRate = 0.001
hcdEpochs = 30
hcdIterations = 10
smoothingSampling = 30.0
smoothingCutoff = 5.0
plotBVHChannels = False
liveDemo = False
calibrationFile = ""
bvhAnglesForPlotting = list()
bvhAllAnglesForPlotting = list()
#python3 -m mediapipeHolisticWebcamMocapNET --from damien.avi --face --nobody --plot --save
#python3 -m mediapipeHolisticWebcamMocapNET --from damien.avi --nobody --face --plot --aspectCorrection 0.8 --save
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--headless"):
headless = True
if (sys.argv[i]=="--live"):
liveDemo = True
if (sys.argv[i]=="--mt"):
multiThreaded = True
if (sys.argv[i]=="--calib"):
calibrationFile = sys.argv[i+1]
if (sys.argv[i]=="--frameskip"):
frameSkip = int(sys.argv[i+1])
if (sys.argv[i]=="--nnsubsample"):
doNNEveryNFrames = int(sys.argv[i+1])
if (sys.argv[i]=="--ik"):
hcdLearningRate = float(sys.argv[i+1])
hcdEpochs = int(sys.argv[i+2])
hcdIterations = int(sys.argv[i+3])
if (sys.argv[i]=="--smooth"):
smoothingSampling = float(sys.argv[i+1])
smoothingCutoff = float(sys.argv[i+2])
if (sys.argv[i]=="--noik"):
doHCDPostProcessing = 0
if (sys.argv[i]=="--aspectCorrection"):
aspectCorrection=float(sys.argv[i+1])
if (sys.argv[i]=="--noise"):
addNoise=float(sys.argv[i+1])
if (sys.argv[i]=="--size"):
videoWidth = int(sys.argv[i+1])
videoHeight = int(sys.argv[i+2])
if (sys.argv[i]=="--scale"):
scale=float(sys.argv[i+1])
if (sys.argv[i]=="--plot"):
plotBVHChannels=True
if (sys.argv[i]=="--all"):
doBody=True
doREye=True
doMouth=True
doHands=True
if (sys.argv[i]=="--nobody"):
doBody=False
if (sys.argv[i]=="--face"):
doFace=True
if (sys.argv[i]=="--eyes") or (sys.argv[i]=="--reye"):
doREye=True
if (sys.argv[i]=="--mouth"):
doMouth=True
if (sys.argv[i]=="--hands"):
doHands=True
if (sys.argv[i]=="--save"):
saveVideo=True
if (sys.argv[i]=="--engine"):
engine=sys.argv[i+1]
print("Selecting engine : ",engine)
if (sys.argv[i]=="--from"):
videoFilePath=sys.argv[i+1]
if (sys.argv[i]=="--profile"):
doProfiling=True
if "/dev/video" in videoFilePath:
smoothingSampling = 20.0
smoothingCutoff = 8.0
print("Special Low Smoothing setup")
from MocapNETVisualization import drawMocapNETOutput,drawDescriptor,drawNSRM,drawMAE2DError,drawMocapNETAllPlots
#Select a MocapNET class from tensorflow/tensorrt/onnx/tf-lite engines
from MocapNET import easyMocapNETConstructor
mnet = easyMocapNETConstructor(
engine,
doProfiling = doProfiling,
multiThreaded = multiThreaded,
doHCDPostProcessing = doHCDPostProcessing,
hcdLearningRate = hcdLearningRate,
hcdEpochs = hcdEpochs,
hcdIterations = hcdIterations,
smoothingSampling = smoothingSampling,
smoothingCutoff = smoothingCutoff,
bvhScale = scale,
doBody = doBody,
doFace = doFace,
doREye = doREye,
doMouth = doMouth,
doHands = doHands,
addNoise = addNoise
)
if (calibrationFile!=""):
print("Enforcing Calibration file : ",calibrationFile)
mnet.bvh.configureRendererFromFile(calibrationFile)
#To scale the intrinsic camera parameters (focal length and principal point) when changing the resolution of the image from 640x480 to 1280x720, you can use the following formula:
#New Focal Length (fx_new, fy_new) = (New Image Width / Original Image Width) * Original Focal Length
#New Principal Point (cx_new, cy_new) = (New Image Width / Original Image Width) * Original Principal Point
mnet.test()
mnet.recordBVH(not liveDemo)
#Body only
mp = None
if (doFace or doMouth or doMouth or doHands):
mp = MediaPipeHolistic(doMediapipeVisualization = False)
else:
mp = MediaPipePose(doMediapipeVisualization = False)
# For webcam input:
frameNumber = 0
#------------------------------------------
if (videoFilePath=="esp"):
from espStream import ESP32CamStreamer
cap = ESP32CamStreamer()
elif (videoFilePath=="webcam"):
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
elif (videoFilePath=="/dev/video0"):
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
elif (videoFilePath=="/dev/video1"):
cap = cv2.VideoCapture(1)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
elif (videoFilePath=="/dev/video2"):
cap = cv2.VideoCapture(2)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, videoWidth)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, videoHeight)
else:
from tools import checkIfPathIsDirectory
if (checkIfPathIsDirectory(videoFilePath) and (not "/dev/" in videoFilePath) ):
from folderStream import FolderStreamer
cap = FolderStreamer(path=videoFilePath,width=videoWidth,height=videoHeight)
mnet.bvh.configureRendererFromFile("%s/color.calib"%videoFilePath)
else:
cap = cv2.VideoCapture(videoFilePath)
#-----------------------------------------
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
print("\n\n\n\nStarting MocapNET using MediaPipe 2D Joint Estimator Input")
print("Please wait until input processing finishes!")
maxBrokenFrames = 100
brokenFrames = 0
while cap.isOpened():
success, image = cap.read()
#Frame skipping..!
if (frameSkip>0):
for i in range(0,frameSkip):
frameNumber = frameNumber + 1
success, image = cap.read()
plotImage = image
if not success:
eprint("Ignoring empty camera frame : ",brokenFrames,"/",maxBrokenFrames)
brokenFrames = brokenFrames + 1
if (brokenFrames>maxBrokenFrames):
break
else:
continue
# If loading a video, use 'break' instead of 'continue'.
#continue
if ( aspectCorrection!=1.0 ):
width = int(image.shape[1]*aspectCorrection)
height = int(image.shape[0])
image = cv2.resize(image, (width,height))
#--------------------------------------------------------------------------------------------------------------
start = time.time() # Time elapsed
mocapNETInput,annotated_image = mp.convertImageToMocapNETInput(image)
end = time.time() # Time elapsed
mnet.hz_2DEst = secondsToHz(end - start)
mnet.history_hz_2DEst.append(mnet.hz_2DEst)
if (len(mnet.history_hz_2DEst)>mnet.perfHistorySize):
mnet.history_hz_2DEst.pop(0) #Keep mnet history on limits
#--------------------------------------------------------------------------------------------------------------
doNN = 1
if (doNNEveryNFrames>0):
doNN = (frameNumber%doNNEveryNFrames)==0
#--------------------------------------------------------------------------------------------------------------
mocapNET3DOutput = mnet.predict3DJoints(mocapNETInput,runNN=doNN,runHCD=True)
mocapNETBVHOutput = mnet.outputBVH
bvhAnglesForPlotting.append(mocapNETBVHOutput)
bvhAllAnglesForPlotting.append(mocapNETBVHOutput)
if (len(bvhAnglesForPlotting)>100):
bvhAnglesForPlotting.pop(0)
#--------------------------------------------------------------------------------------------------------------
from MocapNETVisualization import visualizeMocapNETEnsemble
image,plotImage = visualizeMocapNETEnsemble(mnet,annotated_image,plotBVHChannels=plotBVHChannels,bvhAnglesForPlotting=bvhAnglesForPlotting)
#--------------------------------------------------------------------------------------------------------------
frameNumber = frameNumber + 1
mnet.printStatus()
if (saveVideo):
cv2.imwrite('colorFrame_0_%05u.jpg'%(frameNumber), annotated_image)
if (plotBVHChannels):
cv2.imwrite('plotFrame_0_%05u.jpg'%(frameNumber), plotImage)
if not headless:
cv2.imshow('MocapNET 4 using MediaPipe Holistic 2D Joints', annotated_image)
if (plotBVHChannels):
cv2.imshow('MocapNET 4 using MediaPipe Holistic Motion History',plotImage)
if cv2.waitKey(1) & 0xFF == 27:
break
if (saveVideo): # 1280x720 by default
os.system("ffmpeg -framerate 30 -i colorFrame_0_%%05d.jpg -s %ux%u -y -r 30 -pix_fmt yuv420p -threads 8 livelastRun3DHiRes.mp4 && rm colorFrame_0_*.jpg " % (videoWidth,videoHeight)) #
if (plotBVHChannels):
os.system("ffmpeg -framerate 30 -i plotFrame_0_%05d.jpg -s 1200x720 -y -r 30 -pix_fmt yuv420p -threads 8 livelastPlot3DHiRes.mp4 && rm plotFrame_0_*.jpg")
del mnet #So that the out.bvh file gets created..
if (not liveDemo):
os.system("rm 2d_out.csv 3d_out.csv bvh_out.csv map_out.csv")
os.system("./GroundTruthDumper --from out.bvh --setPositionRotation -2.6 0 2000 0 0 0 --csv ./ out.csv 2d+3d+bvh ") # Remove noise offsetPositionRotation
cap.release()
#------------------------------------------------
#------------------------------------------------
#------------------------------------------------
if __name__ == '__main__':
streamPosesFromCameraToMocapNET()
@@ -0,0 +1,255 @@
#!/usr/bin/python3
import sys
import numpy as np
import matplotlib.pyplot as plt
from readCSV import readGroundTruthFile,splitNumpyArray
from readCSV import parseConfiguration
from tools import getFileFromPath
def splitNumpyArray(model,column):
numberOfSamples=len(model)
npOutput = np.empty([numberOfSamples],dtype=float,order='C')
for num in range(0,numberOfSamples):
npOutput[num]=float(model[num,column]);
return npOutput;
def draw2D(data,width=1920,height=1080):
#----------------------------------------------------
from MocapNETVisualization import drawMocapNETInput
#----------------------------------------------------
import cv2
import numpy as np
#----------------------------------------------------
for sampleID in range(0,len(data['body'])):
image = np.zeros([height,width,3],dtype=np.uint8)
joints2D = dict()
for labelID in range(0,len(data['label'])):
label = data['label'][labelID].lower()
value = data['body'][sampleID][labelID]
#----------------------------------------------------
if "2d_x" in label:
value = value * width
if "2d_y" in label:
value = value * height
#----------------------------------------------------
joints2D[label] = value
drawMocapNETInput(joints2D,image,flipX=False)
font = cv2.FONT_HERSHEY_SIMPLEX
org = (30,60)
fontScale = 1.5
color = (255,255,255)
thickness = 2
message = 'Sample Number : %u / %u ' % (sampleID,len(data['body']))
image = cv2.putText(image, message , org, font, fontScale, color, thickness, cv2.LINE_AA)
cv2.imshow('2D',image)
#print("Sample ",sampleID," -> ",joints2D)
if cv2.waitKey(1000) & 0xFF == 27:
sys.exit(0)
#----------------------------------------------------
def plotDistribution(column,filename,values):
print("Plotting ",filename)
#print(values.shape)
plt.clf()
plt.hist(values,bins=100)
median = np.median(values)
mean = np.mean(values)
std = np.std(values)
var = np.var(values)
minimum = np.min(values)
maximum = np.max(values)
title_string="Histogram of Output distribution for %s \nMedian=%0.2f,Mean=%0.2f,Std=%0.2f,Var=%0.2f,Samples=%u,Min=%0.2f,Max=%0.2f" % (filename,median,mean,std,var,len(values),minimum,maximum)
plt.title(title_string)
print("Stats,%s,%0.2f,%0.2f,%0.2f,%0.2f,%u,%0.2f,%0.2f" % (filename,median,mean,std,var,len(values),minimum,maximum))
plt.savefig("%03u_%s.png" % (column,filename))
def calculate_relative_magnitudes(edm, n):
row_magnitudes = []
column_magnitudes = []
for i in range(n):
row_magnitude = sum(edm[i*n:(i+1)*n])
row_magnitudes.append(row_magnitude)
column_magnitude = sum(edm[i::n])
column_magnitudes.append(column_magnitude)
central_element = edm[n*n // 2]
row_magnitudes_sum = sum(row_magnitudes) - central_element
column_magnitudes_sum = sum(column_magnitudes) - central_element
max_magnitude = max(row_magnitudes_sum, column_magnitudes_sum)
relative_row_magnitudes = [m / max_magnitude for m in row_magnitudes]
relative_column_magnitudes = [m / max_magnitude for m in column_magnitudes]
return relative_row_magnitudes, relative_column_magnitudes
def plotCovariance(X):
covariance = np.cov(X.T)
# Plot the covariance matrix
plt.imshow(covariance, cmap='coolwarm', interpolation='nearest')
plt.colorbar()
plt.title('Covariance Matrix')
plt.savefig("covariance.png")
#plt.show()
def plotTestOutputDistribution(csvfiletoplotIn,csvfiletoplotOut,mem):
useRadians=0
useHalfFloats=0
dataFile = "body"
#This will be get populated using the --config argument
configuration = []
configurationPath=""
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--config"):
configurationPath=sys.argv[i+1]
configuration = parseConfiguration(configurationPath)
#setupDNNModelsUsingJSONConfiguration(configuration)
if (sys.argv[i]=="--mem"):
print("\nMemory usage ",sys.argv[i+1]);
mem=float(sys.argv[i+1])
#-----------------------------------------------
# New 4way split
#-----------------------------------------------
if (sys.argv[i]=="--dataset"):
print("\nOverriding dataset ",dataFile," and using ",sys.argv[i+1]);
dataFile=sys.argv[i+1]
if (sys.argv[i]=="--all"):
#Don't mix this --all with the step2_OrientatonClassifier.py --all
hierarchyPartName=sys.argv[i+1]
dataFile="%s_all" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--back"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_back" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--front"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_front" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--left"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_left" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--right"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_right" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
#-----------------------------------------------
#Resolve PCA name.. :(
x = configuration['doPCA'].split("$",1)
if (len(x)>0):
#If there is a $ character this is our place holder to autocomplete our dataFile
print("PCA filename is resolved from ",configuration['doPCA'])
print(" to ")
configuration['doPCA']=x[0]+dataFile+".pca"
print(configuration['doPCA'])
numberOfChannelsPerNSDMElement=2
if (configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
groundTruth = readGroundTruthFile(
configuration,
csvfiletoplotIn,
csvfiletoplotIn,
csvfiletoplotOut,
mem,
numberOfChannelsPerNSDMElement,
useRadians,
useHalfFloats
)
#----------------------------------------------------------
data = np.empty(len(groundTruth['out']))
for z in range(0,len(groundTruth['labelOut'])):
data=splitNumpyArray(groundTruth['out'],z)
if (z<3):
np.multiply(data,10)
plotDistribution(z,groundTruth['labelOut'][z],data)
#----------------------------------------------------------
data = np.empty(len(groundTruth['in']))
for z in range(0,len(groundTruth['labelIn'])):
data=splitNumpyArray(groundTruth['in'],z)
plotDistribution(z,groundTruth['labelIn'][z],data)
#----------------------------------------------------------
#Test Plots
#./GroundTruthDumper --from dataset/yawTest.bvh --csv ./ yaw.csv 2d --svg .
# python3 csvNET.py --from 2d_yaw.csv --save --keep --hands --white
# convert colorFrame_0_00000.jpg -crop 234x500+0+90 nsrm_00000.jpg
#./GroundTruthDumper --from dataset/pitchTest.bvh --csv ./ pitch.csv 2d --svg .
# python3 csvNET.py --from 2d_pitch.csv --save --keep --hands --white
#./GroundTruthDumper --from dataset/rollTest.bvh --csv ./ roll.csv 2d --svg .
# python3 csvNET.py --from 2d_roll.csv --save --keep --hands --white
def doRun():
label = "nolabel"
if (len(sys.argv)==3) :
#==========================================
if (sys.argv[1]=="--2d"):
print(sys.argv[0]," --2d your.csv")
labelSplit = sys.argv[2].split('.',1)
label = labelSplit[0]
from readCSV import readCSVFile
data = readCSVFile(sys.argv[2],1.0,0)
draw2D(data)
sys.exit(0)
#==========================================
elif (sys.argv[1]=="--simple"):
print(sys.argv[0]," --simple your.csv")
labelSplit = sys.argv[2].split('.',1)
label = labelSplit[0]
from readCSV import readCSVFile
data = readCSVFile(sys.argv[2],1.0,0)
plotCovariance(data['body'])
#USE : python3 plotCSV.py --simple loss.csv | grep Stats > lossStats.csv to create stats csv file!
print("Stats,Output,Median,Mean,Std,Var,Samples,Min,Max")
for z in range(0,len(data['label'])):
print("Plotting Column ",data['label'][z])
specificData=splitNumpyArray(data['body'],z)
filename = getFileFromPath('%s-%s' % (label,data['label'][z]))
plotDistribution(z,filename,specificData)
sys.exit(0)
#==========================================
if (len(sys.argv)<5) :
print("plotCSV.py: Please rerun using a parameter of the CSV file you want to run..")
print("e.g.")
print(sys.argv[0]," --config dataset/lhand_configuration.json dataset/generated/2d_lhand_all.csv dataset/generated/bvh_lhand_all.csv --all lhand")
print(" or ")
print(sys.argv[0]," --config dataset/upperbody_configuration.json dataset/generated/2d_upperbody_all.csv dataset/generated/bvh_upperbody_all.csv --all upperbody ")
print(" or ")
print(sys.argv[0]," --config dataset/face_configuration.json dataset/generated/2d_face_all.csv dataset/generated/bvh_face_all.csv --all face")
print(" or ")
print(sys.argv[0]," --simple your.csv")
sys.exit(0)
plotTestOutputDistribution(sys.argv[3],sys.argv[4],1.0)
if __name__== "__main__":
doRun()
@@ -0,0 +1,352 @@
import matplotlib as mp
import matplotlib.pyplot as plt
import numpy as np
import os
import sys
import time
import array
import csv
# Fixing random state for reproducibility
np.random.seed(19680801)
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
"""
Bytes to KB/MB/GB/TB converter
"""
def convert_bytes(num):
"""
this function will convert bytes to MB.... GB... etc
"""
step_unit = 1000.0 #1024 bad the size
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
if num < step_unit:
return "%3.1f %s" % (num, x)
num /= step_unit
"""
Check if a file exists
"""
def checkIfFileExists(filename):
return os.path.isfile(filename)
"""
Count the number of lines by parsing the file inside python
"""
def getNumberOfLines(filename):
#import socket
#print("Hostname is ",socket.gethostname())
#if (socket.gethostname()=="ammar-kriti"):
# print(bcolors.FAIL,"RETURNING FIXED NUMBER OF LINES FOR SPEED IN MY SLOW PC",bcolors.ENDC)
# return 3858095
print("Counting number of lines in file ",filename)
with open(filename) as f:
return sum(1 for line in f)
"""
typically we work with data[NUMBER_OF_SAMPLES,NUMBER_OF_COLUMNS]
calling splitNumpyArray(data,4,4,0) means get back columns 4,5,6,7 so it will return a data[NUMBER_OF_SAMPLES,4]
"""
def splitNumpyArray(data,column,columnsToTake,useHalfFloats=0):
#-------------------------------------
dtypeSelected=np.dtype(np.float32)
if (useHalfFloats):
dtypeSelected=np.dtype(np.float16)
#-------------------------------------
numberOfSamples=len(data)
npOutput = np.full([numberOfSamples,columnsToTake],fill_value=0,dtype=dtypeSelected,order='C')
for outCol in range(0,columnsToTake):
for num in range(0,numberOfSamples):
npOutput[num,outCol]=float(data[num,column+outCol])
#-------------------------------------
return npOutput;
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------------------------------------------------
def readCSVFile(filename,memPercentage,useHalfFloats=0):
print("CSV file :",filename,"..\n")
if (not checkIfFileExists(filename)):
print( bcolors.FAIL + "Input file "+filename+" does not exist, cannot read ground truth.." + bcolors.ENDC)
print("Current Directory was "+os.getcwd())
sys.exit(1)
start = time.time()
dtypeSelected=np.dtype(np.float32)
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
if (useHalfFloats):
dtypeSelected=np.dtype(np.float16)
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
progress=0.0
#useSquared=1
sampleNumber=0
receivedHeader=0
inputNumberOfColumns=0
outputNumberOfColumns=0
inputLabels=list()
#-------------------------------------------------------------------------------------------------
numberOfSamplesInput=getNumberOfLines(filename)-2
print(" Input file has ",numberOfSamplesInput," training samples\n")
#-------------------------------------------------------------------------------------------------
numberOfSamples = numberOfSamplesInput
numberOfSamplesLimit=int(numberOfSamples*memPercentage)
#-------------------------------------------------------------------------------------------------
if (memPercentage==0.0):
print("readGroundTruthFile was asked to occupy 0 memory so this probably means we just want one record")
numberOfSamplesLimit=2
if (memPercentage>1.0):
print("Memory Limit will be interpreted as a raw value..")
numberOfSamplesLimit=int(memPercentage)
#-------------------------------------------------------------------------------------------------
thisInput = array.array('f')
#---------------------------------
fi = open(filename, "r")
readerIn = csv.reader( fi , delimiter =',', skipinitialspace=True)
for rowIn in readerIn:
#------------------------------------------------------
if (not receivedHeader): #use header to get labels
#------------------------------------------------------
inputNumberOfColumns=len(rowIn)
inputLabels = list(rowIn[i] for i in range(0,inputNumberOfColumns) )
print("Number of Input elements : ",len(inputLabels))
#------------------------------------------------------
if (memPercentage==0):
print("Will only return labels\n")
return {'labels':inputLabels};
#i=0
#print("class Input(Enum):")
#for label in inputLabels:
# print(" ",label," = ",i," #",int(i/3))
# print(" ",label,"=",int(i/3))
# i=i+1
#---------------------------------
# Allocate Lists
#---------------------------------
for i in range(inputNumberOfColumns):
thisInput.append(0.0)
#---------------------------------
#---------------------------------
# Allocate Numpy Arrays
#---------------------------------
inputSize=0
startCompressed=0
inputSize=inputNumberOfColumns
startCompressed=inputNumberOfColumns
npInputBytesize=0+numberOfSamplesLimit * inputSize * dtypeSelectedByteSize
print(" Input file on disk has a shape of [",numberOfSamples,",",inputSize,"]")
print(" Input we will read has a shape of [",numberOfSamplesLimit,",",inputSize,"]")
print(" Input will occupy ",convert_bytes(npInputBytesize)," of RAM\n")
npInput = np.full([numberOfSamplesLimit,inputSize],fill_value=0,dtype=dtypeSelected,order='C')
#----------------------------------------------------------------------------------------------------------
receivedHeader=1
#sys.exit(0)
else:
#-------------------------------------------
# First convert our string INPUT to floats
#-------------------------------------------
for i in range(inputNumberOfColumns):
try:
thisInput[i]=float(rowIn[i])
except ValueError:
thisInput[i]=0.0
#-------------------------------------------
for num in range(0,inputNumberOfColumns):
npInput[sampleNumber,num]=float(thisInput[num]);
#-------------------------------------------
sampleNumber=sampleNumber+1
if (numberOfSamples>0):
progress=sampleNumber/numberOfSamplesLimit
if (sampleNumber%1000==0) :
progressString = "%0.2f"%float(100*progress)
print("\rReading from disk (",sampleNumber,") - ",progressString," % \r", end="", flush=True)
if (numberOfSamplesLimit<=sampleNumber):
print("\rStopping reading file to obey memory limit given by parameter --mem ",memPercentage,"\n")
break
#-------------------------------------------
fi.close()
del readerIn
print("\n read, Samples: ",sampleNumber,", was expecting ",numberOfSamples," samples\n")
print(npInput.shape)
totalNumberOfBytes=npInput.nbytes;
totalNumberOfGigaBytes=totalNumberOfBytes/1073741824;
print("GPU Size Occupied by data = ",totalNumberOfGigaBytes," GB \n")
end = time.time()
print("Time elapsed : ",(end-start)/60," mins")
#---------------------------------------------------------------------
return {'label':inputLabels, 'body':npInput };
def resolve(theList,theName):
result = 0
for item in theList:
if (item==theName):
return result,True
result = result + 1
return result,False
if __name__== "__main__":
filename="report.csv"
output="out.png"
jointName=" HCD FineTune "
#----------------------------------------------
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--from"):
filename=sys.argv[i+1]
data = readCSVFile(filename,1.0)
#----------------------------------------------
if (filename=="report.csv"):
data = readCSVFile(filename,1.0)
#----------------------------------------------
xCol=1
yCol=6
zCol=8
target1Col=11
target2Col=12
xs = None
ys = None
zs = None
vs = None
v2s = None
#https://matplotlib.org/stable/gallery/color/colormap_reference.html
colorMapString = "Greens_r"
#supported values are 'Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Greens', 'Greens_r', 'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu', 'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r', 'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn', 'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r', 'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r', 'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r', 'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis', 'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'gist_earth', 'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_heat', 'gist_heat_r', 'gist_ncar', 'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg', 'gist_yarg_r', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r', 'hot', 'hot_r', 'hsv', 'hsv_r', 'inferno', 'inferno_r', 'jet', 'jet_r', 'magma', 'magma_r', 'nipy_spectral', 'nipy_spectral_r', 'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow', 'rainbow_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer', 'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c', 'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', 'twilight_shifted_r', 'viridis', 'viridis_r', 'winter', 'winter_r'
xOk = False
yOk = False
zOk = False
target1Ok = False
target2Ok = False
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--colormap"):
colorMapString=sys.argv[i+1]
if (sys.argv[i]=="--to"):
output=sys.argv[i+1]
if (sys.argv[i]=="--title"):
jointName=sys.argv[i+1]
if (sys.argv[i]=="--label"):
jointName=sys.argv[i+1]
if (sys.argv[i]=="-x"):
xCol,xOk = resolve(data["label"],sys.argv[i+1])
if (sys.argv[i]=="-y"):
yCol,yOk = resolve(data["label"],sys.argv[i+1])
if (sys.argv[i]=="-z"):
zCol,zOk = resolve(data["label"],sys.argv[i+1])
if (sys.argv[i]=="-v2"):
target2Col,target2Ok = resolve(data["label"],sys.argv[i+1])
if (sys.argv[i]=="-v1"):
target1Col,target1Ok = resolve(data["label"],sys.argv[i+1])
#-------------------------
xLabel=data["label"][xCol]
yLabel=data["label"][yCol]
zLabel=data["label"][zCol]
#-------------------------
viewAzimuth=45
viewElevation=45
transparency=0.6
scale = 0.12 #Smaller is smaller :P
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
if xOk:
xs = splitNumpyArray(data["body"],xCol,1) # 1 = learning rate
else:
print("Error Resolving X")
if yOk:
ys = splitNumpyArray(data["body"],yCol,1) # 6 = iteration
else:
print("Error Resolving Y")
if zOk:
zs = splitNumpyArray(data["body"],zCol,1) # 8 = langevin
else:
print("Error Resolving Z")
if target1Ok:
vs = splitNumpyArray(data["body"],target1Col,1) # 10 = mae
else:
print("Error Resolving Color (v1)")
if target2Ok:
v2s = splitNumpyArray(data["body"],target2Col,1) # 10 = mae
v2sMean = np.mean(v2s)
v2s = v2s * (100.0/v2sMean)
else:
print("Error Resolving Size (v2)")
ax.view_init(viewAzimuth,viewElevation)
#cm = plt.cm.get_cmap('RdYlBu')
#cm = plt.cm.get_cmap('hot')
cm = mp.colormaps.get_cmap(colorMapString)
if target1Ok and target2Ok:
sc = ax.scatter(xs, ys, zs, c=vs, s=v2s , cmap=cm, alpha=transparency)
else:
sc = ax.scatter(xs, ys, zs, alpha=transparency)
plt.colorbar(sc)
ax.set_title(jointName) # Title of the plot
ax.set_xlabel(xLabel)
ax.set_ylabel(yLabel)
ax.set_zlabel(zLabel)
fig.savefig(output)
plt.show()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,287 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import sys
import numpy as np
from readCSV import parseConfiguration,splitNumpyArray,readGroundTruthFile
from DNNModel import setupDNNModelsUsingJSONConfiguration
OKGREEN = '\033[92m'
ENDC = '\033[0m'
FAIL = '\033[91m'
"""
Retreive the available system RAM
"""
def getRAMInformation():
"""
Get node total memory and memory usage
"""
with open('/proc/meminfo', 'r') as mem:
ret = {}
tmp = 0
for i in mem:
sline = i.split()
if str(sline[0]) == 'MemTotal:':
ret['total'] = int(sline[1])
elif str(sline[0]) in ('MemFree:', 'Buffers:', 'Cached:'):
tmp += int(sline[1])
ret['free'] = int(tmp)
ret['used'] = int(ret['total']) - int(ret['free'])
return ret
if __name__ == '__main__':
print("""
██████╗ ███████╗ ██████╗ ██████╗ ███╗ ███╗██████╗ ██████╗ ███████╗███████╗
██╔══██╗██╔════╝██╔════╝██╔═══██╗████╗ ████║██╔══██╗██╔═══██╗██╔════╝██╔════╝
██║ ██║█████╗ ██║ ██║ ██║██╔████╔██║██████╔╝██║ ██║███████╗█████╗
██║ ██║██╔══╝ ██║ ██║ ██║██║╚██╔╝██║██╔═══╝ ██║ ██║╚════██║██╔══╝
██████╔╝███████╗╚██████╗╚██████╔╝██║ ╚═╝ ██║██║ ╚██████╔╝███████║███████╗
╚═════╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚══════╝╚══════╝""")
configuration = []
configurationPath=""
#Use the whole training Dataset by default
memPercentage=1.0
#networkCompression=1.0
useHalfFloats = 0
useRadians = 0
#I/O settings
outputDirectoryForTrainedModels = "step0FrontBody"
dataFile = "body"
testFile = "body_test"
hierarchyPartName = "body"
outputMode = "bvh"
# Sample call with some example parameters :
# python3 principleComponentAnalysisTool.py --config dataset/body_configuration.json --mem 1000 --highlight 3 --all body --show --mode 3
highlightChannel = -1 #<- default shows PC4
batch = 0
mode = 1
dimensions = 0
decompositionType = "pca"
viewA = 45
viewB = 45
visualize = 0
dumpRules = 1
addScreePlot = 0
label = "not defined"
if (len(sys.argv)>1):
#print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--config"):
configurationPath=sys.argv[i+1]
configuration = parseConfiguration(configurationPath)
setupDNNModelsUsingJSONConfiguration(configuration)
decompositionType = configuration['decompositionType']
dimensions = int(configuration['PCADimensionsKept'])
if (configuration['precision']=="fp16"):
useHalfFloats=1
configuration['rememberWeights']=0
setBackendToHalfFloats()
elif (configuration['precision']!="fp32"):
print(bcolors.WARNING,"Cannot use ",configuration['precision']," precision\n",bcolors.ENDC)
if (sys.argv[i]=="--mem"):
print("\nMemory usage ",sys.argv[i+1]);
memPercentage=float(sys.argv[i+1])
#-----------------------------------------------
# New 4way split
#-----------------------------------------------
if (sys.argv[i]=="--dataset"):
print("\nOverriding dataset ",dataFile," and using ",sys.argv[i+1]);
dataFile=sys.argv[i+1]
if (sys.argv[i]=="--all"):
#Don't mix this --all with the step2_OrientatonClassifier.py --all
hierarchyPartName=sys.argv[i+1]
dataFile="%s_all" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--back"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_back" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--front"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_front" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--left"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_left" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
if (sys.argv[i]=="--right"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_right" % hierarchyPartName
outputDirectoryForTrainedModels="step0_%s" % dataFile
#-----------------------------------------------
if (sys.argv[i]=="--type"):
print("\nSet Mode to ",sys.argv[i+1]);
decompositionType=sys.argv[i+1]
configuration['decompositionType'] = decompositionType
if (sys.argv[i]=="--dims"):
print("\nSet Dimensions to ",sys.argv[i+1]);
dimensions=int(sys.argv[i+1])
configuration['PCADimensionsKept']=str(dimensions)
if (sys.argv[i]=="--mode"):
print("\nSet Mode to ",sys.argv[i+1]);
mode=int(sys.argv[i+1])
if (sys.argv[i]=="--highlight"):
print("\nSet Highlight to ",sys.argv[i+1]);
highlightChannel=int(sys.argv[i+1])
if (sys.argv[i]=="--view"):
print("\nSet View to ",sys.argv[i+1],sys.argv[i+2]);
viewA=int(sys.argv[i+1])
viewB=int(sys.argv[i+2])
if (sys.argv[i]=="--batch"):
batch=1
visualize = 1
if (sys.argv[i]=="--nosave"):
dumpRules=0
if (sys.argv[i]=="--show"):
visualize=1
if (sys.argv[i]=="--noscree"):
addScreePlot=0
if (decompositionType==""):
print(OKGREEN,"Not doing everything because no decomposition type requested",ENDC)
sys.exit(0)
#The default compatibility setting is the BMVC2019 2channel NSDM, however nowadays we use NSRM
numberOfChannelsPerNSDMElement=2
if (configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
#Hardcoded path for dataset if using CSV file
#datasetDirectory="/home/ammar/Documents/Programming/DNNTracker/DNNTracker/dataset"
#datasetDirectory="../../DNNTracker/dataset"
datasetDirectory="dataset/generated/"
RAMBefore = getRAMInformation()
print("Initial | free RAM ",RAMBefore['free']," KB");
groundTruthTrain = readGroundTruthFile(
configuration,
"%s Train data for decomposition" % (decompositionType),
"%s/2d_%s.csv" % (datasetDirectory,dataFile),
"%s/%s_%s.csv" % (datasetDirectory,outputMode,dataFile), #outputMode is either bvh or 3d
memPercentage,
numberOfChannelsPerNSDMElement,
useRadians,
useHalfFloats,
completelyDisablePCACode = 1 #If we do PCA while trying to do PCA it will be madness
)
RAMAfter = getRAMInformation()
print("After reading the dataset | free RAM ",RAMAfter['free']," KB");
#----------------------------------------------------------------------------------------------------------
startOfNSxMColumn = len(groundTruthTrain['labelInNoNSDM'])
numberOfNSxMColumns = len(groundTruthTrain['labelIn'])-startOfNSxMColumn
print("2D data are 0 to ",startOfNSxMColumn)
print("NSRM data are ",startOfNSxMColumn , " to ",numberOfNSxMColumns)
if (mode==1):
NSxM = groundTruthTrain['in']
label = "on 2D+NSRM data"
elif (mode==2):
NSxM = splitNumpyArray(groundTruthTrain['in'],startOfNSxMColumn,numberOfNSxMColumns,useHalfFloats)
label = "on NSRM data"
elif (mode==3):
NSxM = splitNumpyArray(groundTruthTrain['in'],0,startOfNSxMColumn,useHalfFloats)
label = "on 2D data"
elif (mode==4):
NSxM = groundTruthTrain['out']
label = "on all BVH Data"
elif (mode==5):
onlyRotationalBVHOutputs = len(groundTruthTrain['labelOut']) - 3
print("Will take output from 3-",onlyRotationalBVHOutputs,"/",len(groundTruthTrain['labelOut']))
NSxM = splitNumpyArray(groundTruthTrain['out'],3,onlyRotationalBVHOutputs,useHalfFloats)
label = "on rot. BVH Data"
elif (mode==6):
onlyLimbRotationalBVHOutputs = len(groundTruthTrain['labelOut']) - 6
print("Will take output from 6-",onlyLimbRotationalBVHOutputs,"/",len(groundTruthTrain['labelOut']))
NSxM = splitNumpyArray(groundTruthTrain['out'],6,onlyLimbRotationalBVHOutputs,useHalfFloats)
label = "on limb rot. BVH Data"
#----------------------------------------------------------------------------------------------------------
RAMSplit = getRAMInformation()
print("After splitting the dataset | free RAM ",RAMSplit['free']," KB");
del groundTruthTrain['in']
if (not visualize):
del groundTruthTrain['out']
RAMFree = getRAMInformation()
print("After freeing original input | free RAM ",RAMFree['free']," KB");
print(OKGREEN,"Will perform dimensionality reduction on ",label,ENDC)
if (decompositionType=="pca"):
print("Attempting PCA using my code with ",dimensions," elements")
print("Our Input Shape is ",NSxM.shape[0],"x",NSxM.shape[1])
from principleComponentAnalysis import PCA
ourDecomposition = PCA(inputData=NSxM,decompositionType=decompositionType)
for i in range(0,len(ourDecomposition.cumulative)):
thisValue = 0.0
try:
thisValue = ourDecomposition.cumulative[i].real
except:
thisValue = ourDecomposition.cumulative[i]
#---------------------------------------------------
if (thisValue>0.99):
print(OKGREEN,"Useless? PCA Dim #",i," - ",thisValue*100,"%",ENDC)
else:
print("PCA Dim #",i," - Explanation of data until here ",thisValue*100,"%")
if (dimensions==i):
print(FAIL," ------------- OUR LIMIT IS SET HERE (",dimensions,") ------------- ",ENDC)
else:
from dataDecomposition import Decomposition
print("Attempting Generic Decomposition ",decompositionType," with ",dimensions," elements")
print("Our Input Shape is ",NSxM.shape[0],"x",NSxM.shape[1])
ourDecomposition = Decomposition(inputData=NSxM,decompositionType=decompositionType,selectedPCADimensions=dimensions)
if (dumpRules):
print("Dumping rules to json file..")
x = configuration['doPCA'].split("$")
if (len(x)>0):
#If there is a $ character this is our place holder to autocomplete our dataFile
print("We resolve ",configuration['doPCA'])
print(" to ")
configuration['doPCA']=x[0]+dataFile+".pca"
print(configuration['doPCA'])
ourDecomposition.save(configuration['doPCA'])
#Number of PCA components to plot on second plot
#-----------------------------------------------------------------------------
onlyScreePlotNDimensions=8
if (batch==1) or (visualize):
if (highlightChannel<0):
colors = list()
colorLabel = "highlighting PC-4"
else:
colorLabel="highlighting "+ groundTruthTrain['labelOut'][highlightChannel]
colors = groundTruthTrain['out'][:,highlightChannel]
#-----------------------------------------------------------------------------
filename = ""
if (batch==1):
filename = "%s_%s_%s_%u_v%u%u.png"%(decompositionType,label,colorLabel,int(memPercentage),viewA,viewB)
filename = filename.replace(' ','_')
#-----------------------------------------------------------------------------
if (visualize):
ourDecomposition.visualize(NSxM,saveToFile=filename,onlyScreePlotNDimensions=onlyScreePlotNDimensions,label=label,colors=colors,colorLabel=colorLabel,viewAzimuth=viewA,viewElevation=viewB,showScree=addScreePlot)
print(OKGREEN,"Finished with ",decompositionType," code!",ENDC)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,124 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$DIR"
#Simple dependency checker that will apt-get stuff if something is missing
# sudo apt-get install python3-venv python3-pip
SYSTEM_DEPENDENCIES="build-essential python3-venv python3-pip freeglut3-dev libglew-dev protobuf-compiler libprotobuf-dev libavdevice-dev"
for REQUIRED_PKG in $SYSTEM_DEPENDENCIES
do
PKG_OK=$(dpkg-query -W --showformat='${Status}\n' $REQUIRED_PKG|grep "install ok installed")
echo "Checking for $REQUIRED_PKG: $PKG_OK"
if [ "" = "$PKG_OK" ]; then
echo "No $REQUIRED_PKG. Setting up $REQUIRED_PKG."
#If this is uncommented then only packages that are missing will get prompted..
#sudo apt-get --yes install $REQUIRED_PKG
#if this is uncommented then if one package is missing then all missing packages are immediately installed..
sudo apt-get --yes install $SYSTEM_DEPENDENCIES
break
fi
done
#------------------------------------------------------------------------------
HEADLESS=" --headless"
OPENCV=" "
if [[ $* == *--collab* ]]
then
echo "Collab mode!"
echo "Performing python package installation without a virtual environment"
HEADLESS=" --headless"
OPENCV="opencv-python-headless"
rm -rf /content/sample_data/ #remove sample data
ln -s $DIR /content/mnet4
sudo apt-get --yes install build-essential freeglut3-dev libglew-dev #For some reason collab has some errors on previous check so just double-make sure we have these libraries
else
echo "Using a python pythonVirtualEnvironment environment"
echo "Activate it using : source pythonVirtualEnvironment/bin/activate"
python3 -m venv pythonVirtualEnvironment
source pythonVirtualEnvironment/bin/activate
OPENCV="opencv-python"
HEADLESS=" "
fi
cd "$DIR"
if [ -f RGBDAcquisition/README.md ]; then
echo "RGBDAcquisition appears to already exist .."
else
git clone https://github.com/AmmarkoV/RGBDAcquisition
cd RGBDAcquisition
#----------------------------------------------------------------------------------------------------------------------
#mkdir build
#cd build
#cmake ..
#cd ..
#----------------------------------------------------------------------------------------------------------------------
cd opengl_acquisition_shared_library/opengl_depth_and_color_renderer/
mkdir build
cd build
cmake ..
make BVHTester
#----------------------------------------------------------------------------------------------------------------------
cd "$DIR"
ln -s RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Applications/BVHTester BVH
ln -s RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/BVHTester GroundTruthDumper
fi
python3 -m pip install --upgrade pip #2.8.0 nvidia-tensorrt
python3 -m pip install tensorflow numpy numba tensorboard_plugin_profile tensorflow-model-optimization keras pillow tf2onnx onnxruntime onnx matplotlib pydot mediapipe $OPENCV scikit-learn
#Two ways to get Models!
#One through the database and compile them yourself (commented out to save Google Collab CPU time)..
#python3 -m getModelFromDatabase --get 318
#To generate the archive in the next lines do :
# zip mnet4_318.zip step1_*/*
#Another just take the precompiled ensembles ready to run
wget http://ammar.gr/mocapnet/mnet4/mnet4_-314.zip -O mnet4_-314.zip
unzip -o mnet4_-314.zip #<- upgrade to 324 mnet4_318.zip
#Unzip models for PoseNET.py operation..
wget http://ammar.gr/mocapnet/mnet4/mediapipe.zip -O mediapipe.zip
unzip -o mediapipe.zip
#To get :
# python3 -m evaluateMocapNET --config dataset/body_configuration.json --all body --engine onnx
# to work
#wget http://cvrlcode.ics.forth.gr/web_share/mocapnet/MocapNETBodyValidationSet.zip
#wget http://ammar.gr/datasets/MocapNETBodyValidationSet.zip
#unzip MocapNETBodyValidationSet.zip
#Doing a test run!
# echo "To enable Tensorflow profiling for non-root users please add : "
# echo "options nvidia \"NVreg_RestrictProfilingToAdminUsers=0\""
# echo "to /etc/modprobe.d/nvidia-graphics-drivers.conf"
# echo " "
echo "Ready for use"
echo "From now on to work with MocapNET you can use : "
echo "source pythonVirtualEnvironment/bin/activate"
echo "!python3 -m mediapipeHolisticWebcamMocapNET --from webcam --save --plot"
echo " OR "
echo "!python3 -m mediapipeHolisticWebcamMocapNET --from shuffle.webm --save --plot"
echo " OR "
echo "!python3 -m csvNET --from ../../../dataset/sample.csv --save --plot"
echo " "
echo " if you are running on collab don't forget to append --headless to your command"
echo " after the run is complete out.bvh will contain your results "
#Force making of library during last-stage of setup..
BVH/makeLibrary.sh
@@ -0,0 +1,556 @@
from scipy.stats import qmc
import numpy as np
import random
"""
python3 sobolRandomDatasetGenerator.py --upperbody --exponent 21
rm dataset/generated/2d_upperbody_all.csv dataset/generated/bvh_upperbody_all.csv
./GroundTruthDumper --from dataset/headerWithHeadAndOneMotion.bvh --importCSVPoses sobolUpperbody_2097152.csv --filterOccludedJoints --csv dataset/generated/ upperbody_all.csv 2d+3d+bvh
python3 sobolRandomDatasetGenerator.py --lowerbody --exponent 21
rm dataset/generated/2d_lowerbody_all.csv dataset/generated/bvh_lowerbody_all.csv
./GroundTruthDumper --from dataset/headerWithHeadAndOneMotion.bvh --importCSVPoses sobolLowerbody_2097152.csv --csv dataset/generated/ lowerbody_all.csv 2d+3d+bvh
python3 sobolRandomDatasetGenerator.py --lhand --exponent 21
rm dataset/generated/2d_lhand_all.csv dataset/generated/bvh_lhand_all.csv
./GroundTruthDumper --from dataset/lhand.qbvh --importCSVPoses sobolLHand_2097152.csv --csv dataset/generated/ lhand_all.csv 2d+3d+bvh
scp -P 2234 dataset/generated/2d_upperbody_all.csv dataset/generated/bvh_upperbody_all.csv dataset/generated/2d_lowerbody_all.csv dataset/generated/bvh_lowerbody_all.csv dataset/generated/2d_lhand_all.csv dataset/generated/bvh_lhand_all.csv ammar@cvrldemo:/home/ammar/Documents/Programming/DNNTracker/tensorflow2GPU/src/dataset/generated
"""
#python3 -m csvNET --from SCANREYE.csv --reye --nobody --plot --save
def scanReye(filename):
f = open(filename, 'w')
f.write("2DX_head_reye_0,2DY_head_reye_0,visible_head_reye_0,2DX_head_reye_1,2DY_head_reye_1,visible_head_reye_1,2DX_head_reye_2,2DY_head_reye_2,visible_head_reye_2,2DX_head_reye_3,2DY_head_reye_3,visible_head_reye_3,2DX_head_reye_4,2DY_head_reye_4,visible_head_reye_4,2DX_head_reye_5,2DY_head_reye_5,visible_head_reye_5,2DX_head_nostrills_2,2DY_head_nostrills_2,visible_head_nostrills_2,2DX_head_rchin_0,2DY_head_rchin_0,visible_head_rchin_0,2DX_head_chin,2DY_head_chin,visible_head_chin,2DX_head_reyebrow_0,2DY_head_reyebrow_0,visible_head_reyebrow_0,2DX_head_reyebrow_1,2DY_head_reyebrow_1,visible_head_reyebrow_1,2DX_head_reyebrow_2,2DY_head_reyebrow_2,visible_head_reyebrow_2,2DX_head_reyebrow_3,2DY_head_reyebrow_3,visible_head_reyebrow_3,2DX_head_reyebrow_4,2DY_head_reyebrow_4,visible_head_reyebrow_4,2DX_head_reye,2DY_head_reye,visible_head_reye\n")
for x in range(710,740): #710 - 750
for y in range(270,280): #range(270,271): #260 - 290
xF = float(x / 1000)
yF = float(y / 1000)
f.write("0.706034,0.271945,1,0.713014,0.265075,1,0.724606,0.264025,1,0.734642,0.276731,1,0.723602,0.280737,1,0.71263,0.277377,1,0.755537,0.331723,1,0.688397,0.274243,1,0.749762,0.466904,1,0.690998,0.262801,1,0.703323,0.247993,1,0.713234,0.238449,1,0.731472,0.246738,1,0.742246,0.255172,1,%f,%f,1\n" % (xF,yF) )
f.close()
import sys
sys.exit(0)
def getUpperbodyList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
minR = -179.90
maxR = 179.90
dof = 0
#-----------------------------------
#joints.append("hip_Xposition"); minima.append(-340.0); maxima.append(340.0); rootDofs.append(dof); dof+=1 # -529 529 original
#joints.append("hip_Yposition"); minima.append(-80.0); maxima.append(80.0); rootDofs.append(dof); dof+=1 # -207 208 original
#joints.append("hip_Zposition"); minima.append(-500.0); maxima.append(-100.0); rootDofs.append(dof); dof+=1 # -450 -90 original
#-------------------------------------------------------------------------------
#joints.append("hip_Zrotation"); minima.append(-45.0); maxima.append(45.0); rootDofs.append(dof); dof+=1
#joints.append("hip_Yrotation"); minima.append(minR); maxima.append(maxR); rootDofs.append(dof); dof+=1
#joints.append("hip_Xrotation"); minima.append(-45.0); maxima.append(45.0); rootDofs.append(dof); dof+=1
#-------------------------------------------------------------------------------
joints.append("abdomen_Zrotation"); minima.append(-175.82); maxima.append(maxR); dof+=1
joints.append("abdomen_Xrotation"); minima.append(-87.84); maxima.append(92.43); dof+=1
joints.append("abdomen_Yrotation"); minima.append(-176.7); maxima.append(173.33); dof+=1
joints.append("chest_Zrotation"); minima.append(-63.64); maxima.append(59.23); dof+=1
joints.append("chest_Xrotation"); minima.append(-59.62); maxima.append(42.48); dof+=1
joints.append("chest_Yrotation"); minima.append(-30.52); maxima.append(34.27); dof+=1
joints.append("neck1_Zrotation"); minima.append(-74.41); maxima.append(97.04); dof+=1
joints.append("neck1_Xrotation"); minima.append(-63.63); maxima.append(81.78); dof+=1
joints.append("neck1_Yrotation"); minima.append(-63.31); maxima.append(71.25); dof+=1
joints.append("head_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("head_Xrotation"); minima.append(-89.24); maxima.append(86.77); dof+=1
joints.append("head_Yrotation"); minima.append(-178.54); maxima.append(maxR); dof+=1
#-------------------------------------------------------------------------------
joints.append("rshoulder_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rshoulder_Xrotation"); minima.append(-102.07); maxima.append(103.87); dof+=1
joints.append("rshoulder_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("relbow_Zrotation"); minima.append(-44.67); maxima.append(34.52); dof+=1
joints.append("relbow_Xrotation"); minima.append(-68.55); maxima.append(9.42); dof+=1
joints.append("relbow_Yrotation"); minima.append(-110.29); maxima.append(164.34); dof+=1
joints.append("rhand_Zrotation"); minima.append(-169.3); maxima.append(4.01); dof+=1
joints.append("rhand_Xrotation"); minima.append(-88.3); maxima.append(85.24); dof+=1
joints.append("rhand_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#-------------------------------------------------------------------------------
joints.append("lshoulder_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lshoulder_Xrotation"); minima.append(-103.92); maxima.append(103.45); dof+=1
joints.append("lshoulder_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lelbow_Zrotation"); minima.append(-14.97); maxima.append(47.34); dof+=1
joints.append("lelbow_Xrotation"); minima.append(-68.43); maxima.append(8.68); dof+=1
joints.append("lelbow_Yrotation"); minima.append(-163.07); maxima.append(15.34); dof+=1
joints.append("lhand_Zrotation"); minima.append(-7.17); maxima.append(172.41); dof+=1
joints.append("lhand_Xrotation"); minima.append(-88.13); maxima.append(85.43); dof+=1
joints.append("lhand_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
#python3 sobolRandomDatasetGenerator.py --exponent 21 --lowerbody --copy
def getLowerbodyList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
minR = -179.90
maxR = 179.90
dof = 0
#-------------------------------------------------------------------------------
#These are no longer needed because they are randomized by the GroundTruthGenerator tool!
#joints.append("hip_Xposition"); minima.append(-340.0); maxima.append(340.0); rootDofs.append(dof); dof+=1 # -529 529 original
#joints.append("hip_Yposition"); minima.append(-80.0); maxima.append(80.0); rootDofs.append(dof); dof+=1 # -207 208 original
#joints.append("hip_Zposition"); minima.append(-500.0); maxima.append(-100.0); rootDofs.append(dof); dof+=1 # -450 -90 original
#-------------------------------------------------------------------------------
#joints.append("hip_Zrotation"); minima.append(-45.0); maxima.append(45.0); rootDofs.append(dof); dof+=1
#joints.append("hip_Yrotation"); minima.append(minR); maxima.append(maxR); rootDofs.append(dof); dof+=1
#joints.append("hip_Xrotation"); minima.append(-45.0); maxima.append(45.0); rootDofs.append(dof); dof+=1
#-------------------------------------------------------------------------------
#joints.append("abdomen_Zrotation"); minima.append(-174.88); maxima.append(174.88); dof+=1
#joints.append("abdomen_Xrotation"); minima.append(-90.0); maxima.append(90.0); dof+=1
#joints.append("abdomen_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#joints.append("chest_Zrotation"); minima.append(-57.0); maxima.append(57.0); dof+=1
#joints.append("chest_Xrotation"); minima.append(-61.78); maxima.append(40.94); dof+=1
#joints.append("chest_Yrotation"); minima.append(-35.27); maxima.append(27.58); dof+=1
#joints.append("neck1_Zrotation"); minima.append(-76.28); maxima.append(97.18); dof+=1
#joints.append("neck1_Xrotation"); minima.append(-63.08); maxima.append(81.78); dof+=1
#joints.append("neck1_Yrotation"); minima.append(-63.31); maxima.append(71.64); dof+=1
#-------------------------------------------------------------------------------
joints.append("rhip_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rhip_Xrotation"); minima.append(-104.0); maxima.append(94.0); dof+=1 #Default -104.11 .. 73.67
joints.append("rhip_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rknee_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rknee_Xrotation"); minima.append(-66.0); maxima.append(94.0); dof+=1 #Default -66.73 .. 94.07
joints.append("rknee_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rfoot_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("rfoot_Xrotation"); minima.append(-89.0); maxima.append(89.0); dof+=1 #Default -90.86 .. 89.26
joints.append("rfoot_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#-------------------------------------------------------------------------------
joints.append("lhip_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lhip_Xrotation"); minima.append(-104.0); maxima.append(94.0); dof+=1 #Default -104.23 .. 93.92
joints.append("lhip_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lknee_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lknee_Xrotation"); minima.append(-66.0); maxima.append(94.0); dof+=1 #Default -46.36 .. 94.34
joints.append("lknee_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lfoot_Zrotation"); minima.append(minR); maxima.append(maxR); dof+=1
joints.append("lfoot_Xrotation"); minima.append(-89.0); maxima.append(89.0); dof+=1 #Default -89.38 .. 91.81
joints.append("lfoot_Yrotation"); minima.append(minR); maxima.append(maxR); dof+=1
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
def getFullFaceList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
#/home/ammar/Programs/blender-3.4.1-linux-x64/3.4/scripts/addons/io_anim_bvh/import_bvh.py
#-----------------------------------
joints.append("hip_Xposition"); minima.append(-0.24); maxima.append(0.24); rootDofs.append(dof); dof+=1
joints.append("hip_Yposition"); minima.append(-0.10); maxima.append(0.10); rootDofs.append(dof); dof+=1
joints.append("hip_Zposition"); minima.append(-2.4); maxima.append(-1.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Zrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Xrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Yrotation"); minima.append(-30.0); maxima.append(30.0); rootDofs.append(dof); dof+=1
joints.append("eye.R_Zrotation"); minima.append(-45.36); maxima.append(45.36); dof+=1
joints.append("eye.R_Xrotation"); minima.append(-10.0); maxima.append(16.0); dof+=1
#Let's assume eyes move together..
#joints.append("eye.L_Zrotation"); minima.append(-20.0); maxima.append(20.0)
#joints.append("eye.L_Xrotation"); minima.append(-7.0); maxima.append(20.0)
joints.append("oculi01.R_Zrotation"); minima.append(-20.0); maxima.append(20.0); dof+=1
joints.append("oculi01.L_Zrotation"); minima.append(-20.0); maxima.append(20.0); dof+=1
joints.append("orbicularis03.R_Xrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
joints.append("orbicularis03.L_Xrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
#joints.append("orbicularis04.R_Xrotation"); minima.append(-15.0); maxima.append(15.0) #This is flipped orbicularis03.R_Xrotation
#joints.append("orbicularis04.L_Xrotation"); minima.append(-15.0); maxima.append(15.0) #This is flipped orbicularis03.L_Xrotation
joints.append("levator06.L_Xrotation"); minima.append(-9.0); maxima.append(9.0); dof+=1
#joints.append("levator06.R_Xrotation"); minima.append(-9.0); maxima.append(9.0) #This is levator06.L_Xrotation
joints.append("levator03.L_Zrotation"); minima.append(-8.0); maxima.append(9.0); dof+=1
#joints.append("levator03.R_Zrotation"); minima.append(-9.0); maxima.append(8.0); dof+=1 #This is flipped levator03.L_Zrotation
joints.append("oris03.L_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris03.R_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris07.L_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("oris07.R_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("jaw_Xrotation"); minima.append(-4.0); maxima.append(20.0); dof+=1
joints.append("jaw_Yrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
joints.append("oris04.L_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("oris04.R_Zrotation"); minima.append(0.0); maxima.append(30.0); dof+=1
joints.append("oris06.L_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris06.R_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
#-----------------------------------
constants["orbicularis03.R_Yrotation"] = 172.0
constants["orbicularis04.R_Yrotation"] = 172.0
constants["orbicularis03.L_Yrotation"] = -172.0
constants["orbicularis04.L_Yrotation"] = 172.0
constants["levator06.L_Yrotation"] = -247.0
constants["levator06.R_Yrotation"] = 247.0
constants["oris03.L_Xrotation"] = -40.0
constants["oris03.L_Yrotation"] = 172.0
constants["oris07.L_Yrotation"] = 172.0
constants["oris03.R_Xrotation"] = -40.0
constants["oris03.R_Yrotation"] = 179.0
constants["oris07.R_Yrotation"] = 172.0
constants["oris05_Xrotation"] = -35.0
constants["oris05_Yrotation"] = -176.0
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
def getReyeList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
#-----------------------------------
joints.append("hip_Xposition"); minima.append(-0.24); maxima.append(0.24); rootDofs.append(dof); dof+=1
joints.append("hip_Yposition"); minima.append(-0.10); maxima.append(0.10); rootDofs.append(dof); dof+=1
joints.append("hip_Zposition"); minima.append(-2.3); maxima.append(-1.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Zrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Xrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Yrotation"); minima.append(-30.0); maxima.append(30.0); rootDofs.append(dof); dof+=1
joints.append("eye.R_Zrotation"); minima.append(-45.36); maxima.append(45.36); dof+=1
joints.append("eye.R_Xrotation"); minima.append(-10.0); maxima.append(16.0); dof+=1
joints.append("oculi01.R_Zrotation"); minima.append(-20.0); maxima.append(20.0); dof+=1
joints.append("orbicularis03.R_Xrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
joints.append("jaw_Xrotation"); minima.append(-4.0); maxima.append(20.0); dof+=1 #Reason being adding some robustness
joints.append("jaw_Yrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1 #Reason being adding some chin robustness
#-----------------------------------
constants["orbicularis03.R_Yrotation"] = 172.0
constants["orbicularis04.R_Yrotation"] = 172.0
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
def getMouthList():
#-----------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
#-----------------------------------
joints.append("hip_Xposition"); minima.append(-0.24); maxima.append(0.24); rootDofs.append(dof); dof+=1
joints.append("hip_Yposition"); minima.append(-0.10); maxima.append(0.10); rootDofs.append(dof); dof+=1
joints.append("hip_Zposition"); minima.append(-2.4); maxima.append(-1.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Zrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Xrotation"); minima.append(-20.0); maxima.append(20.0); rootDofs.append(dof); dof+=1
joints.append("neck1_Yrotation"); minima.append(-30.0); maxima.append(30.0); rootDofs.append(dof); dof+=1
joints.append("levator06.L_Xrotation"); minima.append(-9.0); maxima.append(9.0); dof+=1
#joints.append("levator06.R_Xrotation"); minima.append(-9.0); maxima.append(9.0); dof+=1 #This is levator06.L_Xrotation
joints.append("levator03.L_Zrotation"); minima.append(-8.0); maxima.append(9.0); dof+=1
#joints.append("levator03.R_Zrotation"); minima.append(-9.0); maxima.append(8.0); dof+=1 #This is flipped levator03.L_Zrotation
joints.append("oris03.L_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris03.R_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris07.L_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("oris07.R_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("jaw_Xrotation"); minima.append(-4.0); maxima.append(20.0); dof+=1
joints.append("jaw_Yrotation"); minima.append(-15.0); maxima.append(15.0); dof+=1
joints.append("oris04.L_Zrotation"); minima.append(-30.0); maxima.append(0.0); dof+=1
joints.append("oris04.R_Zrotation"); minima.append(0.0); maxima.append(30.0); dof+=1
joints.append("oris06.L_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
joints.append("oris06.R_Zrotation"); minima.append(-30.0); maxima.append(30.0); dof+=1
#-----------------------------------
constants["levator06.L_Yrotation"] = -247.0
constants["levator06.R_Yrotation"] = 247.0
constants["oris03.L_Xrotation"] = -40.0
constants["oris03.L_Yrotation"] = 172.0
constants["oris07.L_Yrotation"] = 172.0
constants["oris03.R_Xrotation"] = -40.0
constants["oris03.R_Yrotation"] = 179.0
constants["oris07.R_Yrotation"] = 172.0
constants["oris05_Xrotation"] = -35.0
constants["oris05_Yrotation"] = -176.0
#-----------------------------------
return minima,maxima,joints,constants,dof,rootDofs
def getLHandList():
#--------------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
#--------------------------------------
joints.append("lhand_Xposition"); minima.append(-120.0); maxima.append(120.0); rootDofs.append(dof); dof+=1 #230
joints.append("lhand_Yposition"); minima.append(-60.0); maxima.append(60.0); rootDofs.append(dof); dof+=1 #92
joints.append("lhand_Zposition"); minima.append(-250.0); maxima.append(-75.0); rootDofs.append(dof); dof+=1
#joints.append("padding_1"); minima.append(0.0); maxima.append(0.0); rootDofs.append(dof); dof+=1 #<- Align to 4 elements
#--------------------------------------
joints.append("lhand_Wrotation"); minima.append(-1.0); maxima.append(1.0); rootDofs.append(dof); dof+=1
joints.append("lhand_Xrotation"); minima.append(-1.0); maxima.append(1.0); rootDofs.append(dof); dof+=1
joints.append("lhand_Yrotation"); minima.append(-1.0); maxima.append(1.0); rootDofs.append(dof); dof+=1
joints.append("lhand_Zrotation"); minima.append(-1.0); maxima.append(1.0); rootDofs.append(dof); dof+=1
#--------------------------------------
joints.append("finger2-1.l_Zrotation"); minima.append(-90.0); maxima.append(10.0); dof+=1
joints.append("finger2-1.l_Yrotation"); minima.append(-20.0); maxima.append(20.0); dof+=1
joints.append("finger2-2.l_Zrotation"); minima.append(-90.0); maxima.append(0.0); dof+=1
joints.append("finger2-3.l_Zrotation"); minima.append(-45.0); maxima.append(0.0); dof+=1
#--------------------------------------
joints.append("finger3-1.l_Zrotation"); minima.append(-90.0); maxima.append(10.0); dof+=1
joints.append("finger3-1.l_Yrotation"); minima.append(-10.0); maxima.append(10.0); dof+=1
joints.append("finger3-2.l_Zrotation"); minima.append(-90.0); maxima.append(0.0); dof+=1
joints.append("finger3-3.l_Zrotation"); minima.append(-45.0); maxima.append(0.0); dof+=1
#--------------------------------------
joints.append("finger4-1.l_Zrotation"); minima.append(-90.0); maxima.append(10.0); dof+=1
joints.append("finger4-1.l_Yrotation"); minima.append(-10.0); maxima.append(10.0); dof+=1
joints.append("finger4-2.l_Zrotation"); minima.append(-90.0); maxima.append(0.0); dof+=1
joints.append("finger4-3.l_Zrotation"); minima.append(-45.0); maxima.append(0.0); dof+=1
#--------------------------------------
joints.append("finger5-1.l_Zrotation"); minima.append(-90.0); maxima.append(10.0); dof+=1
joints.append("finger5-1.l_Yrotation"); minima.append(-8.0); maxima.append(25.0); dof+=1
joints.append("finger5-2.l_Zrotation"); minima.append(-90.0); maxima.append(0.0); dof+=1
joints.append("finger5-3.l_Zrotation"); minima.append(-45.0); maxima.append(0.0); dof+=1
#--------------------------------------
joints.append("lthumbBase_Zrotation"); minima.append(0.0); maxima.append(60.0); dof+=1
joints.append("lthumbBase_Xrotation"); minima.append(-35.0); maxima.append(0.0); dof+=1
joints.append("lthumbBase_Yrotation"); minima.append(0.0); maxima.append(60.0); dof+=1
#joints.append("padding_2"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#--------------------------------------
joints.append("lthumb_Zrotation"); minima.append(-85.0); maxima.append(85.0); dof+=1
joints.append("lthumb_Xrotation"); minima.append(-30.0); maxima.append(48.0); dof+=1
joints.append("lthumb_Yrotation"); minima.append(0.0); maxima.append(85.0); dof+=1
#joints.append("padding_3"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#--------------------------------------
joints.append("finger1-2.l_Zrotation"); minima.append(-35.0); maxima.append(0.0); dof+=1
joints.append("finger1-2.l_Xrotation"); minima.append(-40.0); maxima.append(45.0); dof+=1
joints.append("finger1-2.l_Yrotation"); minima.append(-70.0); maxima.append(35.0); dof+=1
#joints.append("padding_4"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#--------------------------------------
joints.append("finger1-3.l_Zrotation"); minima.append(-50.0); maxima.append(0.0); dof+=1
joints.append("finger1-3.l_Xrotation"); minima.append(0.0); maxima.append(50.0); dof+=1
#joints.append("padding_5"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#joints.append("padding_6"); minima.append(0.0); maxima.append(0.0); #<- Align to 4 elements
#--------------------------------------
return minima,maxima,joints,constants,dof,rootDofs
#------------------------------------------
# Generate actual samples..
#------------------------------------------
minima = list()
maxima = list()
joints = list()
constants = dict()
rootDofs = list()
dof = 0
datasetPart = "Face"
exponent = 17
doPlots = False
doFinalCopy = False
neutralSamples = 0
#----------------
# Exponent
#----------------
# 14 = 16.384
# 15 = 32.768
# 16 = 65.536
# 17 = 131.072
# 18 = 262.144
# 19 = 524.288
# 20 = 1.048.576
# 21 = 2.097.152
# 22 = 4.194.304
# 23 = 8.388.608
# 24 = 16.777.216
#----------------
import sys
mem = 1.0
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--scanreye"):
scanReye("SCANREYE.csv")
if (sys.argv[i]=="--copy"):
doFinalCopy = True
if (sys.argv[i]=="--plot"):
doPlots = True
if (sys.argv[i]=="--neutral"):
neutralSamples = int(sys.argv[i+1])
elif (sys.argv[i]=="--exponent"):
exponent = int(sys.argv[i+1])
elif (sys.argv[i]=="--upperbody"):
datasetPart = "Upperbody"
minima,maxima,joints,constants,dof,rootDofs = getUpperbodyList()
elif (sys.argv[i]=="--lowerbody"):
datasetPart = "Lowerbody"
minima,maxima,joints,constants,dof,rootDofs = getLowerbodyList()
elif (sys.argv[i]=="--lhand"):
datasetPart = "LHand"
minima,maxima,joints,constants,dof,rootDofs = getLHandList()
elif (sys.argv[i]=="--reye"):
datasetPart = "REye"
minima,maxima,joints,constants,dof,rootDofs = getReyeList()
elif (sys.argv[i]=="--mouth"):
datasetPart = "Mouth"
minima,maxima,joints,constants,dof,rootDofs = getMouthList()
elif (sys.argv[i]=="--face"):
datasetPart = "Face"
minima,maxima,joints,constants,dof,rootDofs = getFullFaceList()
if (len(minima)==0) and (len(maxima)==0) and (len(joints)==0):
print("Please rerun using --face OR --mouth OR --reye OR --lhand OR --upperbody OR --lowerbody to select a target")
numberOfDimensions = len(joints)
numberOfSamples = 2**exponent
filename = "sobol%s_%u.csv" % (datasetPart,numberOfSamples+neutralSamples)
#------------------------------------------
print("Will generate ",numberOfSamples," samples ")
print("Will generate random numbers for ",numberOfDimensions," dimensions")
print("We have ",dof," degrees of freedom")
samplesPerDimension = np.power(numberOfSamples,1/dof)
print("Samples per Dimension : %0.2f "%samplesPerDimension)
print("Involved joints are : ",joints)
sampler = qmc.Sobol(d=numberOfDimensions, scramble=False)
sample = sampler.random_base2(m=exponent)
print("Numbers generated now storing them to ",filename)
#print(sample)
#=========================================
# Write label
#=========================================
f = open(filename, 'w')
recordsWritten=0
#-----------------------------------------
for item in range(0,numberOfDimensions):
if (recordsWritten>0):
f.write(',')
#f.write("dim%u"%(recordsWritten))
f.write("%s" % (joints[item]))
recordsWritten=recordsWritten+1
#-----------------------------------------
if (constants):
for key in constants.keys():
if (recordsWritten>0):
f.write(',')
#f.write("dim%u"%(recordsWritten))
f.write("%s" % (joints[item]))
recordsWritten=recordsWritten+1
#-----------------------------------------
f.write("\n")
#=========================================
#=========================================
# Write Sobol Samples
#=========================================
for sampleNumber in range(0,numberOfSamples):
recordsWritten=0
for item in range(0,numberOfDimensions):
if (recordsWritten>0):
f.write(',')
thisRange = maxima[item]-minima[item]
f.write("%f"%( (thisRange * sample[sampleNumber][item]) + minima[item]) )
recordsWritten=recordsWritten+1
if (constants):
for key in constants.keys():
if (recordsWritten>0):
f.write(',')
f.write("%f"%(constants[key]))
recordsWritten=recordsWritten+1
f.write("\n")
#=========================================
#=========================================
# Write Neutral Samples
#=========================================
if (neutralSamples>0):
print("We will also append %u neutral samples " % neutralSamples)
#=========================================
for sampleNumber in range(0,neutralSamples):
recordsWritten=0
for item in range(0,numberOfDimensions):
if (recordsWritten>0):
f.write(',')
if (item in rootDofs):
#Poor quality uniform random value
value = random.uniform(minima[item],maxima[item])
else:
#True Neutral mean value
value = float((maxima[item]+minima[item]) / 2)
f.write("%f" % value)
recordsWritten=recordsWritten+1
if (constants):
for key in constants.keys():
if (recordsWritten>0):
f.write(',')
f.write("%f"%(constants[key]))
recordsWritten=recordsWritten+1
f.write("\n")
#=========================================
f.close()
import os
#------------------------------
if (doPlots):
os.system("python3 plotCSV.py --simple %s "%filename)
#------------------------------
command1 = ""
command2 = ""
command3 = ""
havePayload = False
minOrientation = -179.90
maxOrientation = 179.90
#------------------------------
if (datasetPart == "LHand"):
command1 = "rm dataset/generated/2d_lhand_all.csv dataset/generated/bvh_lhand_all.csv"
command2 = "./GroundTruthDumper --from dataset/lhand.qbvh --importCSVPoses %s --randomize2D 200 2500 -179.0 -179.0 -179.0 179.0 179.0 179.0 --selectJoints 1 17 lHand finger5-1.l finger5-2.l finger5-3.l finger4-1.l finger4-2.l finger4-3.l finger3-1.l finger3-2.l finger3-3.l finger2-1.l finger2-2.l finger2-3.l lthumbBase lthumb finger1-2.l finger1-3.l --hide2DLocationOfJoints 0 1 lthumbBase --csv dataset/generated/ lhand_all.csv 2d+bvh " % (filename)
command3 = "python3 compressCSVFile.py dataset/generated/bvh_lhand_all.csv && mv dataset/generated/bvh_lhand_all.csv dataset/generated/bvh_lhand_all.csv.original && mv compressed.csv dataset/generated/bvh_lhand_all.csv "
havePayload = True
elif (datasetPart == "Upperbody"):
command1 = "rm dataset/generated/2d_upperbody_all.csv dataset/generated/bvh_upperbody_all.csv"
command2 = "./GroundTruthDumper --from dataset/headerWithHeadAndOneMotion.bvh --importCSVPoses %s --randomize2D 1000 4500 -45 %0.2f -45 45 %0.2f 45 --selectJoints 1 13 hip eye.r eye.l abdomen chest neck head rshoulder relbow rhand lshoulder lelbow lhand --hide2DLocationOfJoints 0 4 abdomen chest eye.r eye.l --csv dataset/generated/ upperbody_all.csv 2d+bvh " % (filename,minOrientation,maxOrientation)
havePayload = True
elif (datasetPart == "Lowerbody"):
command1 = "rm dataset/generated/2d_lowerbody_all.csv dataset/generated/bvh_lowerbody_all.csv"
command2 = "./GroundTruthDumper --from dataset/headerWithHeadAndOneMotion.bvh --importCSVPoses %s --randomize2D 1000 4500 -45 %0.2f -45 45 %0.2f 45 --selectJoints 1 14 hip abdomen chest neck rhip rknee rfoot lhip lknee lfoot toe1-2.r toe5-3.r toe1-2.l toe5-3.l --hide2DLocationOfJoints 0 6 abdomen chest toe1-2.r toe5-3.r toe1-2.l toe5-3.l --csv dataset/generated/ lowerbody_all.csv 2d+bvh " % (filename,minOrientation,maxOrientation)
havePayload = True
#------------------------------
if (havePayload):
if (doFinalCopy):
os.system(command1)
os.system(command2)
if (command3!=""):
os.system(command3)
else:
print("To copy data, please execute : ")
print(command1)
print(command2)
if (command3!=""):
print(command3)
#------------------------------
@@ -0,0 +1,585 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import gc
import os
import sys
import time
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.models import Sequential
from tensorflow.keras.models import model_from_json
from tensorflow.keras.utils import plot_model
import numpy as np
from readCSV import parseConfiguration,checkIfConfigurationHierarchyIsTheSameAsLabelList,readGroundTruthFile,selectOnlySpecificColumnsOfNumpyArray
from DNNModel import loadModel,combineModels,combineAsSingleModel,saveModel
from tools import bcolors,dumpListToFile,createDirectory,checkIfPathExists,notification,getRAMInformation
from DNNTraining import printTrainingVersion,setTensorflowBackendToHalfFloats
def doCombinedModelValidation(outputDirectoryForCombinedModels,groundTruth,merged):
if (groundTruth["in"].shape[0]!=groundTruth["out"].shape[0]):
print(bcolors.FAIL,"Cannot perform network validation, mismatched input/output..",bcolors.ENDC)
sys.exit(1)
#----------------------------------------------------------------------------------
print(bcolors.OKBLUE,"Doing network validation..",bcolors.ENDC)
print("We have ",groundTruth["in"].shape[0]," input samples")
print("We have ",groundTruth["in"].shape[1]," elements in each input sample")
print("We have ",groundTruth["out"].shape[0]," output samples")
print("We have ",groundTruth["out"].shape[1]," elements in each output sample")
#-------------------------------------------------------------------------------
numberOfOutputs = groundTruth["out"].shape[1]
#-------------------------------------------------------------------------------
outputScalars = [1.0] * numberOfOutputs
outputOffsets = [0.0] * numberOfOutputs
outputMinima = [-6000.0] * numberOfOutputs
outputMaxima = [6000.0] * numberOfOutputs
#-------------------------------------------------------------------------------
from readCSV import parseOutputNormalization
from tools import readListFromFile,convertListToLowerCase
#-------------------------------------------------------------------------------
outputs = convertListToLowerCase(readListFromFile(outputDirectoryForCombinedModels+"/neuralNetworkOutputs.list"))
outputOffsets = parseOutputNormalization(outputDirectoryForCombinedModels,"/outputOffsets.csv",outputs,outputOffsets)
outputScalars = parseOutputNormalization(outputDirectoryForCombinedModels,"/outputScalarsFraction.csv",outputs,outputScalars)
outputMinima = parseOutputNormalization(outputDirectoryForCombinedModels,"/outputMinima.csv",outputs,outputMinima)
outputMaxima = parseOutputNormalization(outputDirectoryForCombinedModels,"/outputMaxima.csv",outputs,outputMaxima)
#-------------------------------------------------------------------------------
losses = list()
for outputItem in range(0,groundTruth["out"].shape[1]):
losses.append(0.0)
#----------------------------------------------------------------------------------
for sample in range(0,groundTruth["in"].shape[0]):
networkInput = np.asarray([groundTruth["in"][sample]],dtype=np.float32)
print("Sample : ",sample," |",end='')
inferenceOutputs = merged(tf.cast(networkInput,dtype=tf.float32))
for outputItem in range(0,groundTruth["out"].shape[1]):
out = float(inferenceOutputs[0][outputItem])
#------------------------------------------------------------
out = (out * outputScalars[i]) + outputOffsets[i]
if (out>outputMaxima[i]):
out=outputMaxima[i]
if (out<outputMinima[i]):
out=outputMinima[i]
#------------------------------------------------------------
thisLoss = float(abs(out-groundTruth["out"][sample][outputItem]))
print("|",thisLoss,"|",end='')
losses[outputItem] += thisLoss
print(" ")
#----------------------------------------------------------------------------------
for outputItem in range(0,groundTruth["out"].shape[1]):
print("Output item ",outputItem," loss ~=> ",float(losses[outputItem]/groundTruth["out"].shape[1]) )
sys.exit(0)
#-----------------------------------------------------------------------------------------------------------------
def step1_DNNCombine(useCSVBackend,groundTruth):
printTrainingVersion()
print("""
███████╗███╗ ██╗███████╗███████╗███╗ ███╗██████╗ ██╗ ███████╗
██╔════╝████╗ ██║██╔════╝██╔════╝████╗ ████║██╔══██╗██║ ██╔════╝
█████╗ ██╔██╗ ██║███████╗█████╗ ██╔████╔██║██████╔╝██║ █████╗
██╔══╝ ██║╚██╗██║╚════██║██╔══╝ ██║╚██╔╝██║██╔══██╗██║ ██╔══╝
███████╗██║ ╚████║███████║███████╗██║ ╚═╝ ██║██████╔╝███████╗███████╗
╚══════╝╚═╝ ╚═══╝╚══════╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚══════╝
""")
print("DNNTrainer starting up..\n")
np.set_printoptions(precision=2)
np.set_printoptions(formatter={"float_kind": lambda x: "%g" % x})
#Defaults
#-------------------
useHalfFloats = 0
useNonCompressed = 1
useCompressed = 1
#-------------------
#This will be get populated using the --config argument
configuration = dict()
configurationPath=""
numberOfChannelsPerNSDMElement=2
#datasetDirectory="../../DNNTracker/dataset"
datasetDirectory="dataset/generated/"
#By default no training samples need to be loaded
trainingSamplesPercentage=0.0
#Default Names
#------------------------------------------------
hierarchyPartName = "body"
label = "unknown"
dataFile = "body"
testFile = "body_test"
outputMode = "bvh"
configuration['outputMode'] = "bvh"
doModelOptimization = False
doModelValidation = False
inputLabels = list()
outputLabels = list()
#------------------------------------------------
outputDirectoryForTrainedModels ="step0FrontBody"
outputDirectoryForCombinedModels="step1FrontBody"
filesPath=outputDirectoryForTrainedModels #"./"
#------------------------------------------------
if (len(sys.argv)>1):
print('Argument List:', str(sys.argv))
for i in range(0, len(sys.argv)):
if (sys.argv[i]=="--mem"):
print("Will load more than 0 training samples.. ",sys.argv[i+1],"\n");
trainingSamplesPercentage=float(sys.argv[i+1])
if (sys.argv[i]=="--optimize"):
print("Will also attempt to optimize network\n");
trainingSamplesPercentage=1.0 #<- This should be like --mem 1.0
doModelOptimization = True
if (sys.argv[i]=="--validate"):
print("Will also attempt to validate network\n");
trainingSamplesPercentage=1.0 #<- This should be like --mem 1.0
doModelValidation = True
if (sys.argv[i]=="--config"):
configurationPath = sys.argv[i+1]
configuration = parseConfiguration(configurationPath)
label = configuration['OutputDirectory']
if (configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element set to ",numberOfChannelsPerNSDMElement)
if (configuration['precision']=="fp16"):
useHalfFloats=1
configuration['rememberWeights']=0
setTensorflowBackendToHalfFloats()
elif (configuration['precision']!="fp32"):
print(bcolors.WARNING,"Cannot use ",configuration['precision']," precision\n",bcolors.ENDC)
if (sys.argv[i]=="--lpdnn"):
print("Force Network Padding\n")
configuration['padEnsembleInput'] = 1
if (sys.argv[i]=="--3d"):
print("The network will generate 3D points instead of angles\n")
outputMode = "3d"
configuration['outputMode'] = "3d"
configuration['groupOutputs'] = 3
if (sys.argv[i]=="--halffloats"):
useHalfFloats=1
setTensorflowBackendToHalfFloats()
if (sys.argv[i]=="--from"):
print("\nCombining.. ",sys.argv[i+1],"\n");
outputDirectoryForTrainedModels = sys.argv[i+1]
if (sys.argv[i]=="--categoryall"):
hierarchyPartName=sys.argv[i+1]
dataFile="%s_all" % hierarchyPartName
outputDirectoryForTrainedModels = "step2_%s" % dataFile
startModel=0
endModel=6
print("stepAll has been reduced to a single encoder so no need to merge it we will just copy it")
#os.system('cp step0All/hip_Yrotation/model.h5 step0All/mergedModel.h5')
#os.system('cp step0All/hip_Yrotation/model.json step0All/mergedModel.json')
groundTruth = readGroundTruthFile(
configuration,
"Reference",
"%s/2d_%s.csv" % (datasetDirectory,dataFile),
"%s/%s_%s.csv" % (datasetDirectory,configuration['outputMode'],dataFile),
0,
numberOfChannelsPerNSDMElement,
0,#dont use radians
0,#dont use half floats
)
#combineAsSingleModel(outputDirectoryForTrainedModels,"hip_Yrotation",len(groundTruth['labelIn']),len(groundTruth['labelOut']),"mergedModel","all")
combineAsSingleModel(outputDirectoryForTrainedModels,"Category",len(groundTruth['labelIn']),len(groundTruth['labelOut']),"mergedModelCategory","all")
sys.exit(0)
#-----------------------------------------------
# New 4 way split
#-----------------------------------------------
if (sys.argv[i]=="--all"):
hierarchyPartName=sys.argv[i+1]
label="all"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
if (sys.argv[i]=="--back"):
hierarchyPartName=sys.argv[i+1]
label="back"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
if (sys.argv[i]=="--front"):
hierarchyPartName=sys.argv[i+1]
label="front"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
if (sys.argv[i]=="--left"):
hierarchyPartName=sys.argv[i+1]
label="left"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
if (sys.argv[i]=="--right"):
hierarchyPartName=sys.argv[i+1]
label="right"
dataFile="%s_%s" % (hierarchyPartName,label)
outputDirectoryForTrainedModels ="step0_%s" % dataFile
outputDirectoryForCombinedModels="step1_%s" % dataFile
#Combine needs to read the decomposition files from the outputDirectoryForTrainedModels
#---------------------------------------------------------------------------------------------------
pathToDefaultDecompositionFilesFolder = configuration['doPCA'].split("/")
if (len(pathToDefaultDecompositionFilesFolder)>0):
#Resolve PCA name.. :(
x = pathToDefaultDecompositionFilesFolder[1].split("$")
if (len(x)>0):
#If there is a $ character this is our place holder to autocomplete our dataFile
print("PCA filename is resolved from ",configuration['doPCA'])
print(" to ")
configuration['doPCA']=outputDirectoryForTrainedModels+"/"+x[0]+dataFile+".pca"
print(configuration['doPCA'])
#Calculate number of channels per NSDM elements
#---------------------------------------------------------------------------------------------------
numberOfChannelsPerNSDMElement=2
if (configuration['NSDMAlsoUseAlignmentAngles']==1):
numberOfChannelsPerNSDMElement=1
print("Number of Channels Per NSDM element ",numberOfChannelsPerNSDMElement)
configuration['numberOfChannelsPerNSDMElement']=numberOfChannelsPerNSDMElement
#Eigenposes should be loaded before Train/Test files since they are used in the input transform step
#---------------------------------------------------------------------------------------------------
if ("eigenPoses" in configuration):
#We have eigenPoses Declared!
if (configuration['eigenPoses']==1):
#We have eigenPoses Active!
configuration['eigenPoseData'] = readGroundTruthFile(
configuration,
"Eigenposes",
"%s/2d_%s_eigenposes.csv" % (datasetDirectory,dataFile),
"%s/%s_%s_eigenposes.csv" % (datasetDirectory,configuration['outputMode'],dataFile), #configuration['outputMode'] is either bvh or 3d
1.0,
numberOfChannelsPerNSDMElement,
configuration['useRadians'],
useHalfFloats
)
#We only want headers so we ask for 0.0 memory usage which means just the labels and one record..
#groundTruth = readGroundTruthFile("Test" ,"../../DNNTracker/dataset/2d_test.csv","../../DNNTracker/dataset/bvh_test.csv",0.0,useNonCompressed,useCompressed,configuration['useRadians'],useHalfFloats)
#==============================================================================================================================
#==============================================================================================================================
#==============================================================================================================================
#The inputLabels/outputLabels are very important to create a combined network that has the
#correct outputs, there are 2 ways to load them, the old way was through the groundtruth file
#the new way is through the .list files, since neuralNetworkOutputs.list gets overwritten
#to enable quick copy of networks
#--------------------------------------------------------------------------------------------
inputLabelsNew=""; outputLabelsNew=""; inputLabelsOld=""; outputLabelsOld=""
#--------------------------------------------------------------------------------------------
from tools import checkIfFileExists,readListFromFile,convertListToLowerCase,checkIfListsAreTheSame
#--------------------------------------------------------------------------------------------
inputLabelsPath = outputDirectoryForTrainedModels+"/neuralNetworkInputs.list"
outputLabelsPath = outputDirectoryForTrainedModels+"/neuralNetworkOutputsOriginal.list"
if (checkIfFileExists(inputLabelsPath) and checkIfFileExists(outputLabelsPath) ):
print("Using labels from %s / %s..\n" % (inputLabelsPath,outputLabelsPath) )
inputLabelsNew = readListFromFile(inputLabelsPath)
outputLabelsNew = readListFromFile(outputLabelsPath)
#--------------------------------------------------------------------------------------------
#If we are using CSV backend AND ( new labels loading failed or we want to do model optimization ),
if (useCSVBackend) and ( (inputLabelsNew=="") or (outputLabelsNew=="") or ((doModelOptimization) and (trainingSamplesPercentage>0.0)) ):
groundTruth = readGroundTruthFile(
configuration,
"Reference",
"%s/2d_%s.csv" % (datasetDirectory,dataFile),
"%s/%s_%s.csv" % (datasetDirectory,configuration['outputMode'],dataFile),
trainingSamplesPercentage,
numberOfChannelsPerNSDMElement,
configuration['useRadians'],
useHalfFloats
)
inputLabelsOld = groundTruth['labelIn']
outputLabelsOld = groundTruth['labelOut']
#--------------------------------------------------------------------------------------------
#We need the labels for our input and output..!
#We used to get these from the ground truth file, however nowadays
#they also exist in the neuralNetworkInputs.list / neuralNetworkOutputs.list
#all this code exists in order to try to be backwards compatible :(
#--------------------------------------------------------------------------------------------
if (inputLabelsNew!="") and (outputLabelsNew!="") and (inputLabelsOld!="") and (outputLabelsOld!=""):
print(bcolors.OKGREEN,"We have both new and old input labels.. Selecting the new labels",bcolors.ENDC)
inputLabels = inputLabelsNew
outputLabels = outputLabelsNew
if (len(inputLabelsOld)!=len(inputLabelsNew)) or (len(outputLabelsOld)!=len(outputLabelsNew)):
print(bcolors.FAIL,"I/O labels mismatch between test label set and I/O .list files ..",bcolors.ENDC)
sys.exit(1)
if ( not checkIfListsAreTheSame(inputLabelsOld,inputLabelsNew) ):
print(bcolors.FAIL,"I/O labels mismatch between input test label set and I/O .list files ..",bcolors.ENDC)
sys.exit(1)
if ( not checkIfListsAreTheSame(outputLabelsOld,outputLabelsNew) ):
print(bcolors.FAIL,"I/O labels mismatch between output test label set and I/O .list files ..",bcolors.ENDC)
sys.exit(1)
elif (inputLabelsNew=="") and (outputLabelsNew=="") and (inputLabelsOld!="") and (outputLabelsOld!=""):
print(bcolors.OKGREEN,"We only have OLD labels from groundTruth, using them",bcolors.ENDC)
inputLabels = inputLabelsOld
outputLabels = outputLabelsOld
elif (inputLabelsNew!="") and (outputLabelsNew!="") and (inputLabelsOld=="") and (outputLabelsOld==""):
print(bcolors.OKGREEN,"We only have NEW labels from .list files, using them",bcolors.ENDC)
inputLabels = inputLabelsNew
outputLabels = outputLabelsNew
else:
print(bcolors.FAIL,"Weird combination of I/O labels, don't know what to do so stopping to avoid mistakes..",bcolors.ENDC)
sys.exit(1)
#--------------------------------------------------------------------------------------------
#==============================================================================================================================
#==============================================================================================================================
#==============================================================================================================================
numberOfOutputColumns=len(outputLabels)
#Shorthand to be able to do tricks without altering configuration
#-----------------------------------------------------------
numberOfOutputsOfEachEncoder = configuration['groupOutputs']
if (numberOfOutputsOfEachEncoder==0):
#This special case means that the encoder should span everything automatically..!
numberOfOutputsOfEachEncoder = numberOfOutputColumns #len(groundTruthTest['out'][0])
print(bcolors.WARNING + "step0_DNNTrainer.py : Setting numberOfOutputsOfEachEncoder = %u" % numberOfOutputsOfEachEncoder + bcolors.ENDC )
#--------------------------------------------------------------------------------------------
if ( len(inputLabels)==0 or len(outputLabels)==0 ):
print("I/O labels could not be parsed, we don't know what to do to combine encoders..")
sys.exit(1)
#--------------------------------------------------------------------------------------------
if (not checkIfConfigurationHierarchyIsTheSameAsLabelList(configuration,inputLabels,1)):
print("Inconsistent Configuration association compared to the inputLabelList")
sys.exit(1)
#--------------------------------------------------------------------------------------------
if ('probabilisticOutput' in configuration) and (configuration['probabilisticOutput']==1):
if (numberOfOutputsOfEachEncoder!=1):
print(bcolors.FAIL,"Overriding group outputs setting and setting it to 1!",bcolors.ENDC)
numberOfOutputsOfEachEncoder=1
#--------------------------------------------------------------------------------------------
startModel = 0 # We want to combine all labels so we start from zero..!
endModel = len(outputLabels) # We want to combine all labels so we start at label length zero..!
print("Will read from %s , start at %u and stop at %u ..\n" % (outputDirectoryForTrainedModels,startModel,endModel) )
print("Combined model will have input size of ",len(inputLabels)," and output size of ",len(outputLabels)," \n")
outputName="none"
expectedModelNames=list()
#----------------------------------------------------------------------------------------
#we take care of new potentially more complex naming scheme based on the output groupping
for outputType in range(startModel,endModel,numberOfOutputsOfEachEncoder):
#if we have multiple outputs groupped we want to concatenate all their names to keep track of all handled joints
if (numberOfOutputsOfEachEncoder==numberOfOutputColumns):
#Guard against : File name too long [Op:CreateSummaryFileWriter]
outputName="everything"
expectedModelNames.append(outputName)
elif (numberOfOutputsOfEachEncoder==1):
outputName=outputLabels[outputType]
expectedModelNames.append(outputName)
elif (numberOfOutputsOfEachEncoder>1):
outputName = ""
isFirst = 1
for nameToConcatenate in range(outputType,outputType+numberOfOutputsOfEachEncoder):
if (isFirst==0):
outputName=outputName+"-" #so that output is "3DX_hip_3DY_hip_3DZ_hip" instead of "3DX_hip3DY_hip3DZ_hip"
outputName = outputName + outputLabels[nameToConcatenate]
isFirst = 0
expectedModelNames.append(outputName)
#----------------------------------------------------------------------------------------
print("Expected model names are : ",expectedModelNames)
if (checkIfPathExists(outputDirectoryForCombinedModels)):
print("We found old combined output (%s), we will wipe it to make sure everything is clean! ",outputDirectoryForCombinedModels)
os.system('rm -rf %s/'% (outputDirectoryForCombinedModels))
os.system('mkdir %s/'% (outputDirectoryForCombinedModels))
padEnsembleInput=0
if 'padEnsembleInput' in configuration:
padEnsembleInput=int(configuration['padEnsembleInput'])
#Make a fresh merged Model
mergedModelInMemory,mergedOutputs,selectedColumns = combineModels(
configuration,
outputDirectoryForTrainedModels,
"mergedModel",
len(inputLabels),
len(outputLabels), #The outputs we get in total remain the same
expectedModelNames, # outputLabels
startModel,
len(expectedModelNames), #This is actually shrunk down from endModel,
label,
lpdnnPadding=padEnsembleInput
)
#Load fresh merged Model using its h5/json format
#no longer reloading merged
merged = mergedModelInMemory
#merged=loadModel(outputDirectoryForTrainedModels,"mergedModel")
gc.collect()
#If --optimize or --mem>0 try to optimize network
#------------------------------------------------------------------------------
if (doModelOptimization) and (trainingSamplesPercentage>0.0) and (numberOfOutputsOfEachEncoder==1) and (configuration['probabilisticOutput']==0):
print(bcolors.OKBLUE,"Doing network optimization..",bcolors.ENDC)
trainingSelectedOutput = selectOnlySpecificColumnsOfNumpyArray(groundTruth['out'],selectedColumns,useHalfFloats)
from DNNOptimize import pruneModel,clusterModel
optimized = pruneModel(merged,groundTruth['in'],trainingSelectedOutput)
#These 2 can't work together!
#optimized = clusterModel(merged,configuration,groundTruth['in'],trainingSelectedOutput)
#saveModel(outputDirectoryForTrainedModels,optimized,name="optimizedModel") <- RuntimeError: Unable to create link (name already exists) on clustering
#from DNNOptimize import quantizeModel
#Quantizing a tf.keras Model inside another tf.keras Model is not supported.
#optimized = quantizeModel(merged,groundTruth['in'],trainingSelectedOutput)
#saveModel(outputDirectoryForTrainedModels,optimized,name="optimizedQuantizedModel")
print("Overriding model with optimized version!")
merged=optimized
else:
print("To also optimize model please supply --optimize ( OR --mem VALUE with a value >0 )")
#------------------------------------------------------------------------------
print(bcolors.OKBLUE,"Saving Combined model to ",outputDirectoryForCombinedModels,"..",bcolors.ENDC)
startAt = time.time()
merged.save(outputDirectoryForCombinedModels, save_format='tf') # <- Actually Save Neural Network to File
endAt = time.time()
print(bcolors.OKGREEN,"Save operation took %0.2f mins "%((endAt-startAt)/60),bcolors.ENDC)
#We will also copy with it the two I/O lists to make our lifes easier
print(bcolors.OKBLUE,"Handle configuration files..",bcolors.ENDC)
#---------------------------------------------------------------------------------------------------------------------
os.system('cp %s/*.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/summary.html %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputMinima.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputMaxima.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputScalars.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputScalarsFraction.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/outputOffsets.csv %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/neuralNetworkJoints.list %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
os.system('cp %s/neuralNetworkInputs.list %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
#---------------------------------------------------------------------------------------------------------------------
configFileStandaloneName = os.path.basename(configurationPath)
os.system('cp %s/%s %s/' % (outputDirectoryForTrainedModels,configFileStandaloneName,outputDirectoryForCombinedModels))
#PLEASE KEEP IN MIND THAT THE BASH SCRIPTS ALSO DO THEIR OWN COPIES SO THIS IS
#IS CURRENTLY WAY MORE COMPLICATED THAT IT NEEDS TO..!
#Initially the idea was to directly grab the .pca file from the dataset/ dir however nowadays things are more complex
#os.system('cp %s/%s %s/' % (outputDirectoryForTrainedModels,pcaFileStandaloneName,outputDirectoryForCombinedModels))
#We will now copy *ALL* files hoping to cover everything!
pcaFileStandaloneName = os.path.basename(configuration['doPCA'])
os.system('cp %s/%s %s/' % (outputDirectoryForTrainedModels,pcaFileStandaloneName,outputDirectoryForCombinedModels))
os.system('cp %s/%s* %s/' % (outputDirectoryForTrainedModels,pcaFileStandaloneName,outputDirectoryForCombinedModels))
if (numberOfOutputsOfEachEncoder!=numberOfOutputColumns):
#Write culled list ..!
print("Overwriting neuralNetworkOutputs.list with culled output list")
dumpListToFile(outputDirectoryForCombinedModels+"/neuralNetworkOutputs.list" ,mergedOutputs)
else:
print("We are targeting everything at once so not copying instead of overwriting neuralNetworkOutputs.list with culled output list")
os.system('cp %s/neuralNetworkOutputs.list %s/' % (outputDirectoryForTrainedModels,outputDirectoryForCombinedModels))
if (numberOfOutputsOfEachEncoder==numberOfOutputColumns):
print("We won't mess around with outputs..") #Case when everything is selected at once..
elif (numberOfOutputsOfEachEncoder>1):
os.system('cp %s %s' % (outputDirectoryForCombinedModels+"/neuralNetworkOutputs.list",outputDirectoryForCombinedModels+"/neuralNetworkOutputsOriginal.list"))
from tools import splitTextBasedOnGroupNumber
splitTextBasedOnGroupNumber(numberOfOutputsOfEachEncoder,outputDirectoryForCombinedModels+"/neuralNetworkOutputsOriginal.list",outputDirectoryForCombinedModels+"/neuralNetworkOutputs.list")
#My PC doesn't have enough RAM for this..
#print(bcolors.OKBLUE,"Also Creating a TensorRT Model..",bcolors.ENDC)
#-----------------------------------------------------------------
#from DNNOptimize import convertToTensorRT
#convertToTensorRT(merged,precision="fp16")
#merged.save(outputDirectoryForCombinedModels+"/trt_fp16", save_format='tf') #save directory..
#convertToTensorRT(merged,precision="fp32")
#merged.save(outputDirectoryForCombinedModels+"/trt_fp32", save_format='tf') #save directory..
#-----------------------------------------------------------------
# Try to do validation
#-----------------------------------------------------------------------------------------------------------------
if (doModelValidation) and (trainingSamplesPercentage>0.0) and (numberOfOutputsOfEachEncoder==1):
doCombinedModelValidation(outputDirectoryForCombinedModels,groundTruth,merged)
#-----------------------------------------------------------------------------------------------------------------
RAM = getRAMInformation()
if (RAM["free"]<2000000):
print(bcolors.FAIL,"We do not have enough memory (we have ",RAM["free"],") to generate a TF-Lite model..",bcolors.ENDC)
print(" Please manually run : ",bcolors.OKGREEN," tflite_convert --saved_model_dir=%s --output_file=%s/model.tflite"% (outputDirectoryForCombinedModels,outputDirectoryForCombinedModels),bcolors.ENDC)
else:
print(bcolors.OKBLUE,"Also Creating a TF-Lite Model..",bcolors.ENDC)
gc.collect()
#------------------------------------------------------------------------------
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir=outputDirectoryForCombinedModels)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
if (doModelOptimization) and (trainingSamplesPercentage>0.0):
#If we gave a training sample set then we can enable post training quantization on TFLite
#converter.representative_dataset = groundTruth['in']
#converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
#converter.target_spec.supported_types = [tf.int8]
#converter.inference_input_type = tf.float32 # tf.int8 # or tf.uint8
#converter.inference_output_type = tf.float32 # tf.int8 # or tf.uint8
pass
tflite_model = converter.convert()
with open('%s/model.tflite' % outputDirectoryForCombinedModels, 'wb') as f:
f.write(tflite_model)
#------------------------------------------------------------------------------
#tf2onnx hogs a lot of memory, we will not use any inputs after this point
del groundTruth
gc.collect()
#Show signatures..
#https://www.tensorflow.org/guide/saved_model#the_savedmodel_format_on_disk
print(bcolors.OKBLUE,"Double-check tensorflow model signatures..",bcolors.ENDC)
os.system('saved_model_cli show --dir %s/ --tag_set serve --signature_def serving_default' % (outputDirectoryForCombinedModels))
#--------------------------------------------------------------------------------------------------------------------------------------
RAM = getRAMInformation()
if (RAM["free"]<2000000):
print(bcolors.FAIL,"We do not have enough memory (we have ",RAM["free"],") to generate an ONNX model..",bcolors.ENDC)
print(" Please manually run : ",bcolors.OKGREEN," python3 -m tf2onnx.convert --saved-model %s --opset 17 --tag serve --output %s/model.onnx " % (outputDirectoryForCombinedModels,outputDirectoryForCombinedModels),bcolors.ENDC)
print("See : https://onnxruntime.ai/docs/reference/compatibility.html for the best OPSET")
else:
print(" Please manually run : ",bcolors.OKGREEN," python3 -m tf2onnx.convert --saved-model %s --opset 17 --tag serve --output %s/model.onnx " % (outputDirectoryForCombinedModels,outputDirectoryForCombinedModels),bcolors.ENDC)
#This gets the main python script killed for some reason on cvrldemo..
#print(bcolors.OKBLUE,"Also Creating an ONNX Model..",bcolors.ENDC) #assuming python3 -m pip install tf2onnx
#--------------------------------------------------------------------------------------------------------------------------------------
#os.system("python3 -m tf2onnx.convert --saved-model %s --opset 14 --tag serve --output %s/model.onnx " % (outputDirectoryForCombinedModels,outputDirectoryForCombinedModels))
#--------------------------------------------------------------------------------------------------------------------------------------
notification("MocapNET Network Compilation","Done merging %s "%(outputDirectoryForCombinedModels))
print("To view training run : ",bcolors.OKGREEN," tensorboard --logdir %s/tensorboard/ --bind_all" % (outputDirectoryForTrainedModels),bcolors.ENDC)
print(bcolors.OKGREEN,"Done merging",bcolors.ENDC)
sys.exit(0)
if __name__ == '__main__':
useCSVBackend=1
emptyTrainData=dict()
step1_DNNCombine(useCSVBackend,emptyTrainData)
@@ -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")
@@ -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()