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
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,164 @@
abdomen
chest
neck
neck1
head
__jaw
jaw
special04
oris02
oris01
oris06.l
oris07.l
oris06.r
oris07.r
tongue00
tongue01
tongue02
tongue03
__tongue04
tongue04
tongue07.l
tongue07.r
tongue06.l
tongue06.r
tongue05.l
tongue05.r
__levator02.l
levator02.l
levator03.l
levator04.l
levator05.l
__levator02.r
levator02.r
levator03.r
levator04.r
levator05.r
__special01
special01
oris04.l
oris03.l
oris04.r
oris03.r
oris06
oris05
__special03
special03
__levator06.l
levator06.l
__levator06.r
levator06.r
special06.l
special05.l
eye.l
orbicularis03.l
orbicularis04.l
special06.r
special05.r
eye.r
orbicularis03.r
orbicularis04.r
__temporalis01.l
temporalis01.l
oculi02.l
oculi01.l
__temporalis01.r
temporalis01.r
oculi02.r
oculi01.r
__temporalis02.l
temporalis02.l
risorius02.l
risorius03.l
__temporalis02.r
temporalis02.r
risorius02.r
risorius03.r
rCollar
rShldr
rForeArm
rHand
metacarpal1.r
finger2-1.r
finger2-2.r
finger2-3.r
metacarpal2.r
finger3-1.r
finger3-2.r
finger3-3.r
__metacarpal3.r
metacarpal3.r
finger4-1.r
finger4-2.r
finger4-3.r
__metacarpal4.r
metacarpal4.r
finger5-1.r
finger5-2.r
finger5-3.r
__rthumb
rthumb
finger1-2.r
finger1-3.r
lCollar
lShldr
lForeArm
lHand
metacarpal1.l
finger2-1.l
finger2-2.l
finger2-3.l
metacarpal2.l
finger3-1.l
finger3-2.l
finger3-3.l
__metacarpal3.l
metacarpal3.l
finger4-1.l
finger4-2.l
finger4-3.l
__metacarpal4.l
metacarpal4.l
finger5-1.l
finger5-2.l
finger5-3.l
__lthumb
lthumb
finger1-2.l
finger1-3.l
rButtock
rThigh
rShin
rFoot
toe1-1.R
toe1-2.R
toe2-1.R
toe2-2.R
toe2-3.R
toe3-1.R
toe3-2.R
toe3-3.R
toe4-1.R
toe4-2.R
toe4-3.R
toe5-1.R
toe5-2.R
toe5-3.R
lButtock
lThigh
lShin
lFoot
toe1-1.L
toe1-2.L
toe2-1.L
toe2-2.L
toe2-3.L
toe3-1.L
toe3-2.L
toe3-3.L
toe4-1.L
toe4-2.L
toe4-3.L
toe5-1.L
toe5-2.L
toe5-3.L
@@ -0,0 +1,714 @@
#pragma once
#include <stdio.h>
/**
* @brief A C struct to hold a 2D coordinate
*/
struct point2D
{
float x,y;
};
/**
* @brief A C struct to hold a 3D coordinate
*/
struct point3D
{
float x,y,z;
};
/**
* @brief A structure to hold a bounding box
*/
struct boundingBox
{
char populated;
float minimumX;
float maximumX;
float minimumY;
float maximumY;
};
/**
* @brief This is an array of names for all the old COCO body parts.
*/
static const char * COCOOldBodyNames[] =
{
"Nose", //0
"Neck", //1
"RShoulder", //2
"RElbow", //3
"RWrist", //4
"LShoulder", //5
"LElbow", //6
"LWrist", //7
"RHip", //8
"RKnee", //9
"RAnkle", //10
"LHip", //11
"LKnee", //12
"LAnkle", //13
"REye", //14
"LEye", //15
"REar", //16
"LEar", //17
"Bkg", //18
//=================
"End of Joint Names"
};
/**
* @brief An enumerator of coco skeleton joints
*/
//https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/media/keypoints_pose_18.png
enum COCOOldSkeletonJoints
{
COCO_Nose=0,
COCO_Neck,
COCO_RShoulder,
COCO_RElbow,
COCO_RWrist,
COCO_LShoulder,
COCO_LElbow,
COCO_LWrist,
COCO_RHip,
COCO_RKnee,
COCO_RAnkle,
COCO_LHip,
COCO_LKnee,
COCO_LAnkle,
COCO_REye,
COCO_LEye,
COCO_REar,
COCO_LEar,
COCO_Bkg,
//---------------------
COCO_PARTS
};
/**
* @brief An array of indexes to the parents of coco skeleton joints
*/
static const int COCOSkeletonJointsParentRelationMap[] =
{
// Parent Joint
COCO_Nose, //COCO_Nose,
COCO_Nose, //COCO_Neck,
COCO_Neck, //COCO_RShoulder,
COCO_RShoulder, //COCO_RElbow,
COCO_RElbow, //COCO_RWrist,
COCO_Neck, //COCO_LShoulder,
COCO_LShoulder, //COCO_LElbow,
COCO_LElbow, //COCO_LWrist,
COCO_Neck, //COCO_RHip,
COCO_RHip, //COCO_RKnee,
COCO_RKnee, //COCO_RAnkle,
COCO_Neck, //COCO_LHip,
COCO_LHip, //COCO_LKnee,
COCO_LKnee, //COCO_LAnkle,
COCO_Nose, //COCO_REye,
COCO_Nose, //COCO_LEye,
COCO_REye, //COCO_REar,
COCO_LEye, //COCO_LEar,
COCO_Bkg //COCO_Bkg
};
/**
* @brief This is an array of names for all the new BODY25 body parts.
* This is a "friendly" array, meaning it is meant to be easy to understand and does not need to exactly correspond to the BVH file..
*/
static const char * Body25BodyFriendlyNames[] =
{
"Nose", //0
"Neck", //1
"RShoulder", //2
"RElbow", //3
"RWrist", //4
"LShoulder", //5
"LElbow", //6
"LWrist", //7
"MidHip", //8
"RHip", //9
"RKnee", //10
"RAnkle", //11
"LHip", //12
"LKnee", //13
"LAnkle", //14
"REye", //15
"LEye", //16
"REar", //17
"LEar", //18
"LBigToe", //19
"LSmallToe", //20
"LHeel", //21
"RBigToe", //22
"RSmallToe", //23
"RHeel", //24
"Bkg", //25
//=================
"End of Joint Names"
};
/**
* @brief This is an array of names for all the new BODY25 body parts.
* This tries to mirror body_configuration.json and everything used is lowercase exactly for this reason..
* it also has to be the same with the bvh file headerWithHeadAndOneMotion.bvh
*/
static const char * Body25BodyNames[] =
{
"head", //0
"neck", //1
"rshoulder", //2
"relbow", //3
"rhand", //4
"lshoulder", //5
"lelbow", //6
"lhand", //7
"hip", //8
"rhip", //9
"rknee", //10
"rfoot", //11
"lhip", //12
"lknee", //13
"lfoot", //14
"endsite_eye.r", //15
"endsite_eye.l", //16
"rear", //17 ========= No correspondance
"lear", //18 ========= No correspondance
"endsite_toe1-2.l",//19
"endsite_toe5-3.l",//20
"lheel", //21 ========= No correspondance
"endsite_toe1-2.r",//22
"endsite_toe5-3.r",//23
"rheel", //24 ========= No correspondance
"bkg", //25 ========= No correspondance
//==================
"End of Joint Names"
};
/**
* @brief An enumerator of BODY 25 skeleton joints
*/
enum Body25SkeletonJoints
{
BODY25_Nose=0,
BODY25_Neck,
BODY25_RShoulder,
BODY25_RElbow,
BODY25_RWrist,
BODY25_LShoulder,
BODY25_LElbow,
BODY25_LWrist,
BODY25_MidHip,
BODY25_RHip,
BODY25_RKnee,
BODY25_RAnkle,
BODY25_LHip,
BODY25_LKnee,
BODY25_LAnkle,
BODY25_REye,
BODY25_LEye,
BODY25_REar,
BODY25_LEar,
BODY25_LBigToe,
BODY25_LSmallToe,
BODY25_LHeel,
BODY25_RBigToe,
BODY25_RSmallToe,
BODY25_RHeel,
BODY25_Bkg,
//---------------------
BODY25_PARTS
};
/**
* @brief An array of indexes to the parents of BODY25 skeleton joints
*/
static const int Body25SkeletonJointsParentRelationMap[] =
{
// Parent Joint
BODY25_Nose, //BODY25_Nose,
BODY25_Nose, //BODY25_Neck,
BODY25_Neck, //BODY25_RShoulder,
BODY25_RShoulder, //BODY25_RElbow,
BODY25_RElbow, //BODY25_RWrist,
BODY25_Neck, //BODY25_LShoulder,
BODY25_LShoulder, //BODY25_LElbow,
BODY25_LElbow, //BODY25_LWrist,
BODY25_Neck, //BODY25_MidHip
BODY25_MidHip, //BODY25_RHip,
BODY25_RHip, //BODY25_RKnee,
BODY25_RKnee, //BODY25_RAnkle,
BODY25_MidHip, //BODY25_LHip,
BODY25_LHip, //BODY25_LKnee,
BODY25_LKnee, //BODY25_LAnkle,
BODY25_Nose, //BODY25_REye,
BODY25_Nose, //BODY25_LEye,
BODY25_REye, //BODY25_REar,
BODY25_LEye, //BODY25_LEar,
BODY25_LHeel, //BODY25_LBigToe,
BODY25_LBigToe, //BODY25_LSmallToe,
BODY25_LAnkle, //BODY25_LHeel,
BODY25_RHeel, //BODY25_RBigToe,
BODY25_RBigToe, //BODY25_RSmallToe,
BODY25_RAnkle, // BODY25_RHeel,
BODY25_Bkg //BODY25_Bkg
};
/**
* @brief An enumerator of COCO Hand joints
*/
//https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/media/keypoints_hand.png
enum COCOHandJoints
{
COCO_Hand_Wrist=0,//0
COCO_Hand_Thumb_1,//1
COCO_Hand_Thumb_2, //2
COCO_Hand_Thumb_3, //3
COCO_Hand_Thumb_4,//4
COCO_Hand_Index_1,//5
COCO_Hand_Index_2,//6
COCO_Hand_Index_3,//7
COCO_Hand_Index_4,//8
COCO_Hand_Middle_1,//9
COCO_Hand_Middle_2,//10
COCO_Hand_Middle_3,//11
COCO_Hand_Middle_4,//12
COCO_Hand_Ring_1,//13
COCO_Hand_Ring_2,//14
COCO_Hand_Ring_3,//15
COCO_Hand_Ring_4,//16
COCO_Hand_Pinky_1,//17
COCO_Hand_Pinky_2,//18
COCO_Hand_Pinky_3,//19
COCO_Hand_Pinky_4,//20
//---------------------
COCO_HAND_PARTS
};
/**
* @brief This is an array of names for the left hand.
* This is a "friendly" array, meaning it is meant to be easy to understand and does not need to exactly correspond to the BVH file..
*/
static const char * COCOLeftHandFriendlyNames[] =
{
"Left_Hand_Wrist",//0
"Left_Hand_Thumb_1",//1
"Left_Hand_Thumb_2", //2
"Left_Hand_Thumb_3", //3
"Left_Hand_Thumb_4",//4
"Left_Hand_Index_1",//5
"Left_Hand_Index_2",//6
"Left_Hand_Index_3",//7
"Left_Hand_Index_4",//8
"Left_Hand_Middle_1",//9
"Left_Hand_Middle_2",//10
"Left_Hand_Middle_3",//11
"Left_Hand_Middle_4",//12
"Left_Hand_Ring_1",//13
"Left_Hand_Ring_2",//14
"Left_Hand_Ring_3",//15
"Left_Hand_Ring_4",//16
"Left_Hand_Pinky_1",//17
"Left_Hand_Pinky_2",//18
"Left_Hand_Pinky_3",//19
"Left_Hand_Pinky_4",//20
//--------------------
"End of Left Hand Names"
};
/**
* @brief This is an array of names for the left hand.
* This tries to mirror lhand_configuration.json and everything used is lowercase exactly for this reason..
* it also has to be the same with the bvh file headerWithHeadAndOneMotion.bvh
*/
static const char * COCOLeftHandNames[] =
{
"lhand",//0
"lthumb",//1
"finger1-2.l", //2
"finger1-3.l", //3
"endsite_finger1-3.l",//4
"finger2-1.l",//5
"finger2-2.l",//6
"finger2-3.l",//7
"endsite_finger2-3.l",//8
"finger3-1.l",//9
"finger3-2.l",//10
"finger3-3.l",//11
"endsite_finger3-3.l",//12
"finger4-1.l",//13
"finger4-2.l",//14
"finger4-3.l",//15
"endsite_finger4-3.l",//16
"finger5-1.l",//17
"finger5-2.l",//18
"finger5-3.l",//19
"endsite_finger5-3.l",//20
//--------------------
"End of Left Hand Names"
};
/**
* @brief This is an array of names for the right hand.
* This is a "friendly" array, meaning it is meant to be easy to understand and does not need to exactly correspond to the BVH file..
*/
static const char * COCORightHandFriendlyNames[] =
{
"Right_Hand_Wrist",//0
"Right_Hand_Thumb_1",//1
"Right_Hand_Thumb_2", //2
"Right_Hand_Thumb_3", //3
"Right_Hand_Thumb_4",//4
"Right_Hand_Index_1",//5
"Right_Hand_Index_2",//6
"Right_Hand_Index_3",//7
"Right_Hand_Index_4",//8
"Right_Hand_Middle_1",//9
"Right_Hand_Middle_2",//10
"Right_Hand_Middle_3",//11
"Right_Hand_Middle_4",//12
"Right_Hand_Ring_1",//13
"Right_Hand_Ring_2",//14
"Right_Hand_Ring_3",//15
"Right_Hand_Ring_4",//16
"Right_Hand_Pinky_1",//17
"Right_Hand_Pinky_2",//18
"Right_Hand_Pinky_3",//19
"Right_Hand_Pinky_4",//20
//--------------------
"End of Right Hand Names"
};
/**
* @brief This is an array of names for the right hand.
* This tries to mirror rhand_configuration.json and everything used is lowercase exactly for this reason..
* it also has to be the same with the bvh file headerWithHeadAndOneMotion.bvh
*/
static const char * COCORightHandNames[] =
{
"rhand",//0
"rthumb",//1
"finger1-2.r", //2
"finger1-3.r", //3
"endsite_finger1-3.r",//4
"finger2-1.r",//5
"finger2-2.r",//6
"finger2-3.r",//7
"endsite_finger2-3.r",//8
"finger3-1.r",//9
"finger3-2.r",//10
"finger3-3.r",//11
"endsite_finger3-3.r",//12
"finger4-1.r",//13
"finger4-2.r",//14
"finger4-3.r",//15
"endsite_finger4-3.r",//16
"finger5-1.r",//17
"finger5-2.r",//18
"finger5-3.r",//19
"endsite_finger5-3.r",//20
//--------------------
"End of Right Hand Names"
};
/**
* @brief An enumerator of COCO Hand joints
*/
//https://raw.githubusercontent.com/CMU-Perceptual-Computing-Lab/openpose/master/doc/media/keypoints_face.png
enum OP_HeadJoints
{
OP_Head_RChin_0=0, //0
OP_Head_RChin_1, //1
OP_Head_RChin_2, //2
OP_Head_RChin_3, //3
OP_Head_RChin_4, //4
OP_Head_RChin_5, //5
OP_Head_RChin_6, //6
OP_Head_RChin_7, //7
OP_Head_Chin, //8
OP_Head_LChin_7 , //9
OP_Head_LChin_6, //10
OP_Head_LChin_5, //11
OP_Head_LChin_4, //12
OP_Head_LChin_3, //13
OP_Head_LChin_2, //14
OP_Head_LChin_1, //15
OP_Head_LChin_0, //16
OP_Head_REyebrow_0, //17
OP_Head_REyebrow_1, //18
OP_Head_REyebrow_2, //19
OP_Head_REyebrow_3, //20
OP_Head_REyebrow_4, //21
OP_Head_LEyebrow_4, //22
OP_Head_LEyebrow_3, //23
OP_Head_LEyebrow_2, //24
OP_Head_LEyebrow_1, //25
OP_Head_LEyebrow_0, //26
OP_Head_NoseBone_0,//27
OP_Head_NoseBone_1,//28
OP_Head_NoseBone_2,//29
OP_Head_NoseBone_3,//30
OP_Head_Nostrills_0,//31
OP_Head_Nostrills_1,//32
OP_Head_Nostrills_2,//33
OP_Head_Nostrills_3,//34
OP_Head_Nostrills_4,//35
OP_Head_REye_0,//36
OP_Head_REye_1,//37
OP_Head_REye_2,//38
OP_Head_REye_3,//39
OP_Head_REye_4,//40
OP_Head_REye_5,//41
OP_Head_LEye_0,//42
OP_Head_LEye_1,//43
OP_Head_LEye_2,//44
OP_Head_LEye_3,//45
OP_Head_LEye_4,//46
OP_Head_LEye_5,//47
OP_Head_OutMouth_0,//48
OP_Head_OutMouth_1,//49
OP_Head_OutMouth_2,//50
OP_Head_OutMouth_3,//51
OP_Head_OutMouth_4,//52
OP_Head_OutMouth_5,//53
OP_Head_OutMouth_6,//54
OP_Head_OutMouth_7,//55
OP_Head_OutMouth_8,//56
OP_Head_OutMouth_9,//57
OP_Head_OutMouth_10,//58
OP_Head_OutMouth_11,//59
OP_Head_InMouth_0,//60
OP_Head_InMouth_1,//61
OP_Head_InMouth_2,//62
OP_Head_InMouth_3,//63
OP_Head_InMouth_4,//64
OP_Head_InMouth_5,//65
OP_Head_InMouth_6,//66
OP_Head_InMouth_7,//67
OP_Head_REye,//68
OP_Head_LEye,//69
//---------------------
OP_HEAD_PARTS
};
static const char * HeadNames[] =
{
"Head_RChin_0", //0
"Head_RChin_1", //1
"Head_RChin_2", //2
"Head_RChin_3", //3
"Head_RChin_4", //4
"Head_RChin_5", //5
"Head_RChin_6", //6
"Head_RChin_7", //7
"Head_Chin", //8
"Head_LChin_7", //9
"Head_LChin_6", //10
"Head_LChin_5", //11
"Head_LChin_4", //12
"Head_LChin_3", //13
"Head_LChin_2", //14
"Head_LChin_1", //15
"Head_LChin_0", //16
"Head_REyebrow_0",//17
"Head_REyebrow_1",//18
"Head_REyebrow_2",//19
"Head_REyebrow_3",//20
"Head_REyebrow_4",//21
"Head_LEyebrow_4",//22
"Head_LEyebrow_3",//23
"Head_LEyebrow_2",//24
"Head_LEyebrow_1",//25
"Head_LEyebrow_0",//26
"Head_NoseBone_0",//27
"Head_NoseBone_1",//28
"Head_NoseBone_2",//29
"Head_NoseBone_3",//30
"Head_Nostrills_0",//31
"Head_Nostrills_1",//32
"Head_Nostrills_2",//33
"Head_Nostrills_3",//34
"Head_Nostrills_4",//35
"Head_REye_0",//36
"Head_REye_1",//37
"Head_REye_2",//38
"Head_REye_3",//39
"Head_REye_4",//40
"Head_REye_5",//41
"Head_LEye_0",//42
"Head_LEye_1",//43
"Head_LEye_2",//44
"Head_LEye_3",//45
"Head_LEye_4",//46
"Head_LEye_5",//47
"Head_OutMouth_0",//48
"Head_OutMouth_1",//49
"Head_OutMouth_2",//50
"Head_OutMouth_3",//51
"Head_OutMouth_4",//52
"Head_OutMouth_5",//53
"Head_OutMouth_6",//54
"Head_OutMouth_7",//55
"Head_OutMouth_8",//56
"Head_OutMouth_9",//57
"Head_OutMouth_10",//58
"Head_OutMouth_11",//59
"Head_InMouth_0",//60
"Head_InMouth_1",//61
"Head_InMouth_2",//62
"Head_InMouth_3",//63
"Head_InMouth_4",//64
"Head_InMouth_5",//65
"Head_InMouth_6",//66
"Head_InMouth_7",//67
"Head_REye",//68
"Head_LEye"//69
};
/**
* @brief A C struct to hold a hand. It contains its 2D points, its 3D points and some flags that signal
*/
struct handCOCO
{
int isPopulated;
int isLeft;
int isRight;
struct point2D joint2D[COCO_HAND_PARTS];
float jointAccuracy[COCO_HAND_PARTS];
unsigned int active[COCO_HAND_PARTS];
struct point3D joint[COCO_HAND_PARTS];
};
/**
* @brief A C struct to hold a hand. It contains its 2D points, its 3D points and some flags that signal
*/
struct headOP
{
int isPopulated;
struct point2D joint2D[OP_HEAD_PARTS];
float jointAccuracy[OP_HEAD_PARTS];
unsigned int active[OP_HEAD_PARTS];
struct point3D joint[OP_HEAD_PARTS];
};
/**
* @brief A C struct to hold a body. It contains its 2D points, its 3D points and some flags that signal
*/
struct body25OP
{
int isPopulated;
struct point2D joint2D[BODY25_PARTS];
struct point2D bbox2D[2];
float jointAccuracy[BODY25_PARTS];
unsigned int active[BODY25_PARTS];
struct point3D joint[BODY25_PARTS];
struct point3D bbox[8];
};
/**
* @brief A C struct to hold a skeleton. It contains its 2D points, its 3D points and some flags that signal
*/
struct skeletonStructure
{
unsigned int observationNumber , observationTotal;
unsigned int userID;
unsigned int totalUsersPresent;
//------------------------
struct body25OP body;
struct handCOCO leftHand;
struct handCOCO rightHand;
struct headOP head;
//------------------------
struct boundingBox bbox2D;
};
struct headerField
{
unsigned int strLength;
char * str;
};
struct bodyField
{
float value;
};
struct skeletonSerialized
{
unsigned int skeletonHeaderElements;
struct headerField skeletonHeader[512];
unsigned int skeletonBodyElements;
struct bodyField skeletonBody[512];
float width;
float height;
};
static void printSkeletonSerialized(const char * msg, struct skeletonSerialized * sk )
{
if (msg!=0)
{
fprintf(stderr,"printSkeletonSerialized (%s)\n",msg);
}
if (sk==0)
{
fprintf(stderr,"struct skeletonSerialized that was given as input is not allocated\n");
return;
}
if (sk->skeletonHeaderElements != sk->skeletonBodyElements)
{
fprintf(stderr,"struct skeletonSerialized is corrupted since it has a different number of head and body records..\n");
return;
}
fprintf(stderr,"Serialization has %u elements\n",sk->skeletonHeaderElements);
for (unsigned int skID = 0; skID<sk->skeletonHeaderElements; skID++)
{
if (sk->skeletonHeader[skID].str==0)
{
fprintf(stderr," Serial #%u has an empty label => % 0.2f \n" ,skID , sk->skeletonBody[skID].value);
} else
{
fprintf(stderr," %s => % 0.2f \n" ,sk->skeletonHeader[skID].str , sk->skeletonBody[skID].value);
}
}
}
@@ -0,0 +1,827 @@
#include "conversions.hpp"
#include <string.h>
#include <vector>
#include "../tools.hpp"
#include "bvh.hpp"
#include "csvRead.hpp"
#include "../../../../dependencies/RGBDAcquisition/tools/AmMatrix/matrix4x4Tools.h"
#define NORMAL "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
int appendVectorToFile(const char * filename, std::vector<float> vec)
{
FILE * fp = fopen(filename,"a");
if (fp!=0)
{
for (unsigned int i=0; i<vec.size(); i++)
{
if (i!=0) { fprintf(fp,","); }
fprintf(fp,"%f",vec[i]);
}
fprintf(fp,"\n");
fclose(fp);
return 1;
}
return 0;
}
int initializeAssociationsForSubsetOfSkeleton(unsigned int * targetIndexIsInitializedFlag,unsigned int * targetIndexes,unsigned int targetLength,const char * * targetLabels,struct skeletonSerialized * input)
{
//int i=0,z=0;
for (unsigned int i=0; i<targetLength; i++)
{
targetIndexes[i]=666;
}
char targetLabelLowercase[513]={0};
for (unsigned int i=0; i<targetLength; i++)
{
convertStringToLowercase(targetLabelLowercase,512,targetLabels[i]);
for (unsigned int z=0; z<input->skeletonHeaderElements; z++)
{
if (input->skeletonHeader[z].str!=0)
{
if (strcmp(input->skeletonHeader[z].str,targetLabelLowercase)==0)
{
if (targetIndexes[i]==666)
{
targetIndexes[i]=z;
fprintf(stderr,GREEN "%s==%s\n" NORMAL,input->skeletonHeader[z].str,targetLabelLowercase);
} else
{
fprintf(stderr,YELLOW "%s==%s multiple times, only keeping first association..\n" NORMAL,input->skeletonHeader[z].str,targetLabelLowercase);
}
} //We have a matching string..
} //There is a string to compare
}
}
unsigned int unassociatedJoints=0;
for (unsigned int i=0; i<targetLength; i++)
{
if ( targetIndexes[i]==666 ) {
++unassociatedJoints;
fprintf(stderr,RED "Joint %s(%u) is not associated\n" NORMAL,targetLabels[i],i);
} else
{ fprintf(stderr,GREEN "Joint %s(%u) associated\n" NORMAL,targetLabels[i],i); }
}
*targetIndexIsInitializedFlag=(unassociatedJoints==0);
return (unassociatedJoints==0);
}
std::vector<float> deriveMocapNET2InputUsingAssociations(struct MocapNET2 * mnet,struct skeletonSerialized * input,unsigned int * targetIndexIsInitializedFlag,unsigned int * targetIndexes,unsigned int targetLength,const char * * targetLabels,int verbose)
{
std::vector<float> result;
if (mnet->indexesPopulated)
{
if (! *targetIndexIsInitializedFlag)
{
fprintf(stderr,RED "deriveMocapNET2InputUsingAssociations called without initialization\n" NORMAL);
initializeAssociationsForSubsetOfSkeleton(
targetIndexIsInitializedFlag,
targetIndexes,
targetLength,
targetLabels,
input
);
}
for (int i=0; i<targetLength; i++)
{
if (verbose) { fprintf(stderr,"%s = %0.2f -> %s \n" , input->skeletonHeader[targetIndexes[i]].str , input->skeletonBody[targetIndexes[i]].value ,targetLabels[i]); }
result.push_back(input->skeletonBody[targetIndexes[i]].value);
}
} else
{
fprintf(stderr,RED "initializeAssociationsForSubsetOfSkeleton has to be run at initialization before deriveMocapNET2InputUsingAssociations\n");
}
return result;
}
int convertSkeletons2DDetectedToSkeletonsSerialized(
struct skeletonSerialized * output,
struct Skeletons2DDetected * input,
unsigned int frameNumber,
unsigned int width,
unsigned int height
)
{
int check;
if (output->skeletonHeaderElements==0)
{
//Brand new header that needs to be populated..!
int elementsPopulated=3;
output->skeletonHeader[0].strLength = 12;
output->skeletonHeader[0].str=(char *) malloc(sizeof(char) * output->skeletonHeader[0].strLength);
snprintf(output->skeletonHeader[0].str,output->skeletonHeader[0].strLength,"frameNumber");
output->skeletonHeader[1].strLength = 11;
output->skeletonHeader[1].str=(char *) malloc(sizeof(char) * output->skeletonHeader[1].strLength);
snprintf(output->skeletonHeader[1].str,output->skeletonHeader[1].strLength,"skeletonID");
output->skeletonHeader[2].strLength = 15;
output->skeletonHeader[2].str=(char *) malloc(sizeof(char) * output->skeletonHeader[2].strLength);
snprintf(output->skeletonHeader[2].str,output->skeletonHeader[2].strLength,"totalSkeletons");
char lowercaseName[512]={0};
for (int i=0; i<BODY25_PARTS; i++)
{
convertStringToLowercase(lowercaseName,512,Body25BodyNames[i]);
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"2dx_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"2dy_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+9;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"visible_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
}
for (int i=0; i<COCO_HAND_PARTS; i++)
{
convertStringToLowercase(lowercaseName,512,COCOLeftHandNames[i]);
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"2dx_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"2dy_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+9;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"visible_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
}
for (int i=0; i<COCO_HAND_PARTS; i++)
{
convertStringToLowercase(lowercaseName,512,COCORightHandNames[i]);
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"2dx_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"2dy_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+9;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"visible_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
}
for (int i=0; i<OP_HEAD_PARTS; i++)
{
convertStringToLowercase(lowercaseName,512,HeadNames[i]);
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"2dx_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"2dy_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+9;
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
if (output->skeletonHeader[elementsPopulated].str!=0)
{
check = snprintf(
output->skeletonHeader[elementsPopulated].str ,
output->skeletonHeader[elementsPopulated].strLength,
"visible_%s",
lowercaseName
);
if (check<0) { return 0; }
} else { return 0; }
++elementsPopulated;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
}
output->skeletonHeaderElements = elementsPopulated;
}
// Reduce spam
// else
//{
// fprintf(stderr,"SkeletonSerialized appears to be already populated, skipping re allocating everything..\n");
//}
//=================================================================================
//=================================================================================
//=================================================================================
//=================================================================================
//=================================================================================
// Now to convert the values..
//=================================================================================
//=================================================================================
//=================================================================================
//=================================================================================
//=================================================================================
output->skeletonBodyElements = output->skeletonHeaderElements;
//Points will be normalized using normalize2DPointWhileAlsoMatchingTrainingAspectRatio
output->width = 1.0;
output->height = 1.0;
for (unsigned int skID=0; skID<input->numberOfSkeletonsDetected; skID++)
{
int bodyElementsPopulated=3;
output->skeletonBody[0].value = frameNumber;
output->skeletonBody[1].value = skID;
output->skeletonBody[2].value = input->numberOfSkeletonsDetected;
for (int i=0; i<BODY25_PARTS; i++)
{
//Normalize targets --------------------------------------------------------------
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
&input->skeletons[skID].body.joint2D[i].x,
&input->skeletons[skID].body.joint2D[i].y,
width,
height,
1,//Respect training aspect ratio
MocapNETTrainingWidth,
MocapNETTrainingHeight
);
//--------------------------------------------------------------------------------
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].body.joint2D[i].x;
++bodyElementsPopulated;
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].body.joint2D[i].y;
++bodyElementsPopulated;
output->skeletonBody[bodyElementsPopulated].value = ( (input->skeletons[skID].body.joint2D[i].x!=0) && (input->skeletons[skID].body.joint2D[i].y!=0) ) ;
/*
if (!output->skeletonBody[bodyElementsPopulated].value)
{
fprintf(stderr,"%s not populated.. \n" ,Body25BodyNames[i]);
}*/
++bodyElementsPopulated;
//--------------------------------------------------------------------------------
}
for (int i=0; i<COCO_HAND_PARTS; i++)
{
//Normalize targets --------------------------------------------------------------
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
&input->skeletons[skID].leftHand.joint2D[i].x,
&input->skeletons[skID].leftHand.joint2D[i].y,
width,
height,
1,//Respect training aspect ratio
MocapNETTrainingWidth,
MocapNETTrainingHeight
);
//--------------------------------------------------------------------------------
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].leftHand.joint2D[i].x;
++bodyElementsPopulated;
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].leftHand.joint2D[i].y;
++bodyElementsPopulated;
output->skeletonBody[bodyElementsPopulated].value =( (input->skeletons[skID].leftHand.joint2D[i].x!=0) && (input->skeletons[skID].leftHand.joint2D[i].y!=0) ) ;
++bodyElementsPopulated;
//--------------------------------------------------------------------------------
}
for (int i=0; i<COCO_HAND_PARTS; i++)
{
//Normalize targets --------------------------------------------------------------
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
&input->skeletons[skID].rightHand.joint2D[i].x,
&input->skeletons[skID].rightHand.joint2D[i].y,
width,
height,
1,//Respect training aspect ratio
MocapNETTrainingWidth,
MocapNETTrainingHeight
);
//--------------------------------------------------------------------------------
output->skeletonBody[bodyElementsPopulated].value = input->skeletons[skID].rightHand.joint2D[i].x;
++bodyElementsPopulated;
output->skeletonBody[bodyElementsPopulated].value = input->skeletons[skID].rightHand.joint2D[i].y;
++bodyElementsPopulated;
output->skeletonBody[bodyElementsPopulated].value = ( (input->skeletons[skID].rightHand.joint2D[i].x!=0) && (input->skeletons[skID].rightHand.joint2D[i].y!=0) );
++bodyElementsPopulated;
//--------------------------------------------------------------------------------
}
for (int i=0; i<OP_HEAD_PARTS; i++)
{
//Normalize targets --------------------------------------------------------------
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
&input->skeletons[skID].head.joint2D[i].x,
&input->skeletons[skID].head.joint2D[i].y,
width,
height,
1,//Respect training aspect ratio
MocapNETTrainingWidth,
MocapNETTrainingHeight
);
//--------------------------------------------------------------------------------
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].head.joint2D[i].x;
++bodyElementsPopulated;
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].head.joint2D[i].y;
++bodyElementsPopulated;
output->skeletonBody[bodyElementsPopulated].value = ( (input->skeletons[skID].head.joint2D[i].x!=0) && (input->skeletons[skID].head.joint2D[i].y!=0) );
++bodyElementsPopulated;
}
}
return 1;
}
int convertMocapNET2OutputToSkeletonSerialized(
struct MocapNET2 * mnet,
struct skeletonSerialized * output,
std::vector<std::vector<float> > mocapNET2DPointsResult,
unsigned int frameNumber,
unsigned int width,
unsigned int height
)
{
if (mocapNET2DPointsResult.size()==0)
{
fprintf(stderr,"convertMocapNET2OutputToSkeletonSerialized cannot work without 3D point results\n");
return 0;
}
struct Skeletons2DDetected input={0};
input.numberOfSkeletonsDetected=1;
input.skeletons[0].body.joint2D[BODY25_Nose].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS05][0];
input.skeletons[0].body.joint2D[BODY25_Nose].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS05][1];
input.skeletons[0].body.joint2D[BODY25_Neck].x = mocapNET2DPointsResult[MOCAPNET_JOINT_NECK][0];
input.skeletons[0].body.joint2D[BODY25_Neck].y = mocapNET2DPointsResult[MOCAPNET_JOINT_NECK][1];
input.skeletons[0].body.joint2D[BODY25_RShoulder].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RSHOULDER][0];
input.skeletons[0].body.joint2D[BODY25_RShoulder].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RSHOULDER][1];
input.skeletons[0].body.joint2D[BODY25_RElbow].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RELBOW][0];
input.skeletons[0].body.joint2D[BODY25_RElbow].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RELBOW][1];
input.skeletons[0].body.joint2D[BODY25_RWrist].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RHAND][0];
input.skeletons[0].body.joint2D[BODY25_RWrist].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RHAND][1];
input.skeletons[0].body.joint2D[BODY25_LShoulder].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LSHOULDER][0];
input.skeletons[0].body.joint2D[BODY25_LShoulder].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LSHOULDER][1];
input.skeletons[0].body.joint2D[BODY25_LElbow].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LELBOW][0];
input.skeletons[0].body.joint2D[BODY25_LElbow].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LELBOW][1];
input.skeletons[0].body.joint2D[BODY25_LWrist].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LHAND][0];
input.skeletons[0].body.joint2D[BODY25_LWrist].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LHAND][1];
input.skeletons[0].body.joint2D[BODY25_MidHip].x = mocapNET2DPointsResult[MOCAPNET_JOINT_HIP][0];
input.skeletons[0].body.joint2D[BODY25_MidHip].y = mocapNET2DPointsResult[MOCAPNET_JOINT_HIP][1];
input.skeletons[0].body.joint2D[BODY25_RHip].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RHIP][0];
input.skeletons[0].body.joint2D[BODY25_RHip].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RHIP][1];
input.skeletons[0].body.joint2D[BODY25_RKnee].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RKNEE][0];
input.skeletons[0].body.joint2D[BODY25_RKnee].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RKNEE][1];
input.skeletons[0].body.joint2D[BODY25_RAnkle].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RFOOT][0];
input.skeletons[0].body.joint2D[BODY25_RAnkle].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RFOOT][1];
input.skeletons[0].body.joint2D[BODY25_LHip].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LHIP][0];
input.skeletons[0].body.joint2D[BODY25_LHip].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LHIP][1];
input.skeletons[0].body.joint2D[BODY25_LKnee].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LKNEE][0];
input.skeletons[0].body.joint2D[BODY25_LKnee].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LKNEE][1];
input.skeletons[0].body.joint2D[BODY25_LAnkle].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LFOOT][0];
input.skeletons[0].body.joint2D[BODY25_LAnkle].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LFOOT][1];
input.skeletons[0].body.joint2D[BODY25_REye].x = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_R][0];
input.skeletons[0].body.joint2D[BODY25_REye].y = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_R][1];
input.skeletons[0].body.joint2D[BODY25_LEye].x = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_L][0];
input.skeletons[0].body.joint2D[BODY25_LEye].y = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_L][1];
input.skeletons[0].body.joint2D[BODY25_REar].x = mocapNET2DPointsResult[MOCAPNET_JOINT_TEMPORALIS02_R][0];
input.skeletons[0].body.joint2D[BODY25_REar].y = mocapNET2DPointsResult[MOCAPNET_JOINT_TEMPORALIS02_R][1];
input.skeletons[0].body.joint2D[BODY25_LEar].x = mocapNET2DPointsResult[MOCAPNET_JOINT_TEMPORALIS02_L][0];
input.skeletons[0].body.joint2D[BODY25_LEar].y = mocapNET2DPointsResult[MOCAPNET_JOINT_TEMPORALIS02_L][1];
input.skeletons[0].body.joint2D[BODY25_LBigToe].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE1_2_L][0];
input.skeletons[0].body.joint2D[BODY25_LBigToe].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE1_2_L][1];
input.skeletons[0].body.joint2D[BODY25_LSmallToe].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE5_3_L][0];
input.skeletons[0].body.joint2D[BODY25_LSmallToe].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE5_3_L][1];
input.skeletons[0].body.joint2D[BODY25_LHeel].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LFOOT][0];
input.skeletons[0].body.joint2D[BODY25_LHeel].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LFOOT][1];
input.skeletons[0].body.joint2D[BODY25_RBigToe].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE1_2_R][0];
input.skeletons[0].body.joint2D[BODY25_RBigToe].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE1_2_R][1];
input.skeletons[0].body.joint2D[BODY25_RSmallToe].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE5_3_R][0];
input.skeletons[0].body.joint2D[BODY25_RSmallToe].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE5_3_R][1];
input.skeletons[0].body.joint2D[BODY25_RHeel].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RFOOT][0];
input.skeletons[0].body.joint2D[BODY25_RHeel].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RFOOT][1];
//Dont forget to update convertBodySkeletonSerializedToBVHTransform
//Populate right hand
input.skeletons[0].rightHand.joint2D[COCO_Hand_Wrist].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RHAND][0]; //MOCAPNET_OUTPUT_JOINT_RHAND
input.skeletons[0].rightHand.joint2D[COCO_Hand_Wrist].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RHAND][1]; //MOCAPNET_OUTPUT_JOINT_RHAND
//---------------------------------------------------------------------------------
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RTHUMB][0]; //MOCAPNET_OUTPUT_JOINT_RTHUMB
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RTHUMB][1]; //MOCAPNET_OUTPUT_JOINT_RTHUMB
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_2_R][0]; //MOCAPNET_OUTPUT_JOINT_RTHUMB
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_2_R][1]; //MOCAPNET_OUTPUT_JOINT_RTHUMB
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER1_2_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER1_2_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER1_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER1_3_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER1_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER1_3_R
//---------------------------------------------------------------------------------
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_1_R][0]; //MOCAPNET_OUTPUT_JOINT_METACARPAL1_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_1_R][1]; //MOCAPNET_OUTPUT_JOINT_METACARPAL1_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_2_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER2_1_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_2_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER2_1_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER2_2_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER2_2_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER2_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER2_3_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER2_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER2_3_R
//---------------------------------------------------------------------------------
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_1_R][0];//MOCAPNET_OUTPUT_JOINT_METACARPAL2_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_1_R][1];
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_2_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER3_1_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_2_R][1];
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER3_2_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_3_R][1];
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER3_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER3_3_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER3_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER3_3_R
//---------------------------------------------------------------------------------
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_1_R][0]; //MOCAPNET_OUTPUT_JOINT_METACARPAL3_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_1_R][1];
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_2_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER4_1_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_2_R][1];
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER4_2_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_3_R][1];
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER4_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER4_3_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER4_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER4_3_R
//---------------------------------------------------------------------------------
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_1_R][0]; //MOCAPNET_OUTPUT_JOINT_METACARPAL4_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_1_R][1];
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_2_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER5_1_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_2_R][1];
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER5_2_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_3_R][1];
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER5_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER5_3_R
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER5_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER5_3_R
//---------------------------------------------------------------------------------
//Dont forget convertRHandSkeletonSerializedToBVHTransform needs to also be updated
//Populate left hand
input.skeletons[0].leftHand.joint2D[COCO_Hand_Wrist].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LHAND][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Wrist].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LHAND][1];
//---------------------------------------------------------------------------------
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LTHUMB][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LTHUMB][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_2_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_2_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_3_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER1_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER1_3_L][1];
//---------------------------------------------------------------------------------
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_1_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_1_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_2_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_2_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_3_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER2_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER2_3_L][1]; //Maybe the end site is prefereable?
//---------------------------------------------------------------------------------
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_1_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_1_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_2_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_2_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_3_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER3_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER3_3_L][1]; //Maybe the end site is prefereable?
//---------------------------------------------------------------------------------
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_1_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_1_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_2_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_2_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_3_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER4_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER4_3_L][1]; //Maybe the end site is prefereable?
//---------------------------------------------------------------------------------
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_1_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_1_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_2_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_2_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_3_L][1];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER5_3_L][0];
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER5_3_L][1]; //Maybe the end site is prefereable?
//---------------------------------------------------------------------------------
//Dont forget convertLHandSkeletonSerializedToBVHTransform needs to also be updated
//Populate face
input.skeletons[0].head.joint2D[OP_Head_REye_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS03_R][0];
input.skeletons[0].head.joint2D[OP_Head_REye_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS03_R][1];
input.skeletons[0].head.joint2D[OP_Head_REye].x = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_R][0];
input.skeletons[0].head.joint2D[OP_Head_REye].y = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_R][1];
input.skeletons[0].head.joint2D[OP_Head_REye_5].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS04_R][0];
input.skeletons[0].head.joint2D[OP_Head_REye_5].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS04_R][1];
//---------------------------------------------------------------------------------
input.skeletons[0].head.joint2D[OP_Head_LEye_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS03_L][0];
input.skeletons[0].head.joint2D[OP_Head_LEye_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS03_L][1];
input.skeletons[0].head.joint2D[OP_Head_LEye].x = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_L][0];
input.skeletons[0].head.joint2D[OP_Head_LEye].y = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_L][1];
input.skeletons[0].head.joint2D[OP_Head_LEye_5].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS04_L][0];
input.skeletons[0].head.joint2D[OP_Head_LEye_5].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS04_L][1];
//---------------------------------------------------------------------------------
input.skeletons[0].head.joint2D[OP_Head_Chin].x = mocapNET2DPointsResult[MOCAPNET_JOINT_SPECIAL04][0];
input.skeletons[0].head.joint2D[OP_Head_Chin].y = mocapNET2DPointsResult[MOCAPNET_JOINT_SPECIAL04][1];
//---------------------------------------------------------------------------------
input.skeletons[0].head.joint2D[OP_Head_InMouth_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS03_R][0];
input.skeletons[0].head.joint2D[OP_Head_InMouth_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS03_R][1];
input.skeletons[0].head.joint2D[OP_Head_InMouth_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS05][0];
input.skeletons[0].head.joint2D[OP_Head_InMouth_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS05][1];
input.skeletons[0].head.joint2D[OP_Head_InMouth_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS03_L][0];
input.skeletons[0].head.joint2D[OP_Head_InMouth_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS03_L][1];
//---------------------------------------------------------------------------------
input.skeletons[0].head.joint2D[OP_Head_InMouth_7].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS07_R][0];
input.skeletons[0].head.joint2D[OP_Head_InMouth_7].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS07_R][1];
input.skeletons[0].head.joint2D[OP_Head_InMouth_6].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS01][0];
input.skeletons[0].head.joint2D[OP_Head_InMouth_6].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS01][1];
input.skeletons[0].head.joint2D[OP_Head_InMouth_5].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS07_L][0];
input.skeletons[0].head.joint2D[OP_Head_InMouth_5].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS07_L][1];
//---------------------------------------------------------------------------------
// Dont forget to update convertFaceSkeletonSerializedToBVHTransform
/*
for (int jID=0; jID<getBVHNumberOfJoints(); jID++)
{
const char * jointName = getBVHJointName(jID);
fprintf(stderr,"%u = %s \n",jID,jointName);
}*/
return convertSkeletons2DDetectedToSkeletonsSerialized(
output,
&input,
frameNumber,
width,
height
);
}
int affineSkeletonRotation(struct skeletonSerialized * input,float degrees)
{
if (degrees==0.0) { return 1; }
//---------------------------------------------------------------------------
float rad = degrees_to_radF(degrees);
//---------------------------------------------------------------------------
unsigned int hipJoint = 1 + BODY25_MidHip; //+1 because the first three parameters are for skeleton ids etc.
float hipX = input->skeletonBody[hipJoint*3+0].value;
float hipY = input->skeletonBody[hipJoint*3+1].value;
char hipVisibility = (input->skeletonBody[hipJoint*3+2].value > 0.0);
if (hipVisibility)
{
if (input!=0)
{
for (unsigned int jID = 0; jID< input->skeletonBodyElements/3; jID++)
{
float x=input->skeletonBody[jID*3+0].value;
float y=input->skeletonBody[jID*3+1].value;
char visibility=(char) (input->skeletonBody[jID*3+2].value > 0.0);
if (visibility)
{
//Subtract HIP from every joint and perform a 2D rotation using the rad variable
float unrotatedX = x-hipX;
//Subtract HIP from every joint and perform a 2D rotation using the rad variable
float unrotatedY = y-hipY;
input->skeletonBody[jID*3+0].value = hipX + (unrotatedX * cosf(rad)) - (unrotatedY * sinf(rad));
input->skeletonBody[jID*3+1].value = hipY + (unrotatedX * sinf(rad)) + (unrotatedY * cosf(rad));
}
}
return 1;
}
}
return 0;
}
float rotationRequiredToMakeSkeletonCloserToTrainingDataset(struct skeletonSerialized * input)
{
//--------------------------------------------------------------------
unsigned int hipJoint = 1 + BODY25_MidHip; //+1 because the first three parameters are for skeleton ids etc.
float hipX = input->skeletonBody[hipJoint*3+0].value;
float hipY = input->skeletonBody[hipJoint*3+1].value;
char hipVisibility = (input->skeletonBody[hipJoint*3+2].value > 0.0);
//--------------------------------------------------------------------
unsigned int neckJoint = 1 + BODY25_Neck; //+1 because the first three parameters are for skeleton ids etc.
float neckX = input->skeletonBody[neckJoint*3+0].value;
float neckY = input->skeletonBody[neckJoint*3+1].value;
char neckVisibility = (input->skeletonBody[neckJoint*3+2].value > 0.0);
//--------------------------------------------------------------------
if ( (hipVisibility) && (neckVisibility) )
{
float alignmentAngle=getAngleToAlignToZero_tools(hipX,hipY,neckX,neckY);
return alignmentAngle;
}
return 0.0;
}
int makeSkeletonUpright(struct skeletonSerialized * input)
{
float angleCorrectionNeededInDegrees = 180 + goFromRadToDegrees * rotationRequiredToMakeSkeletonCloserToTrainingDataset(input);
if (angleCorrectionNeededInDegrees!=180.0)
{
return affineSkeletonRotation(input,angleCorrectionNeededInDegrees);
}
return 0;
}
@@ -0,0 +1,62 @@
#pragma once
/** @file conversions.hpp
* @brief Unfortunately due to the complexity of the problem and the different libraries used there cannot be a single skeleton representation.
* This module handles conversions between std::vector<float> which is used by Tensorflow/NeuralNetwork layer , skeletonSerialized which is used by MocapNET and Skeletons2DDetected which is used by the 2D estimator
* @author Ammar Qammaz (AmmarkoV)
*/
#include <vector>
#include "../mocapnet2.hpp"
#include "../../../JointEstimator2D/jointEstimator2D.hpp"
int appendVectorToFile(const char * filename, std::vector<float> vec);
int initializeAssociationsForSubsetOfSkeleton(
unsigned int * targetIndexIsInitializedFlag,
unsigned int * targetIndexes,
unsigned int targetLength,
const char * * targetLabels,
struct skeletonSerialized * input
);
std::vector<float> deriveMocapNET2InputUsingAssociations(
struct MocapNET2 * mnet,
struct skeletonSerialized * input,
unsigned int * targetIndexIsInitializedFlag,
unsigned int * targetIndexes,
unsigned int targetLength,
const char * * targetLabels,
int verbose
);
int convertSkeletons2DDetectedToSkeletonsSerialized(
struct skeletonSerialized * output,
struct Skeletons2DDetected * input,
unsigned int frameNumber,
unsigned int width,
unsigned int height
);
int convertMocapNET2OutputToSkeletonSerialized(
struct MocapNET2 * mnet ,
struct skeletonSerialized * output ,
std::vector<std::vector<float> > mocapNET2DPointsResult,
unsigned int frameNumber,
unsigned int width,
unsigned int height
);
int affineSkeletonRotation(struct skeletonSerialized * input,float degrees);
float rotationRequiredToMakeSkeletonCloserToTrainingDataset(struct skeletonSerialized * input);
int makeSkeletonUpright(struct skeletonSerialized * input);
@@ -0,0 +1,653 @@
#include <iostream>
#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include "csvRead.hpp"
#include "../../MocapNETLib2/mocapnet2.hpp"
#include "../../MocapNETLib2/IO/jsonMocapNETHelpers.hpp"
#include "../../../../dependencies/InputParser/InputParser_C.h"
#define NORMAL "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
unsigned int getBodyLinesOfCSVFIle(struct CSVFileContext * csv,const char * filename)
{
FILE * fp = fopen(filename,"r");
{
// Extract characters from file and store in character c
unsigned int count=0;
char c;
for (c = getc(fp); c != EOF; c = getc(fp))
if (c == '\n') // Increment count if this character is newline
{
count = count + 1;
}
fclose(fp);
//The first line of a CSV is its header so we don't count this ..
if (count>0)
{
--count;
}
return count;
}
return 0;
}
int openCSVFile(struct CSVFileContext * csv,const char * filename)
{
csv->fp = fopen(filename,"r");
if (csv->fp!=0)
{
csv->lineNumber=0;
csv->numberOfHeaderFields=0;
fprintf(stderr,GREEN "Successfully opened CSV file %s\n" NORMAL,filename);
return 1;
}
fprintf(stderr,RED "Failed to open CSV file %s\n" NORMAL,filename);
return 0;
}
int closeCSVFile(struct CSVFileContext * csv)
{
if (csv==0)
{
fprintf(stderr,RED "Dont need to close empty CSV struct..\n" NORMAL);
return 1;
}
if (csv->fp==0)
{
fprintf(stderr,RED "Dont need to close CSV header that has already been closed..\n" NORMAL);
return 1;
}
if (csv->fp!=0)
{
//TODO FREE STUFF HERE..
int i=0;
for (i=0; i<csv->numberOfHeaderFields; i++)
{
if (csv->field[i].str!=0)
{
free(csv->field[i].str);
csv->field[i].str=0;
}
}
fclose(csv->fp);
}
return 1;
}
int parseCSVHeader(struct CSVFileContext * csv)
{
if (csv==0)
{
fprintf(stderr,RED "Cannot parse empty CSV header..\n" NORMAL);
return 0;
}
if (csv->fp==0)
{
fprintf(stderr,RED "Cannot parse CSV header that hasn't been opened using openCSVFile..\n" NORMAL);
return 0;
}
fprintf(stderr,"Parsing CSV header..\n");
char whereToStoreItems[513]= {0};
char * line = NULL;
size_t len = 0;
ssize_t read;
if (csv->lineNumber==0)
{
read = getline(&line, &len, csv->fp);
if (line!=0)
{
struct InputParserC * ipc = InputParser_Create(8096,4);
InputParser_SetDelimeter(ipc,0,',');
InputParser_SetDelimeter(ipc,1,0);
InputParser_SetDelimeter(ipc,2,10);
InputParser_SetDelimeter(ipc,3,13);
int numberOfArguments = InputParser_SeperateWords(ipc,line,1);
if (numberOfArguments<MAX_CSV_HEADER_FIELDS)
{
int i=0;
for (i=0; i<numberOfArguments; i++)
{
//InputParser_GetWord InputParser_GetLowercaseWord
InputParser_GetLowercaseWord(ipc,i,whereToStoreItems,512);
//fprintf(stderr,"CSV Header element %u => %s\n",i,whereToStoreItems);
csv->field[i].strLength = strlen(whereToStoreItems);
csv->field[i].str = (char*) malloc(sizeof(char) * (csv->field[i].strLength+2));
memcpy(csv->field[i].str,whereToStoreItems,csv->field[i].strLength);
csv->field[i].str[csv->field[i].strLength]=0;
++csv->numberOfHeaderFields;
}
}
else
{
fprintf(stderr,"Too many CSV header arguments (encountered %u, max %u)..\n",numberOfArguments,MAX_CSV_HEADER_FIELDS);
InputParser_Destroy(ipc);
if (line!=0)
{
free(line);
line=0;
}
return 0;
}
InputParser_Destroy(ipc);
csv->lineNumber = csv->lineNumber +1;
if (line!=0)
{
free(line);
line=0;
}
return 1;
}
}
if (line!=0)
{
free(line);
line=0;
}
return 0;
}
int parseNextCSVFloatLine(struct CSVFileContext * csv,struct CSVFloatFileLine * csvLine)
{
if (csv==0)
{
return 0;
}
if (csvLine==0)
{
return 0;
}
char * line = NULL;
size_t len = 0;
ssize_t read;
if (csv->lineNumber==0)
{
if (!parseCSVHeader(csv))
{
fprintf(stderr,RED "Could not read CSV header on first loop\n" NORMAL);
return 0;
}
}
if ((read = getline(&line, &len, csv->fp)) != -1)
{
struct InputParserC * ipc = InputParser_Create(8096,4);
InputParser_SetDelimeter(ipc,0,',');
InputParser_SetDelimeter(ipc,1,0);
InputParser_SetDelimeter(ipc,2,10);
InputParser_SetDelimeter(ipc,3,13);
csvLine->lineNumber=csv->lineNumber;
csvLine->numberOfFields = InputParser_SeperateWords(ipc,line,1);
//fprintf(stderr,"Line %u (%s) has %u arguments \n",csvLine->lineNumber,line,csvLine->numberOfFields );
if ( csvLine->numberOfFields != csv->numberOfHeaderFields )
{
fprintf(stderr,RED "Number of header fields %u does not correspond with number of body elements %u \n" NORMAL,csv->numberOfHeaderFields,csvLine->numberOfFields);
}
for (int i=0; i<csvLine->numberOfFields; i++)
{
csvLine->field[i] = InputParser_GetWordFloat(ipc,i);
//fprintf(stderr,"%s(%u)=%0.2f ",csv->field[i].str,i,csvLine->field[i]);
}
InputParser_Destroy(ipc);
csv->lineNumber = csv->lineNumber+1;
if (line!=0)
{
free(line);
line=0;
}
return 1;
}
if (line!=0)
{
free(line);
line=0;
}
return 0;
}
int parseNextCSVCOCOSkeleton(struct CSVFileContext * csv, struct skeletonSerialized * skel)
{
if (csv==0)
{
return 0;
}
if (skel==0)
{
return 0;
}
char * line = NULL;
size_t len = 0;
ssize_t read;
if (csv->lineNumber==0)
{
if (!parseCSVHeader(csv))
{
fprintf(stderr,RED "Could not read CSV header on first loop\n" NORMAL);
return 0;
}
/*
else
{
fprintf(stderr,"Header of skeleton parsed successfully..\n");
for (unsigned int i=0; i<csv->numberOfHeaderFields; i++)
{
fprintf(stderr,"CSV file header element %u => %s \n",i,csv->field[i].str);
}
}*/
}
if ((read = getline(&line, &len, csv->fp)) != -1)
{
//CSV files are always stored normalized..
skel->width = 1.0;
skel->height = 1.0;
struct InputParserC * ipc = InputParser_Create(8096,4);
InputParser_SetDelimeter(ipc,0,',');
InputParser_SetDelimeter(ipc,1,0);
InputParser_SetDelimeter(ipc,2,10);
InputParser_SetDelimeter(ipc,3,13);
skel->skeletonBodyElements = InputParser_SeperateWords(ipc,line,1);
//fprintf(stderr,"Line %u (%s) has %u arguments \n",csv->lineNumber,line,skel->skeletonBodyElements);
int typeOfData=0,jointID=0;
float value=0.0;
if ( skel->skeletonBodyElements != csv->numberOfHeaderFields )
{
fprintf(stderr,"Number of header fields %u does not correspond with number of body elements %u \n",csv->numberOfHeaderFields,skel->skeletonBodyElements);
}
//Copy references to header ..
skel->skeletonHeaderElements=csv->numberOfHeaderFields;
for (int i=0; i<csv->numberOfHeaderFields; i++)
{
skel->skeletonHeader[i].strLength = csv->field[i].strLength;
skel->skeletonHeader[i].str = csv->field[i].str;
}
for (int i=0; i<skel->skeletonBodyElements; i++)
{
//fprintf(stderr,"CSV Header element %u => %s\n",i,whereToStoreItems);
skel->skeletonBody[i].value = InputParser_GetWordFloat(ipc,i);
//fprintf(stderr,"%s(%u)=%0.2f ",csv->field[i].str,i,skel->skeletonBody[i].value);
}
InputParser_Destroy(ipc);
csv->lineNumber = csv->lineNumber+1;
if (line!=0)
{
free(line);
line=0;
}
return 1;
}
if (line!=0)
{
free(line);
line=0;
}
return 0;
}
int uniformlyScaleSerializedSkeleton(struct skeletonSerialized * skel,float factor)
{
if (skel==0)
{
return 0;
}
for (int i=0; i<skel->skeletonBodyElements; i++)
{
skel->skeletonBody[i].value *= factor;
}
return 1;
}
int scaleSerializedSkeletonX(struct skeletonSerialized * skel,float factorX)
{
if (skel==0)
{
return 0;
}
if (skel->skeletonHeaderElements!=skel->skeletonBodyElements)
{
fprintf(stderr,"scaleSerializedSkeletonX: Inconsistent headers length\n");
return 0;
}
int scaledJoints=0;
for (int i=0; i<skel->skeletonHeaderElements; i++)
{
if
(
( skel->skeletonHeader[i].strLength >4 ) &&
( skel->skeletonHeader[i].str!=0 )
)
{
if (
(skel->skeletonHeader[i].str[0]=='2') &&
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
( (skel->skeletonHeader[i].str[2]=='X') || (skel->skeletonHeader[i].str[2]=='x') ) &&
(skel->skeletonHeader[i].str[3]=='_')
)
{
skel->skeletonBody[i].value *= factorX;
++scaledJoints;
}
}
}
return scaledJoints;
}
int scaleSerializedSkeletonY(struct skeletonSerialized * skel,float factorY)
{
if (skel==0)
{
return 0;
}
if (skel->skeletonHeaderElements!=skel->skeletonBodyElements)
{
fprintf(stderr,"scaleSerializedSkeletonY: Inconsistent headers length\n");
return 0;
}
int scaledJoints=0;
for (int i=0; i<skel->skeletonHeaderElements; i++)
{
if
(
( skel->skeletonHeader[i].strLength >4 ) &&
( skel->skeletonHeader[i].str!=0 )
)
{
if (
(skel->skeletonHeader[i].str[0]=='2') &&
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
( (skel->skeletonHeader[i].str[2]=='Y') || (skel->skeletonHeader[i].str[2]=='y') ) &&
(skel->skeletonHeader[i].str[3]=='_')
)
{
skel->skeletonBody[i].value *= factorY;
++scaledJoints;
}
///else { fprintf(stderr,"`%s` does not match\n",skel->skeletonHeader[i].str); }
}
}
return scaledJoints;
}
int scaleSerializedSkeletonFromCenter(struct skeletonSerialized * skel,float factorX,float factorY)
{
if (skel==0)
{
return 0;
}
// Assuming we have a 2D point cloud with points 0..1,0..1
// This is how we model the framebuffer
// 0,0 __________________________________________________________________________________ 1,0
// | /\ |
// | | 0.5 |
// | | |
// | 0.5 | 0.5 |
// | <----------------------------- * -----------------------------> |
// | | |
// | | |
// | | 0.5 |
// | \/ |
// 0,1------------------------------------------------------------------------------------ 1,1
// The * is the center of the image..
// We want to scale X,Y points based on factorX and factorY
//However the magnitued of the scaling will be linear to the distance from the
//Center of the image , Points 0.5 units away from the center will be scaled fully with the factor
//Points close to the center will be not scaled at all..
if (skel->skeletonHeaderElements!=skel->skeletonBodyElements)
{
fprintf(stderr,"scaleSerializedSkeletonY: Inconsistent headers length\n");
return 0;
}
float value,magnitude,maximumFactor,thisFactorY,relativeY,thisFactorX,relativeX;
int scaledJoints=0;
for (int i=0; i<skel->skeletonHeaderElements; i++)
{
if
(
( skel->skeletonHeader[i].strLength >4 ) &&
( skel->skeletonHeader[i].str!=0 )
)
{
if (
(skel->skeletonHeader[i].str[0]=='2') &&
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
( (skel->skeletonHeader[i].str[2]=='X') || (skel->skeletonHeader[i].str[2]=='x') ) &&
(skel->skeletonHeader[i].str[3]=='_')
)
{
if (factorX!=1.0)
{
value = skel->skeletonBody[i].value;
maximumFactor = factorX-1.0;
magnitude = (float) fabs(value-0.5)/0.5;
thisFactorX = (magnitude * maximumFactor) + 1.0;
relativeX = value - 0.5;
relativeX *= thisFactorX;
skel->skeletonBody[i].value = relativeX + 0.5 ;
++scaledJoints;
}
}
else if (
(skel->skeletonHeader[i].str[0]=='2') &&
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
( (skel->skeletonHeader[i].str[2]=='Y') || (skel->skeletonHeader[i].str[2]=='y') ) &&
(skel->skeletonHeader[i].str[3]=='_')
)
{
if (factorY!=1.0)
{
value = skel->skeletonBody[i].value;
maximumFactor = factorY-1.0;
magnitude = (float) fabs(value-0.5)/0.5;
thisFactorY = ( magnitude * maximumFactor ) + 1.0;
relativeY = value - 0.5;
relativeY *= thisFactorY;
skel->skeletonBody[i].value = relativeY + 0.5 ;
++scaledJoints;
}
}
} //Valid header
} // For each joint
return scaledJoints;
}
#ifdef __GNUC__
# if __GNUC_PREREQ(5,5)
// If gcc_version >= RANDOM support
#include <random> //For generating random samples based on a normal distribution
//This function makes the life of the 3D pose estimator more difficult by adding a configurable level of gaussian noise on the 2D pixels estimated
int perturbSerializedSkeletonUsingGaussianNoise(struct skeletonSerialized * skel,float gaussianNoiseInNormalizedPixelsX,float gaussianNoiseInNormalizedPixelsY)
{
if (skel->skeletonHeaderElements!=skel->skeletonBodyElements)
{
fprintf(stderr,"perturbSerializedSkeletonUsingGaussianNoise: Inconsistent headers length\n");
return 0;
}
std::default_random_engine generator;
std::normal_distribution<float> distributionX(0.0,gaussianNoiseInNormalizedPixelsX);
std::normal_distribution<float> distributionY(0.0,gaussianNoiseInNormalizedPixelsY);
float value,magnitude,maximumFactor,thisFactorY,relativeY,thisFactorX,relativeX;
int perturbedCoordinates=0;
for (int i=0; i<skel->skeletonHeaderElements; i++)
{
if
(
( skel->skeletonHeader[i].strLength >4 ) &&
( skel->skeletonHeader[i].str!=0 )
)
{
if (
(skel->skeletonHeader[i].str[0]=='2') &&
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
( (skel->skeletonHeader[i].str[2]=='X') || (skel->skeletonHeader[i].str[2]=='x') ) &&
(skel->skeletonHeader[i].str[3]=='_')
)
{
if (gaussianNoiseInNormalizedPixelsX>0.0)
{
float perturbation = distributionX(generator);
skel->skeletonBody[i].value += perturbation;
++perturbedCoordinates;
}
}
else if (
(skel->skeletonHeader[i].str[0]=='2') &&
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
( (skel->skeletonHeader[i].str[2]=='Y') || (skel->skeletonHeader[i].str[2]=='y') ) &&
(skel->skeletonHeader[i].str[3]=='_')
)
{
if (gaussianNoiseInNormalizedPixelsY>0.0)
{
float perturbation = distributionY(generator);
skel->skeletonBody[i].value += perturbation;
++perturbedCoordinates;
}
}
} //Valid header
} // For each joint
return perturbedCoordinates;
}
# else
#warning "Your compiler is too old and is missing normal random distributions"
int perturbSerializedSkeletonUsingGaussianNoise(struct skeletonSerialized * skel,float gaussianNoiseInNormalizedPixelsX,float gaussianNoiseInNormalizedPixelsY)
{
fprintf(stderr,RED "\n\n\n\nYour compiler is too old and is missing normal random distributions\n\n\n\n" NORMAL );
return 0;
}
// Else
# endif
#else
int perturbSerializedSkeletonUsingGaussianNoise(struct skeletonSerialized * skel,float gaussianNoiseInNormalizedPixelsX,float gaussianNoiseInNormalizedPixelsY)
{
fprintf(stderr,RED "\n\n\n\nYour compiler is not GCC old and is missing(?) normal random distributions\n\n\n\n" NORMAL );
return 0;
}
// If not gcc
#endif
/*
float rand_FloatRange(float a, float b)
{
return ((b - a) * ((float)rand() / RAND_MAX)) + a;
}*/
std::vector<std::vector<float> > get2DPointsFromSkeleton(struct skeletonSerialized * skel)
{
fprintf(stderr,"get2DPointsFromSkeleton: ");
std::vector<std::vector<float> > finalVector;
if (skel==0)
{
fprintf(stderr,"get2DPointsFromSkeleton: No input\n");
return finalVector;
}
if (skel->skeletonBodyElements!=skel->skeletonHeaderElements)
{
fprintf(stderr,"get2DPointsFromSkeleton: Mismatch of elements of body/header\n");
return finalVector;
}
std::vector<float> points2D;
for (int i=0; i<skel->skeletonBodyElements; i++)
{
if ( strstr(skel->skeletonHeader[i].str,"2DX_")!=0)
{
points2D.push_back(skel->skeletonBody[i].value);
}
else if ( strstr(skel->skeletonHeader[i].str,"2DY_")!=0)
{
points2D.push_back(skel->skeletonBody[i].value);
}
else if ( strstr(skel->skeletonHeader[i].str,"visible_")!=0)
{
finalVector.push_back(points2D);
points2D.clear();
}
}
fprintf(stderr,"survived..\n");
return finalVector;
}
@@ -0,0 +1,91 @@
#pragma once
/** @file csvRead.hpp
* @brief To simplify dataset parsing the very simple CSV ( comma seperated value ) format is used by MocapNET2
* This module facilitates opening,parsing and performing some trivial processing of CSV input files..
* @author Ammar Qammaz (AmmarkoV)
*/
#include <vector>
#include "commonSkeleton.hpp"
#define MAX_CSV_HEADER_FIELDS 1024
/**
* @brief Each CSV file needs a context to be parsed, this contains the file discriptor the current line number, the number of fields in the header as well as header fields
*/
struct CSVFileContext
{
FILE * fp;
unsigned int lineNumber;
unsigned int numberOfHeaderFields;
struct headerField field[MAX_CSV_HEADER_FIELDS];
};
/**
* @brief We may choose to parse a CSV file that only consists of floats, for this specific type there is an optimized CSV context
*/
struct CSVFloatFileLine
{
unsigned int lineNumber;
unsigned int numberOfFields;
float field[MAX_CSV_HEADER_FIELDS];
};
/**
* @brief Write a skeleton to a CSV. This is the first call that prepares the header
* @param CSV context
* @param filename of CSV file
* @retval 0=Failure/No lines, Otherwise the number of body lines is returned
*/
unsigned int getBodyLinesOfCSVFIle(struct CSVFileContext * csv,const char * filename);
/**
* @brief This is the initial call to open a CSV file, you need to have a preallocated CSVFileContext strcture as well as a filename. Also don't forget to call closeCSVFile after you are done parsing it
* @param CSV context
* @param filename of CSV file
* @retval 0=Failure/1=Success
*/
int openCSVFile(struct CSVFileContext * csv,const char * filename);
/**
* @brief This call should be executed once after opening a CSV file to parse it's header
* @param CSV context
* @retval 0=Failure/1=Success
*/
int parseCSVHeader(struct CSVFileContext * csv);
/**
* @brief This is the final call to close a CSV file and release its file descriptor after you are done parsing it
* @param CSV context
* @retval 0=Failure/1=Success
*/
int closeCSVFile(struct CSVFileContext * csv);
int parseNextCSVFloatLine(struct CSVFileContext * csv,struct CSVFloatFileLine * csvLine);
int parseNextCSVCOCOSkeleton(struct CSVFileContext * csv, struct skeletonSerialized * skel);
int uniformlyScaleSerializedSkeleton(struct skeletonSerialized * skel,float factor);
int scaleSerializedSkeletonX(struct skeletonSerialized * skel,float factorX);
int scaleSerializedSkeletonY(struct skeletonSerialized * skel,float factorY);
int scaleSerializedSkeletonFromCenter(struct skeletonSerialized * skel,float factorX,float factorY);
int perturbSerializedSkeletonUsingGaussianNoise(struct skeletonSerialized * skel,float gaussianNoiseInNormalizedPixelsX,float gaussianNoiseInNormalizedPixelsY);
std::vector<std::vector<float> > get2DPointsFromSkeleton(struct skeletonSerialized * skel);
@@ -0,0 +1,251 @@
#include <iostream>
#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include "../mocapnet2.hpp"
#include "../tools.hpp"
#include "csvWrite.hpp"
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
int writeCSVHeaderFromVector(const char * filename,const char ** labels,unsigned int numberOfLabels)
{
FILE * fp = fopen(filename,"w");
if (fp!=0)
{
for (int i=0; i<numberOfLabels; i++)
{
fprintf(fp,"%s",labels[i]);
if (i<numberOfLabels-1)
{
fprintf(fp,",");
}
}
fprintf(fp,"\n");
fclose(fp);
return 1;
}
return 0;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
int writeCSVBodyFromVector(const char * filename,std::vector<float> inputValues)
{
FILE * fp = fopen(filename,"a");
if (fp!=0)
{
if (inputValues.size()==0)
{
fprintf(stderr,"Failed to read from JSON file..\n");
}
for (int i=0; i<inputValues.size(); i++)
{
if (i%3==2)
{
fprintf(fp,"%0.1f",inputValues[i]);
}
else
{
fprintf(fp,"%f",inputValues[i]);
}
if (i<inputValues.size()-1)
{
fprintf(fp,",");
}
}
fprintf(fp,"\n");
fclose(fp);
return 1;
}
return 0;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
int writeCSVHeaderFromLabelsAndVectorOfVectors(const char * filename,const char ** labels,unsigned int numberOfLabels,std::vector<std::vector<float> > inputFrames)
{
int totalWritesNeeded=0;
int totalWritesSucceeded=0;
if ( writeCSVHeaderFromVector(filename,labels,numberOfLabels) )
{
for (int i=0; i<inputFrames.size(); i++)
{
++totalWritesNeeded;
if ( writeCSVBodyFromVector(filename,inputFrames[i]) )
{
++totalWritesSucceeded;
}
}
return (totalWritesSucceeded==totalWritesNeeded);
}
return 0;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
int writeOpenPoseCSVHeaderFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int width,unsigned int height)
{
FILE * fp = fopen(filename,"w");
if (fp!=0)
{
fprintf(fp,"frameNumber,");
fprintf(fp,"skeletonID,");
fprintf(fp,"totalSkeletons,");
char lowercaseName[512];
for (int i=0; i<BODY25_PARTS; i++)
{
convertStringToLowercase(lowercaseName,512,Body25BodyNames[i]);
//----------------------------------
fprintf(fp,"2DX_%s,",lowercaseName);
fprintf(fp,"2DY_%s,",lowercaseName);
fprintf(fp,"visible_%s,",lowercaseName);
}
for (int i=0; i<COCO_HAND_PARTS; i++)
{
convertStringToLowercase(lowercaseName,512,COCOLeftHandNames[i]);
//----------------------------------
fprintf(fp,"2DX_%s,",lowercaseName);
fprintf(fp,"2DY_%s,",lowercaseName);
fprintf(fp,"visible_%s,",lowercaseName);
}
for (int i=0; i<COCO_HAND_PARTS; i++)
{
convertStringToLowercase(lowercaseName,512,COCORightHandNames[i]);
//----------------------------------
fprintf(fp,"2DX_%s,",lowercaseName);
fprintf(fp,"2DY_%s,",lowercaseName);
fprintf(fp,"visible_%s,",lowercaseName);
}
for (int i=0; i<OP_HEAD_PARTS; i++)
{
convertStringToLowercase(lowercaseName,512,HeadNames[i]);
//----------------------------------
fprintf(fp,"2DX_%s,",lowercaseName);
fprintf(fp,"2DY_%s,",lowercaseName);
fprintf(fp,"visible_%s",lowercaseName);
if (i<OP_HEAD_PARTS-1)
{
fprintf(fp,",");
}
}
fprintf(fp,"\n");
fclose(fp);
return 1;
}
return 0;
}
int writeOpenPoseCSVBodyFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int respectTrainingAspectRatio,unsigned int width,unsigned int height)
{
FILE * fp = fopen(filename,"a");
if (fp!=0)
{
fprintf(fp,"%u,",skeleton->observationNumber);
fprintf(fp,"%u,",skeleton->userID);
fprintf(fp,"%u,",skeleton->totalUsersPresent);
for (int i=0; i<BODY25_PARTS; i++)
{
//Normalize targets --------------------------------------------------------------
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
&skeleton->body.joint2D[i].x,
&skeleton->body.joint2D[i].y,
width,
height,
respectTrainingAspectRatio,
MocapNETTrainingWidth,
MocapNETTrainingHeight
);
//--------------------------------------------------------------------------------
fprintf(fp,"%f,",(float) skeleton->body.joint2D[i].x);
fprintf(fp,"%f,",(float) skeleton->body.joint2D[i].y);
fprintf(fp,"%u,", ( (skeleton->body.joint2D[i].x!=0) && (skeleton->body.joint2D[i].y!=0) ) );
}
for (int i=0; i<COCO_HAND_PARTS; i++)
{
//Normalize targets --------------------------------------------------------------
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
&skeleton->leftHand.joint2D[i].x,
&skeleton->leftHand.joint2D[i].y,
width,
height,
respectTrainingAspectRatio,
MocapNETTrainingWidth,
MocapNETTrainingHeight
);
//--------------------------------------------------------------------------------
fprintf(fp,"%f,",(float) skeleton->leftHand.joint2D[i].x);
fprintf(fp,"%f,",(float) skeleton->leftHand.joint2D[i].y);
fprintf(fp,"%u,", ( (skeleton->leftHand.joint2D[i].x!=0) && (skeleton->leftHand.joint2D[i].y!=0) ) );
}
for (int i=0; i<COCO_HAND_PARTS; i++)
{
//Normalize targets --------------------------------------------------------------
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
&skeleton->rightHand.joint2D[i].x,
&skeleton->rightHand.joint2D[i].y,
width,
height,
respectTrainingAspectRatio,
MocapNETTrainingWidth,
MocapNETTrainingHeight
);
//--------------------------------------------------------------------------------
fprintf(fp,"%f,",(float) skeleton->rightHand.joint2D[i].x);
fprintf(fp,"%f,",(float) skeleton->rightHand.joint2D[i].y);
fprintf(fp,"%u,", ( (skeleton->rightHand.joint2D[i].x!=0) && (skeleton->rightHand.joint2D[i].y!=0) ) );
}
for (int i=0; i<OP_HEAD_PARTS; i++)
{
//Normalize targets --------------------------------------------------------------
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
&skeleton->head.joint2D[i].x,
&skeleton->head.joint2D[i].y,
width,
height,
respectTrainingAspectRatio,
MocapNETTrainingWidth,
MocapNETTrainingHeight
);
//--------------------------------------------------------------------------------
fprintf(fp,"%f,",(float) skeleton->head.joint2D[i].x);
fprintf(fp,"%f,",(float) skeleton->head.joint2D[i].y);
fprintf(fp,"%u", ( (skeleton->head.joint2D[i].x!=0) && (skeleton->head.joint2D[i].y!=0) ) );
if (i<OP_HEAD_PARTS-1)
{
fprintf(fp,",");
}
}
fprintf(fp,"\n");
fclose(fp);
return 1;
}
return 0;
}
@@ -0,0 +1,65 @@
#pragma once
/** @file csvWrite.hpp
* @brief These are some simple functions to facilitate CSV writing
* @author Ammar Qammaz (AmmarkoV)
*/
#include "commonSkeleton.hpp"
/**
* @brief Write a skeleton to a CSV. This is the first call that prepares the header
* @param Path to output file i.e. "output.bvh"
* @param Pointer to Skeleton that we want to save
* @param Width of Image where the skeleton was retreieved from
* @param Height of Image where the skeleton was retreieved from
* @retval 1=Success,0=Failure
*/
int writeCSVHeaderFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int width,unsigned int height);
/**
* @brief Write the body of a skeleton to a CSV. Each time this call is repeated an extra line is appended
* @param Path to output file i.e. "output.bvh"
* @param Pointer to Skeleton that we want to save
* @param Width of Image where the skeleton was retreieved from
* @param Height of Image where the skeleton was retreieved from
* @retval 1=Success,0=Failure
*/
int writeCSVBodyFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int width,unsigned int height);
/**
* @brief Write an array of C-Strings
* @param Path to output file i.e. "output.bvh"
* @param Pointer to array of C-Strings i.e. MocapNETInputUncompressedArrayNames
* @param Number of elements of labels array, MOCAPNET_UNCOMPRESSED_JOINT_PARTS*3 in the case of MocapNETInputUncompressedArrayNames
* @retval 1=Success,0=Failure
*/
int writeCSVHeaderFromVector(const char * filename,const char ** labels,unsigned int numberOfLabels);
/**
* @brief Write the body of a skeleton in the form of std::vectors to a CSV. Each time this call is repeated an extra line is appended
* @param Path to output file i.e. "output.bvh"
* @param Pointer to Skeleton that we want to save
* @param Width of Image where the skeleton was retreieved from
* @param Height of Image where the skeleton was retreieved from
* @retval 1=Success,0=Failure
*/
int writeCSVBodyFromVector(const char * filename,std::vector<float> inputValues);
int writeCSVHeaderFromLabelsAndVectorOfVectors(const char * filename,const char ** labels,unsigned int numberOfLabels,std::vector<std::vector<float> > inputFrames);
int writeOpenPoseCSVHeaderFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int width,unsigned int height);
int writeOpenPoseCSVBodyFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int respectTrainingAspectRatio,unsigned int width,unsigned int height);
@@ -0,0 +1,612 @@
#include "jsonMocapNETHelpers.hpp"
#include <stdio.h>
#include <string.h>
#include "../../MocapNETLib2/IO/bvh.hpp"
#define NORMAL "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
int bothZero(float a,float b)
{
return (a==0.0)&&(b==0.0);
}
int jointIsNotZero(struct skeletonStructure * sk,int jointID)
{
if ( bothZero(sk->body.joint2D[jointID].x,sk->body.joint2D[jointID].y) )
{
return 0;
}
return 1;
}
int bothJointAreNotZero(struct skeletonStructure * sk,int jointIDA,int jointIDB)
{
if (
( (sk->body.joint2D[jointIDA].x==0.0)&&(sk->body.joint2D[jointIDA].y==0.0) ) ||
( (sk->body.joint2D[jointIDB].x==0.0)&&(sk->body.joint2D[jointIDB].y==0.0) )
)
{
return 0;
}
return 1;
}
void addSkeletonJointFromTwoJoints(
struct skeletonStructure * sk,
std::vector<float> &result,
int jointIDA,
int jointIDB
)
{
float x=(float) (sk->body.joint2D[jointIDA].x + sk->body.joint2D[jointIDB].x)/2;
float y=(float) (sk->body.joint2D[jointIDA].y + sk->body.joint2D[jointIDB].y)/2;
float v=1.0;
if (
( (sk->body.joint2D[jointIDA].x==0.0)&&(sk->body.joint2D[jointIDA].y==0.0) ) ||
( (sk->body.joint2D[jointIDB].x==0.0)&&(sk->body.joint2D[jointIDB].y==0.0) )
)
{
x=0.0;
y=0.0;
v=0.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
}
void addSkeletonJoint(
struct skeletonStructure * sk,
std::vector<float> &result,
int jointID
)
{
float x=(float) sk->body.joint2D[jointID].x;
float y=(float) sk->body.joint2D[jointID].y;
float v=1.0;
if ( (x==0.0)&&(y==0.0) )
{
v=0.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
}
void addRightFinger(
struct skeletonStructure * sk,
std::vector<float> &result,
int fingerJointA,
int fingerJointB,
int fingerJointC
)
{
float x=(float) sk->rightHand.joint2D[fingerJointA].x;
float y=(float) sk->rightHand.joint2D[fingerJointA].y;
float v=1.0;
if ( (x==0.0)&&(y==0.0) )
{
v=0.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
//----------------------------------------------
x=(float) sk->rightHand.joint2D[fingerJointB].x;
y=(float) sk->rightHand.joint2D[fingerJointB].y;
v=1.0;
if ( (x==0.0)&&(y==0.0) )
{
v=0.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
//----------------------------------------------
x=(float) sk->rightHand.joint2D[fingerJointC].x;
y=(float) sk->rightHand.joint2D[fingerJointC].y;
v=1.0;
if ( (x==0.0)&&(y==0.0) )
{
v=0.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
}
void addLeftFinger(
struct skeletonStructure * sk,
std::vector<float> &result,
int fingerJointA,
int fingerJointB,
int fingerJointC
)
{
float x=(float) sk->leftHand.joint2D[fingerJointA].x;
float y=(float) sk->leftHand.joint2D[fingerJointA].y;
float v=1.0;
if ( (x==0.0)&&(y==0.0) )
{
v=0.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
//----------------------------------------------
x=(float) sk->leftHand.joint2D[fingerJointB].x;
y=(float) sk->leftHand.joint2D[fingerJointB].y;
v=1.0;
if ( (x==0.0)&&(y==0.0) )
{
v=0.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
//----------------------------------------------
x=(float) sk->leftHand.joint2D[fingerJointC].x;
y=(float) sk->leftHand.joint2D[fingerJointC].y;
v=1.0;
if ( (x==0.0)&&(y==0.0) )
{
v=0.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
}
std::vector<float> normalizeWhileAlsoMatchingTrainingAspectRatio(
std::vector<float> input,
unsigned int currentWidth,
unsigned int currentHeight,
unsigned int trainingWidth,
unsigned int trainingHeight
)
{
//fprintf(stderr,YELLOW "normalizeWhileAlsoMatchingTrainingAspectRatio\n" NORMAL);
unsigned int addX=0,addY=0;
unsigned int targetWidth=currentWidth,targetHeight=currentHeight;
float currentAspectRatio = (float) currentWidth/currentHeight;
float trainingAspectRatio = (float) trainingWidth/trainingHeight;
//fprintf(stderr,"Will try to correct aspect ratio from %0.2f(%ux%u) to %0.2f (%ux%u)\n",currentAspectRatio,currentWidth,currentHeight,trainingAspectRatio,trainingWidth,trainingHeight);
std::vector<float> fixedAspectRatio=input;
if (currentHeight<currentWidth)
{
targetHeight=(unsigned int) currentWidth/trainingAspectRatio;
if (targetHeight>=currentHeight)
{
addY=(unsigned int) (targetHeight-currentHeight)/2;
} else
{
//Turns out we will have to enlarge X instead of englarging Y
addY=0;
targetHeight=currentHeight;
targetWidth=(unsigned int)currentHeight*trainingAspectRatio;
addX=(unsigned int) (targetWidth-currentWidth)/2;
}
} else
if (currentWidth<=currentHeight)
{
targetWidth=(unsigned int)currentHeight*trainingAspectRatio;
if (targetWidth>=currentWidth)
{
addX=(unsigned int) (targetWidth-currentWidth)/2;
} else
{
//Turns out we will have to enlarge Y instead of englarging X
addX=0;
targetWidth=currentWidth;
targetHeight=(unsigned int) currentWidth/trainingAspectRatio;
addY=(unsigned int) (targetHeight-currentHeight)/2;
}
}
//fprintf(stderr,"Target resolution is %ux%u to Y\n",targetWidth,targetHeight);
//fprintf(stderr,"Will add %u to X and %u to Y to achieve it\n",addX,addY);
float targetAspectRatio=(float) targetWidth/targetHeight;
if ((unsigned int) targetAspectRatio/100!= (unsigned int) trainingAspectRatio/100)
{
fprintf(stderr,RED "Failed to perfectly match training aspect ratio (%0.5f), managed to reach (%0.5f)\n" NORMAL,trainingAspectRatio,targetAspectRatio);
}
for (int i=0; i<input.size()/3; i++)
{
if (input[i*3+2]!=0)
{
//Only Fix Aspect Ratio on visible points to preserve 0,0,0 that are
//important to the neural network..
fixedAspectRatio[i*3+0]=(float) (input[i*3+0]+addX)/targetWidth;
fixedAspectRatio[i*3+1]=(float) (input[i*3+1]+addY)/targetHeight;
}
}
return fixedAspectRatio;
}
std::vector<float> flattenskeletonStructureToVector(struct skeletonStructure * sk,unsigned int width ,unsigned int height)
{
//Extra joints..
float hipX=0.0;
float hipY=0.0;
int hipExists=0;
float x,y,v;
std::vector<float> result;
// MOCAPNET_UNCOMPRESSED_JOINT_HIP=0, //0
x=(float) (sk->body.joint2D[BODY25_LHip].x + sk->body.joint2D[BODY25_RHip].x)/2;
y=(float) (sk->body.joint2D[BODY25_LHip].y + sk->body.joint2D[BODY25_RHip].y)/2;
if (
( (sk->body.joint2D[BODY25_LHip].x==0.0)&&(sk->body.joint2D[BODY25_LHip].y==0.0) ) ||
( (sk->body.joint2D[BODY25_RHip].x==0.0)&&(sk->body.joint2D[BODY25_RHip].y==0.0) )
)
{
v=0.0;
x=0.0;
y=0.0;
}
else
{
v=1.0;
hipX=x;
hipY=y;
hipExists=1;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
//------------------------------------
float chestX= (float) (sk->body.joint2D[BODY25_Neck].x + hipX)/2;
float chestY= (float) (sk->body.joint2D[BODY25_Neck].y + hipY)/2;
int chestNotVisible= (( (sk->body.joint2D[BODY25_Neck].x==0.0)&&(sk->body.joint2D[BODY25_Neck].y==0.0) ) || ( (hipX==0.0)&&(hipY==0.0) ) );
//MOCAPNET_UNCOMPRESSED_JOINT_ABDOMEN, //1
x=(float) (sk->body.joint2D[BODY25_Neck].x + chestX)/2;
y=(float) (sk->body.joint2D[BODY25_Neck].y + chestY)/2;
if ( (chestNotVisible) || ((sk->body.joint2D[BODY25_Neck].x==0.0)&&(sk->body.joint2D[BODY25_Neck].y==0.0)) )
{
v=0.0;
x=0.0;
y=0.0;
}
else
{
v=1.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
//TODO:
//------------------------------------
//MOCAPNET_UNCOMPRESSED_JOINT_CHEST, //2
x=chestX;
y=chestY;
if ( chestNotVisible )
{
v=0.0;
x=0.0;
y=0.0;
}
else
{
v=1.0;
}
result.push_back(x);
result.push_back(y);
result.push_back(v);
//------------------------------------
//MOCAPNET_UNCOMPRESSED_JOINT_NECK, //3
addSkeletonJoint(sk,result,COCO_Neck);
//------------------------------------
//MOCAPNET_UNCOMPRESSED_JOINT_HEAD, //4
//
int guessNose=1;
if (guessNose==1)
{
//TODO : The nose should only be visible in front
//Eyes the same.. I should also add this to the BVH -> 3D CSV conversions..!
if (bothJointAreNotZero(sk,BODY25_LEar,BODY25_REar))
{
addSkeletonJointFromTwoJoints(sk,result,BODY25_LEar,BODY25_REar);
}
else
if (bothJointAreNotZero(sk,BODY25_LEye,BODY25_REye))
{
addSkeletonJointFromTwoJoints(sk,result,BODY25_LEye,BODY25_REye);
} else
{
addSkeletonJoint(sk,result,BODY25_Nose);
}
}
else
{
addSkeletonJoint(sk,result,BODY25_Nose);
}
//------------------------------------
//MOCAPNET_UNCOMPRESSED_JOINT_LEFTEYE, //5
addSkeletonJoint(sk,result,BODY25_LEye);
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LEFTEYE, //6
addSkeletonJoint(sk,result,BODY25_LEye);
//MOCAPNET_UNCOMPRESSED_JOINT_RIGHTEYE, //7
addSkeletonJoint(sk,result,BODY25_REye);
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RIGHTEYE, //8
addSkeletonJoint(sk,result,BODY25_REye);
//MOCAPNET_UNCOMPRESSED_JOINT_RCOLLAR, //9
addSkeletonJointFromTwoJoints(sk,result,BODY25_Neck,BODY25_RShoulder);
//------------------------------
//MOCAPNET_UNCOMPRESSED_JOINT_RSHOULDER, //10
addSkeletonJoint(sk,result,BODY25_RShoulder);
//MOCAPNET_UNCOMPRESSED_JOINT_RELBOW, //11
addSkeletonJoint(sk,result,BODY25_RElbow);
//MOCAPNET_UNCOMPRESSED_JOINT_RHAND, //12
addSkeletonJoint(sk,result,BODY25_RWrist);
//MOCAPNET_UNCOMPRESSED_JOINT_RTHUMB1, //13
//MOCAPNET_UNCOMPRESSED_JOINT_RTHUMB2, //14
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RTHUMB2, //15
addRightFinger(sk,result,COCO_Hand_Thumb_1,COCO_Hand_Thumb_2,COCO_Hand_Thumb_3);
//MOCAPNET_UNCOMPRESSED_JOINT_RINDEX1, //16
//MOCAPNET_UNCOMPRESSED_JOINT_RINDEX2, //17
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RINDEX2, //18
addRightFinger(sk,result,COCO_Hand_Index_1,COCO_Hand_Index_2,COCO_Hand_Index_3);
//MOCAPNET_UNCOMPRESSED_JOINT_RMID1, //19
//MOCAPNET_UNCOMPRESSED_JOINT_RMID2, //20
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RMID2, //21
addRightFinger(sk,result,COCO_Hand_Middle_1,COCO_Hand_Middle_2,COCO_Hand_Middle_3);
//MOCAPNET_UNCOMPRESSED_JOINT_RRING1, //22
//MOCAPNET_UNCOMPRESSED_JOINT_RRING2, //23
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RRING2, //24
addRightFinger(sk,result,COCO_Hand_Ring_1,COCO_Hand_Ring_2,COCO_Hand_Ring_3);
//MOCAPNET_UNCOMPRESSED_JOINT_RPINKY1, //25
//MOCAPNET_UNCOMPRESSED_JOINT_RPINKY2, //26
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RPINKY2, //27
addRightFinger(sk,result,COCO_Hand_Pinky_1,COCO_Hand_Pinky_2,COCO_Hand_Pinky_3);
//MOCAPNET_UNCOMPRESSED_JOINT_LCOLLAR, //28
addSkeletonJointFromTwoJoints(sk,result,BODY25_Neck,BODY25_LShoulder);
//MOCAPNET_UNCOMPRESSED_JOINT_LSHOULDER, //29
addSkeletonJoint(sk,result,BODY25_LShoulder);
//MOCAPNET_UNCOMPRESSED_JOINT_LELBOW, //30
addSkeletonJoint(sk,result,BODY25_LElbow);
//MOCAPNET_UNCOMPRESSED_JOINT_LHAND, //31
addSkeletonJoint(sk,result,BODY25_LWrist);
//MOCAPNET_UNCOMPRESSED_JOINT_LTHUMB1, //32
//MOCAPNET_UNCOMPRESSED_JOINT_LTHUMB2, //33
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LTHUMB2, //34
addLeftFinger(sk,result,COCO_Hand_Thumb_1,COCO_Hand_Thumb_2,COCO_Hand_Thumb_3);
//MOCAPNET_UNCOMPRESSED_JOINT_LINDEX1, //35
//MOCAPNET_UNCOMPRESSED_JOINT_LINDEX2, //36
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LINDEX2, //37
addLeftFinger(sk,result,COCO_Hand_Index_1,COCO_Hand_Index_2,COCO_Hand_Index_3);
//MOCAPNET_UNCOMPRESSED_JOINT_LMID1, //38
//MOCAPNET_UNCOMPRESSED_JOINT_LMID2, //39
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LMID2, //40
addLeftFinger(sk,result,COCO_Hand_Middle_1,COCO_Hand_Middle_2,COCO_Hand_Middle_3);
//MOCAPNET_UNCOMPRESSED_JOINT_LRING1, //41
//MOCAPNET_UNCOMPRESSED_JOINT_LRING2, //42
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LRING2, //43
addLeftFinger(sk,result,COCO_Hand_Ring_1,COCO_Hand_Ring_2,COCO_Hand_Ring_3);
//MOCAPNET_UNCOMPRESSED_JOINT_LPINKY1, //44
//MOCAPNET_UNCOMPRESSED_JOINT_LPINKY2, //45
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LPINKY2, //46
addLeftFinger(sk,result,COCO_Hand_Pinky_1,COCO_Hand_Pinky_2,COCO_Hand_Pinky_3);
//MOCAPNET_UNCOMPRESSED_JOINT_RBUTTOCK, //47
//MOCAPNET_UNCOMPRESSED_JOINT_RHIP, //48
addSkeletonJoint(sk,result,BODY25_RHip);
addSkeletonJoint(sk,result,BODY25_RHip);
//MOCAPNET_UNCOMPRESSED_JOINT_RKNEE, //49
addSkeletonJoint(sk,result,BODY25_RKnee);
//MOCAPNET_UNCOMPRESSED_JOINT_RFOOT, //50
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RFOOT, //51
addSkeletonJoint(sk,result,BODY25_RAnkle);
addSkeletonJoint(sk,result,BODY25_RAnkle);
//MOCAPNET_UNCOMPRESSED_JOINT_LBUTTOCK, //52
//MOCAPNET_UNCOMPRESSED_JOINT_LHIP, //53
addSkeletonJoint(sk,result,BODY25_LHip);
addSkeletonJoint(sk,result,BODY25_LHip);
//MOCAPNET_UNCOMPRESSED_JOINT_LKNEE, //54
addSkeletonJoint(sk,result,BODY25_LKnee);
//MOCAPNET_UNCOMPRESSED_JOINT_LFOOT, //55
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LFOOT, //56
addSkeletonJoint(sk,result,BODY25_LAnkle);
addSkeletonJoint(sk,result,BODY25_LAnkle);
//Last sanity check..!
//-----------------------------------------------------------
for (int i=0; i<result.size()/3; i++)
{
if (
( ( result[i*3+0]<=0 )&&( result[i*3+1]<=0 ) ) || //Both x,y are zero
( ( result[i*3+0]==0 )||( result[i*3+1]==0 ) ) //Any of x or y are zero to combat a weird bug..
)
{
result[i*3+0]=0;
result[i*3+1]=0;
result[i*3+2]=0;
}
}
//-----------------------------------------------------------
if ( (width==1) && (height==1) )
{
//Input is already normalized, nothing to do here..
//fprintf(stderr,"Input is already normalized\n");
} else
{
//This is the training configuration of MocapNET
unsigned int trainingWidth=1920;
unsigned int trainingHeight=1080;
float currentAspectRatio = (float) width/height;
float trainingAspectRatio = (float) trainingWidth/trainingHeight;
if (currentAspectRatio!=trainingAspectRatio)
{
//fprintf(stderr,"Normalizing WITH aspect ratio change\n");
//MocapNET has been trained on 1920x1080 frames, so all the received coordinates are normalized in the
//0..1 range based on that. This means that the NN learns the X and Y variations. If a joint lies at pixel 500,500
//it will be represented as 500/1920 , 500/1080.
//Now if a user uses another configuration, let's say a vertical (portrait) feed where the resolution is 1080x1920
//the 2D points will get normalized at 500/1080 , 500/1920 and the resulting 2D joint cloud won't work as well
//This is why it is better to change the aspect ratio while normalizing
result = normalizeWhileAlsoMatchingTrainingAspectRatio(result,width,height,trainingWidth,trainingHeight);
} else
{
//If we don't want to correct aspect ratio just go on with normalization..
//fprintf(stderr,"Normalizing without aspect ratio change\n");
for (int i=0; i<result.size()/3; i++)
{
result[i*3+0]=(float) result[i*3+0]/width;
result[i*3+1]=(float) result[i*3+1]/height;
}
}
}
if (result.size()==0)
{
fprintf(stderr,"Could not convert skeleton to vector..\n");
return result;
}
return result;
}
// ./GroundTruthDumper --from dataset/gestures/comeleft.bvh --360 1 --bvh test.bvh
// ./convertBVHToCSV --from test.bvh -o test.csv
// ./MocapNETJSON --from test.csv --visualize
int convertBVHFrameToSkeletonCOCO(struct skeletonStructure * sk,std::vector<float> bvhFrame,unsigned int width ,unsigned int height)
{
std::vector<std::vector<float> > bvhFrame2DOutput = convertBVHFrameTo2DPoints(bvhFrame); //,width,height
const int INVALID_JOINT=6666;
fprintf(stderr,"Converting BVH frame to a SkeletonCOCO assuming a %ux%u frame\n",width,height);
for (unsigned int jointID=0; jointID<bvhFrame2DOutput.size(); jointID++)
{
fprintf(stderr,"Joint %u - %s - %0.2f,%0.2f \n",jointID,getBVHJointName(jointID),bvhFrame2DOutput[jointID][0],bvhFrame2DOutput[jointID][1]);
const char * jointName = getBVHJointName(jointID);
unsigned int jointTargetID = INVALID_JOINT;
if (strcmp("hip",jointName)==0) { jointTargetID=BODY25_MidHip; } else
if (strcmp("neck",jointName)==0) { jointTargetID=BODY25_Neck; } else
if (strcmp("head",jointName)==0) { jointTargetID=BODY25_Nose; } else
if (strcmp("rShldr",jointName)==0) { jointTargetID=BODY25_RShoulder; } else
if (strcmp("rForeArm",jointName)==0) { jointTargetID=BODY25_RElbow; } else
if (strcmp("rHand",jointName)==0) { jointTargetID=BODY25_RWrist; } else
if (strcmp("lShldr",jointName)==0) { jointTargetID=BODY25_LShoulder; } else
if (strcmp("lForeArm",jointName)==0) { jointTargetID=BODY25_LElbow; } else
if (strcmp("lHand",jointName)==0) { jointTargetID=BODY25_LWrist; } else
if (strcmp("rThigh",jointName)==0) { jointTargetID=BODY25_RHip; } else
if (strcmp("rShin",jointName)==0) { jointTargetID=BODY25_RKnee; } else
if (strcmp("rFoot",jointName)==0) { jointTargetID=BODY25_RAnkle; } else
if (strcmp("lThigh",jointName)==0) { jointTargetID=BODY25_LHip; } else
if (strcmp("lShin",jointName)==0) { jointTargetID=BODY25_LKnee; } else
if (strcmp("lFoot",jointName)==0) { jointTargetID=BODY25_LAnkle; } else
if (strcmp("rightEye",jointName)==0) { jointTargetID=BODY25_REye; } else
if (strcmp("leftEye",jointName)==0) { jointTargetID=BODY25_LEye; }
if (jointTargetID!=INVALID_JOINT)
{
sk->body.joint2D[jointTargetID].x=(float) bvhFrame2DOutput[jointID][0];
sk->body.joint2D[jointTargetID].y=(float) bvhFrame2DOutput[jointID][1];
fprintf(stderr,"-> %0.2f,%0.2f \n",sk->body.joint2D[jointTargetID].x,sk->body.joint2D[jointTargetID].y);
}
/*
, //,
, //,
BODY25_Nose, //,
BODY25_Nose, //,
BODY25_REye, //BODY25_REar,
BODY25_LEye, //BODY25_LEar,
BODY25_LHeel, //BODY25_LBigToe,
BODY25_LBigToe, //BODY25_LSmallToe,
BODY25_LAnkle, //BODY25_LHeel,
BODY25_RHeel, //BODY25_RBigToe,
BODY25_RBigToe, //BODY25_RSmallToe,
BODY25_RAnkle, // BODY25_RHeel,
BODY25_Bkg //BODY25_Bkg
*/
}
return 0;
}
@@ -0,0 +1,46 @@
#pragma once
/** @file jsonMocapNETHelpers.hpp
* @brief This file contains helpers to facilitate conversion between different skeleton formats.
* @author Ammar Qammaz (AmmarkoV)
*/
#include "jsonRead.hpp"
#include <vector>
void addSkeletonJointFromTwoJoints(
struct skeletonStructure * sk,
std::vector<float> &result,
int jointIDA,
int jointIDB
);
void addSkeletonJoint(
struct skeletonStructure * sk,
std::vector<float> &result,
int jointID
);
void addRightFinger(
struct skeletonStructure * sk,
std::vector<float> &result,
int fingerJointA,
int fingerJointB,
int fingerJointC
);
void addLeftFinger(
struct skeletonStructure * sk,
std::vector<float> &result,
int fingerJointA,
int fingerJointB,
int fingerJointC
);
std::vector<float> flattenskeletonCOCOToVector(struct skeletonStructure * sk,unsigned int width ,unsigned int height);
int convertBVHFrameToSkeletonCOCO(struct skeletonStructure * sk,std::vector<float> bvhFrame,unsigned int width ,unsigned int height);
@@ -0,0 +1,262 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "jsonRead.hpp"
#include "../../../../dependencies/InputParser/InputParser_C.h"
#define NORMAL "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
float checkSkeletonDistance(struct skeletonStructure * PreviousSkelA,struct skeletonStructure * skelB)
{
float score=0.0f,xSq=0.0f,ySq=0.0f;
for (int i=0; i<COCO_PARTS; i++)
{
if (
(skelB->body.joint2D[i].x==0) &&
(skelB->body.joint2D[i].y==0)
)
{
score+=1000;// Penalize holes..
}
else
{
xSq = PreviousSkelA->body.joint2D[i].x - skelB->body.joint2D[i].x ;
xSq = xSq * xSq;
ySq = PreviousSkelA->body.joint2D[i].y - skelB->body.joint2D[i].y;
ySq = ySq * ySq;
score+=sqrt(xSq+ySq);
}
}
return score;
}
int parseJsonCOCOSkeleton(const char * filename , struct skeletonStructure * skel,float acceptableThreshold,unsigned int frameID)
{
//memset(skel,0,sizeof(struct skeletonStructure));
ssize_t read;
FILE * fp = fopen(filename,"r");
if (fp!=0)
{
fprintf(stderr,"Parsing 2D skeleton from %s \n",filename);
struct InputParserC * ipc = InputParser_Create(2048,3);
InputParser_SetDelimeter(ipc,0,',');
InputParser_SetDelimeter(ipc,1,',');
char * line = NULL;
size_t len = 0;
/*
{"version":1.2,"people":[{"pose_keypoints_2d":[1051.33,389.167,0.90388,1054.25,474.35,0.834839,995.279,477.271,0.840843,977.646,592.078,0.843254,974.836,692.082,0.925783,1119.04,465.536,0.857748,1148.35,574.318,0.82055,1163.13,671.663,0.926104,1065.89,668.604,0.768351,1021.83,668.697,0.789775,998.248,833.448,0.891052,954.023,974.726,0.895817,1104.23,668.623,0.725152,1092.4,833.417,0.892817,1068.87,954.203,0.908514,1042.39,380.222,0.879022,1069.03,380.207,0.905886,1021.77,388.906,0.874647,1092.43,388.924,0.880871,1095.43,1001.27,0.875549,1110.14,995.311,0.873654,1048.35,968.843,0.832852,954.222,1024.87,0.826879,933.585,1021.78,0.818463,951.109,980.601,0.70936],"face_keypoints_2d":[1021.85,379.364,0.312111,1022.56,385.04,0.388846,1022.92,394.265,0.400321,1025.04,404.553,0.559545,1027.88,413.423,0.583821,1031.79,421.938,0.61052,1037.46,429.389,0.609643,1044.2,434.001,0.630441,1051.3,435.775,0.729202,1059.81,435.065,0.657737,1067.97,430.098,0.685271,1074.36,423.003,0.685615,1078.97,415.197,0.731754,1081.81,406.327,0.712712,1082.17,397.103,0.697536,1082.88,388.233,0.6253,1083.94,380.073,0.518587,1022.56,373.332,0.47997,1027.88,370.494,0.637251,1033.91,369.784,0.717338,1041.72,370.139,0.853094,1047.75,372.977,0.90591,1056.27,373.332,0.889469,1062.3,370.494,0.892274,1068.33,370.494,0.831293,1074.36,371.558,0.73095,1078.97,374.751,0.598676,1051.65,380.073,0.765338,1050.94,386.459,0.77752,1050.94,392.491,0.767245,1050.94,398.167,0.696292,1044.56,401.006,0.712432,1047.75,401.715,0.848516,1050.94,403.134,0.929941,1054.85,402.07,0.957662,1058.75,401.36,0.981191,1030.01,378.299,0.420897,1033.91,378.654,0.380504,1037.11,378.654,0.393703,1039.95,379.009,0.464231,1036.75,379.009,0.458442,1033.56,379.009,0.404015,1062.3,381.847,0.749875,1065.49,381.492,0.641693,1069.39,381.137,0.495781,1072.94,381.492,0.501538,1069.75,381.847,0.518428,1065.49,382.202,0.611457,1038.53,408.456,0.72183,1042.78,407.747,0.864191,1048.11,407.392,0.85783,1051.3,408.456,0.80366,1054.85,407.392,0.833569,1060.17,408.456,0.880244,1066.2,410.23,0.902783,1061.94,417.326,0.928561,1056.27,420.519,0.899355,1051.3,420.874,0.923864,1048.11,420.519,0.927453,1042.07,418.035,0.798128,1039.95,409.875,0.841352,1048.11,410.23,0.881547,1051.65,410.23,0.85485,1055.2,410.23,0.805752,1064.43,410.94,0.870964,1055.91,415.907,0.938425,1051.65,416.262,0.891374,1048.11,416.262,0.926013,1034.98,378.654,0.312223,1067.62,381.492,0.513061],"hand_left_keypoints_2d":[1165.94,680.642,0.466609,1156.44,688.082,0.629248,1153.13,701.72,0.761934,1153.13,715.359,0.819062,1151.89,726.518,0.775558,1168.84,711.64,0.671397,1168.84,728.172,0.799059,1163.88,737.264,0.725134,1160.16,742.224,0.736829,1172.97,711.64,0.702249,1171.73,728.172,0.808444,1166.77,738.091,0.642235,1161.4,742.224,0.604293,1173.38,710.813,0.666696,1172.97,724.865,0.61383,1166.77,732.718,0.536511,1163.88,740.157,0.497097,1172.56,708.747,0.597281,1172.14,721.559,0.59746,1167.18,727.345,0.381854,1163.88,729.411,0.33763],"hand_right_keypoints_2d":[976.039,702.5,0.411615,985.84,702.926,0.655772,996.066,713.152,0.692949,1002.03,726.362,0.772721,1009.7,733.605,0.864994,984.561,730.197,0.731554,988.822,745.536,0.812263,990.953,756.615,0.808444,991.805,765.137,0.836125,979.022,737.014,0.686607,982.005,749.798,0.65217,981.579,760.876,0.754628,979.448,767.694,0.727902,976.039,738.719,0.634819,977.317,749.798,0.69985,976.465,758.32,0.664762,975.187,765.137,0.690298,975.187,739.571,0.592209,975.187,748.093,0.492786,975.613,754.059,0.522497,974.761,760.45,0.43477],"pose_keypoints_3d":[],"face_keypoints_3d":[],"hand_left_keypoints_3d":[],"hand_right_keypoints_3d":[]}]}
*/
while ((read = getline(&line, &len, fp)) != -1)
{
skel->observationNumber=frameID;
//We should have the whole output.. since it is one line
char * poseStart=0;
char * poseEnd=0;
//-----------------------------------------------
poseStart=strstr(line,"\"pose_keypoints_2d\":[");
if(poseStart!=0)
{
poseStart=strstr(poseStart,"[")+1;
poseEnd=strstr(poseStart,"]");
}
//-----------------------------------------------
char * handLeftStart=0;
char * handLeftEnd=0;
handLeftStart=strstr(line,"\"hand_left_keypoints_2d\":[");
if (handLeftStart!=0)
{
handLeftStart=strstr(handLeftStart,"[")+1;
handLeftEnd=strstr(handLeftStart,"]");
}
//-----------------------------------------------
char * handRightStart=0;
char * handRightEnd=0;
handRightStart=strstr(line,"\"hand_right_keypoints_2d\":[");
if (handRightStart!=0)
{
handRightStart=strstr(handRightStart,"[")+1;
handRightEnd=strstr(handRightStart,"]");
}
//-----------------------------------------------
char * headStart=0;
char * headEnd=0;
headStart=strstr(line,"\"face_keypoints_2d\":[");
if (headStart!=0)
{
headStart=strstr(headStart,"[")+1;
headEnd=strstr(headStart,"]");
}
//-----------------------------------------------
//Null Terminate strings..
//----------------------------------------------------------------------------------------------------------------
if (poseEnd!=0) { *poseEnd=0; }
if (handLeftEnd!=0) { *handLeftEnd=0; }
if (handRightEnd!=0) { *handRightEnd=0; }
if (headEnd!=0) { *headEnd=0; }
//----------------------------------------------------------------------------------------------------------------
//fprintf(stderr,"RHand : %s\n",handLeftStart);
//fprintf(stderr,"LHand : %s\n",handRightStart);
//fprintf(stderr,"Pose : %s\n",poseStart);
//fprintf(stderr,"Head : %s\n",headStart);
int numberOfJoints;
float value;
//----------------------------------------------------------------------------------------------------------------
if (poseStart!=0)
{
numberOfJoints = InputParser_SeperateWords(ipc,poseStart,1)/3;
if (numberOfJoints>=BODY25_PARTS)
{
fprintf(stderr,RED "The number of joints found in JSON file (%u) is more than our BODY25 internal structure (%u)\n" NORMAL,numberOfJoints,BODY25_PARTS);
} else
{
if (numberOfJoints>0) { skel->body.isPopulated=1; }
for (int poseNum=0; poseNum<numberOfJoints; poseNum++)
{
skel->body.joint2D[poseNum].x = InputParser_GetWordFloat(ipc,poseNum*3+0);
//fprintf(stderr,"Pose%u x ( %u ) = %0.2f\n",poseNum,poseNum*3+0, skel->joint2D[poseNum].x );
skel->body.joint2D[poseNum].y = InputParser_GetWordFloat(ipc,poseNum*3+1);
//fprintf(stderr,"Pose%u y ( %u ) = %0.2f\n",poseNum,poseNum*3+1,skel->joint2D[poseNum].y);
value = InputParser_GetWordFloat(ipc,poseNum*3+2);
if (value>1.0)
{
fprintf(stderr,"Warning : Too large value for accuracy\n");
}
skel->body.jointAccuracy[poseNum] = value;
skel->body.active[poseNum] = (value>acceptableThreshold);
//fprintf(stderr,"Pose%u A ( %u ) = %0.2f\n",poseNum,poseNum*3+2,value);
}
}
}
//----------------------------------------------------------------------------------------------------------------
// Left Hand Parser
//----------------------------------------------------------------------------------------------------------------
if (handLeftStart!=0)
{
numberOfJoints = InputParser_SeperateWords(ipc,handLeftStart,1)/3;
if (numberOfJoints>COCO_HAND_PARTS)
{
fprintf(stderr,RED "The number of left hand joints found in JSON file (%u) is more than our internal structure (%u)\n" NORMAL,numberOfJoints,COCO_HAND_PARTS);
} else
{
skel->leftHand.isRight=0;
skel->leftHand.isLeft=1;
if (numberOfJoints>0) { skel->leftHand.isPopulated=1; }
for (int poseNum=0; poseNum<numberOfJoints; poseNum++)
{
value = InputParser_GetWordFloat(ipc,poseNum*3+0);
skel->leftHand.joint2D[poseNum].x = value;
value = InputParser_GetWordFloat(ipc,poseNum*3+1);
skel->leftHand.joint2D[poseNum].y = value;
value = InputParser_GetWordFloat(ipc,poseNum*3+2);
skel->leftHand.jointAccuracy[poseNum] = value;
skel->leftHand.active[poseNum] = (value>acceptableThreshold);
}
}
}
// Right Hand Parser
//----------------------------------------------------------------------------------------------------------------
if (handRightStart!=0)
{
numberOfJoints = InputParser_SeperateWords(ipc,handRightStart,1)/3;
if (numberOfJoints>COCO_HAND_PARTS)
{
fprintf(stderr,RED "The number of right hand joints found in JSON file (%u) is more than our internal structure (%u)\n" NORMAL,numberOfJoints,COCO_HAND_PARTS);
} else
{
skel->rightHand.isRight=1;
skel->rightHand.isLeft=0;
if (numberOfJoints>0) { skel->rightHand.isPopulated=1; }
for (int poseNum=0; poseNum<numberOfJoints; poseNum++)
{
value = InputParser_GetWordFloat(ipc,poseNum*3+0);
skel->rightHand.joint2D[poseNum].x = value;
value = InputParser_GetWordFloat(ipc,poseNum*3+1);
skel->rightHand.joint2D[poseNum].y = value;
value = InputParser_GetWordFloat(ipc,poseNum*3+2);
skel->rightHand.jointAccuracy[poseNum] = value;
skel->rightHand.active[poseNum] = (value>acceptableThreshold);
}
}
}
//----------------------------------------------------------------------------------------------------------------
// Head Parser
//----------------------------------------------------------------------------------------------------------------
if (headStart!=0)
{
numberOfJoints = InputParser_SeperateWords(ipc,headStart,1)/3;
if (numberOfJoints>OP_HEAD_PARTS)
{
fprintf(stderr,RED "The number of head joints found in JSON file (%u) is more than our internal structure (%u)\n" NORMAL,numberOfJoints,OP_HEAD_PARTS);
} else
{
if (numberOfJoints>0) { skel->head.isPopulated=1; }
for (int poseNum=0; poseNum<numberOfJoints; poseNum++)
{
value = InputParser_GetWordFloat(ipc,poseNum*3+0);
skel->head.joint2D[poseNum].x = value;
value = InputParser_GetWordFloat(ipc,poseNum*3+1);
skel->head.joint2D[poseNum].y = value;
value = InputParser_GetWordFloat(ipc,poseNum*3+2);
skel->head.jointAccuracy[poseNum] = value;
skel->head.active[poseNum] = (value>acceptableThreshold);
}
}
}
//----------------------------------------------------------------------------------------------------------------
}
InputParser_Destroy(ipc);
fclose(fp);
return 1;
}
else
{
fprintf(stderr,"Could not open 2D skeleton file %s \n",filename);
return 0;
}
fprintf(stderr,"Could not find COCO 2D skeleton in %s \n",filename);
return 0;
}
@@ -0,0 +1,19 @@
#pragma once
/** @file jsonCocoSkeleton.hpp
* @brief This is the code needed to parse an OpenPose JSON file to our struct skeletonStructure. This JSON parser barely works for the specific JSON output and so should be treated with caution.
* It is not comformant to the JSON spec nor will it work for an arbitrary JSON file..!
* @author Ammar Qammaz (AmmarkoV)
*/
#include <stdio.h>
#include "commonSkeleton.hpp"
/**
* @brief Parse a JSON file and retrieve a skeleton
* @param Path to JSON file
* @param Pointer to a struct skeletonStructure that will hold the information loaded
* @param Threshold to set a joint to active ( 0.4-0.5 is a good value )
* @retval 1=Success/0=Failure
*/
int parseJsonCOCOSkeleton(const char * filename , struct skeletonStructure * skel,float acceptableThreshold,unsigned int frameID);
@@ -0,0 +1,107 @@
#include "skeletonAbstraction.hpp"
#include "csvRead.hpp"
#include <iostream>
#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#define NORMAL "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#include <ctype.h> //toupper
int strcasecmp_sk(const char * input1,const char * input2)
{
#if CASE_SENSITIVE_OBJECT_NAMES
return strcmp(input1,input2);
#endif
if ( (input1==0) || (input2==0) )
{
fprintf(stderr,"Error , calling strcasecmp_internal with null parameters \n");
return 1;
}
unsigned int len1 = strlen(input1);
unsigned int len2 = strlen(input2);
if (len1!=len2)
{
//mismatched lengths of strings , they can't be equal..!
return 1;
}
char A; //<- character buffer for input1
char B; //<- character buffer for input2
unsigned int i=0;
while (i<len1) //len1 and len2 are equal
{
A = toupper(input1[i]);
B = toupper(input2[i]);
if (A!=B) { return 1; }
++i;
}
//if we reached this point , there where no reasons
//why input1 and input2 could not be equal..
return 0;
}
int areFeetMissing(struct skeletonSerialized * skel)
{
unsigned int activeLegJoints=0;
for (unsigned int i=0; i<skel->skeletonBodyElements; i++)
{
//If the specific label exists in our skeletonSerialized
if (skel->skeletonHeader[i].str!=0)
{
//The strcmp was flipped, thx to yangjituan for noticing this https://github.com/FORTH-ModelBasedTracker/MocapNET/issues/57
//This is a pretty inefficient function, at some point I need to restructure the skeletonSerialized structure to an enum like
//https://github.com/FORTH-ModelBasedTracker/MocapNET/blob/master/src/MocapNET2/MocapNETLib2/mocapnet2.hpp#L839
//it would just be 4 floating point checks instead of this loop going through labels etc.
//If we are at the correct skeletonSerialized label for the particular r/l foot or knee and check its value and it is non-zero
//we can count it as present in the list of activeLegJoints count the number of active joints..
if ( (strcasecmp_sk(skel->skeletonHeader[i].str,"visible_rfoot")==0) && (skel->skeletonBody[i].value) ) { ++activeLegJoints; } else
if ( (strcasecmp_sk(skel->skeletonHeader[i].str,"visible_rknee")==0) && (skel->skeletonBody[i].value) ) { ++activeLegJoints; } else
if ( (strcasecmp_sk(skel->skeletonHeader[i].str,"visible_lfoot")==0) && (skel->skeletonBody[i].value) ) { ++activeLegJoints; } else
if ( (strcasecmp_sk(skel->skeletonHeader[i].str,"visible_lknee")==0) && (skel->skeletonBody[i].value) ) { ++activeLegJoints; }
}
}
if (activeLegJoints<3)
{
fprintf(stderr,YELLOW "Feet are missing, Only %u leg joints detected..\n" NORMAL,activeLegJoints);
return 1;
}
return 0;
}
int isLeftHardExtended(std::vector<float> result)
{
//TODO:
return 0;
}
int isRightHardExtended(std::vector<float> result)
{
//TODO:
return 0;
}
int getPointOrientation(std::vector<float> result,float *x, float *y,float *r)
{
//TODO:
return 0;
}
@@ -0,0 +1,16 @@
#pragma once
#include "commonSkeleton.hpp"
#include <vector>
int areFeetMissing(struct skeletonSerialized * skel);
int isLeftHardExtended(std::vector<float> result);
int isRightHardExtended(std::vector<float> result);
int getPointOrientation(std::vector<float> result,float *x, float *y,float *r);