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
@@ -0,0 +1,24 @@
project( MocapNET4Test )
cmake_minimum_required( VERSION 2.8.7 )
#cmake_minimum_required(VERSION 3.5)
find_package(OpenCV REQUIRED)
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
#set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 11)
include_directories(${TENSORFLOW_INCLUDE_ROOT})
include_directories(../MocapNETLib4) #<- includes in test.cpp
add_executable(MocapNET4Test test.cpp)
target_link_libraries(MocapNET4Test rt dl m ${OpenCV_LIBRARIES} ${OPENGL_LIBS} JointEstimator2D Tensorflow TensorflowFramework MocapNETLib4 ${NETWORK_CLIENT_LIBRARIES} ${PNG_Libs} ${JPG_Libs} )
set_target_properties(MocapNET4Test PROPERTIES DEBUG_POSTFIX "D")
set_target_properties(MocapNET4Test PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
)
@@ -0,0 +1,122 @@
/** @file livedemo.cpp
* @brief This is the main "demo" offered in this repository, it will take a stream from a webcam or video file using OpenCV and run
* 2D pose estimation + MocapNET giving you a nice 3D visualization as well as an output .bvh file
* @author Ammar Qammaz (AmmarkoV)
*/
#include <stdio.h>
#include <unistd.h>
//-----------------------------------------------------------------
#include "PCA/PCA.h"
#include "JSON/readModelConfiguration.h"
#include "JSON/readListFile.h"
#include "NSxM/NSxM.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 */
void testPCA(struct PCAData * pca)
{
float output[210]={0};
int outputSize = 210;
float input[458]={0};
int inputSize = 458;
for (int i=0; i<inputSize; i++)
{
input[i]=1.0;
}
doPCATransform(output,&outputSize,pca,input,inputSize,210);
for (int i=0; i<outputSize; i++)
{
fprintf(stderr,"%u = %f \n",i,output[i]);
}
}
int main(int argc, char *argv[])
{
//struct MocapNET2Options options= {0};
//struct MocapNET4 mnet={0};
struct PCAData pcaUpperBody={0};
loadPCADataFromJSON(&pcaUpperBody,"dataset/combinedModel/mocapnet4/mode1/1.0/step1_upperbody_all/upperbody_all.pca");
// the camera will be deinitialized automatically in VideoCapture destructor
struct ModelConfigurationData modelConfigurationUpperBody={0};
loadModelConfigurationData(&modelConfigurationUpperBody,"dataset/combinedModel/mocapnet4/mode1/1.0/step1_upperbody_all/upperbody_configuration.json");
printModelConfigurationData(&modelConfigurationUpperBody);
printf("Now will load I/O lists..\n");
struct listFileData neuralNetworkInputsUpperBody = {0};
struct listFileData neuralNetworkOutputsUpperBody = {0};
struct listFileData neuralNetworkJointsUpperBody = {0};
//----------------------------------------------------------------------------------------------------------------------------
readListFile(&neuralNetworkInputsUpperBody,"dataset/combinedModel/mocapnet4/mode1/1.0/step1_upperbody_all/neuralNetworkInputs.list");
printListFile(&neuralNetworkInputsUpperBody,"neuralNetworkInputs");
//----------------------------------------------------------------------------------------------------------------------------
readListFile(&neuralNetworkOutputsUpperBody,"dataset/combinedModel/mocapnet4/mode1/1.0/step1_upperbody_all/neuralNetworkOutputs.list");
printListFile(&neuralNetworkOutputsUpperBody,"neuralNetworkOutputs");
//----------------------------------------------------------------------------------------------------------------------------
readListFile(&neuralNetworkJointsUpperBody,"dataset/combinedModel/mocapnet4/mode1/1.0/step1_upperbody_all/neuralNetworkJoints.list");
printListFile(&neuralNetworkJointsUpperBody,"neuralNetworkJoints");
//----------------------------------------------------------------------------------------------------------------------------
unsigned int data2DLength = 25 * 3; //BODY25 * (x,y,vis)
float * data2D = (float*) malloc(sizeof(float) * data2DLength);
//---------------------------------------------------------------
for (int i=0; i<25; i++)
{
data2D[i*3 + 0 ] = 0.1 * i;
data2D[i*3 + 1 ] = 0.1 * i;
data2D[i*3 + 2 ] = 1.0;
}
struct inputRouting routeUpperBody={0};
//---------------------------------------------------------------
generateRouteFromLabels(
&modelConfigurationUpperBody,
&routeUpperBody,
Body25Labels,
25
);
struct descriptor upperBodyNSRM={0};
//---------------------------------------------------------------
if (data2D!=0)
{
createDescriptor(
&upperBodyNSRM,
data2D,
data2DLength,
&routeUpperBody,
&modelConfigurationUpperBody,
&pcaUpperBody,
&neuralNetworkJointsUpperBody,
&neuralNetworkOutputsUpperBody
);
fprintf(stderr,"\nGenerated UpperBody Descriptor : \n");
for (int i=0; i<upperBodyNSRM.numberOfElements; i++)
{
fprintf(stderr,"%u = %f \n",i,upperBodyNSRM.values[i]);
}
}
return 0;
}
@@ -0,0 +1,48 @@
project( MocapNETLib4 )
cmake_minimum_required(VERSION 3.5)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
#Unfortunately needed for tf_utils.cpp
set(CMAKE_CXX_STANDARD 11)
include_directories(${TENSORFLOW_INCLUDE_ROOT})
#add_executable(MocapNETLib mocapnet.cpp ${CMAKE_SOURCE_DIR}/src/Tensorflow/tf_utils.cpp)
add_library(MocapNETLib4 SHARED
${BVH_SOURCE}
${OPENGL_SOURCE}
../MocapNETLib4/config.h
../MocapNETLib4/tools.h
../MocapNETLib4/PCA/PCA.h
../MocapNETLib4/NSxM/NSxM.h
../MocapNETLib4/NSxM/NSDM.h
../MocapNETLib4/NSxM/NSRM.h
../MocapNETLib4/NSxM/EDM.h
../MocapNETLib4/NSxM/calculations.h
../MocapNETLib4/NSxM/calculations.c
../MocapNETLib4/IO/inputRouting.h
../MocapNETLib4/JSON/readModelConfiguration.h
../MocapNETLib4/JSON/readListFile.h
../MocapNETLib4/mocapnet4.cpp
../MocapNETLib4/mocapnet4.h
${CMAKE_SOURCE_DIR}/dependencies/nxjson/nxjson.h
${CMAKE_SOURCE_DIR}/dependencies/nxjson/nxjson.c
${CMAKE_SOURCE_DIR}/dependencies/InputParser/InputParser_C.cpp
#Tensorflow stuff..
${TENSORFLOW_SOURCE_FILES}
)
target_link_libraries(MocapNETLib4 rt dl m pthread ${OpenCV_LIBRARIES} ${OPENGL_LIBS} Tensorflow TensorflowFramework ${NETWORK_CLIENT_LIBRARIES} ${PNG_Libs} ${JPG_Libs} )
set_target_properties(MocapNETLib4 PROPERTIES DEBUG_POSTFIX "D")
set_target_properties(MocapNETLib4 PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
)
@@ -0,0 +1,259 @@
/** @file inputRouting.h
* @brief An implementation of input routing for the input joints
* @author Ammar Qammaz (AmmarkoV)
*/
#ifndef INPUT_ROUTING_H_INCLUDED
#define INPUT_ROUTING_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
#include "../JSON/readModelConfiguration.h"
#include "../NSxM/NSxM.h"
#include <math.h>
/**
* @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 * Body25Labels[] =
{
"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",
0
};
#include <ctype.h> //toupper
static int strcasecmp_route(const char * input1,const char * input2)
{
if ( (input1==0) || (input2==0) )
{
fprintf(stderr,"Error , calling strcasecmp_route with null parameters \n");
return 1;
}
#if CASE_SENSITIVE_OBJECT_NAMES
return strcmp(input1,input2);
#endif
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;
}
struct inputRouting
{
char resolved;
float * routedValues;
int * routingRules;
int numberOfRoutingRules;
};
static int destroyRoute(struct inputRouting * route)
{
if (route==0) { return 0; }
if (route->routedValues!=0) { free(route->routedValues); route->routedValues=0; }
if (route->routingRules!=0) { free(route->routingRules); route->routingRules=0; }
route->numberOfRoutingRules=0;
route->resolved=0;
return 1;
}
/**
* @brief generate Route from Labels
* @param Pointer to a model configuration
* @param Pointer to the route structure
* @param Labels to route
* @param Number of Labels to route
* @retval 1=Success/0=Failure
*/
static int generateRouteFromLabels(
struct ModelConfigurationData * config,
struct inputRouting * route,
const char * * incomingLabels,
unsigned int incomingLabelsLength
)
{
fprintf(stderr,GREEN "\ngenerateRouteFromLabels for %u labels and %u hierarchy elements\n" NORMAL,incomingLabelsLength,config->numberOfHierarchyElements);
if (config==0) { return 0; }
if (incomingLabels==0) { return 0; }
if (route==0) { return 0; }
destroyRoute(route);
route->numberOfRoutingRules = config->numberOfHierarchyElements;
route->routedValues = (float*) malloc(sizeof(float) * 3 * route->numberOfRoutingRules);
route->routingRules = (int*) malloc(sizeof(int) * route->numberOfRoutingRules);
if (
(route->routedValues==0) ||
(route->routingRules==0)
) //Failed allocating memory..
{
destroyRoute(route);
return 0;
}
memset(route->routedValues,0,sizeof(float) * 3 * route->numberOfRoutingRules);
memset(route->routingRules,0,sizeof(int) * route->numberOfRoutingRules);
int routingFailures = 0;
for (int trg=0; trg<config->numberOfHierarchyElements; trg++)
{
//fprintf(stderr,"trg %u/%u\n",trg,config->numberOfHierarchyElements);
int trgJointResolved = 0;
for (int src=0; src<incomingLabelsLength; src++)
{
//fprintf(stderr,"src %u/%u\n",src,incomingLabelsLength);
if (strcasecmp_route(incomingLabels[src],config->hierarchyElements[trg].joint)==0)
{
fprintf(stderr,GREEN "MATCH %s (%u) to %s (%u) \n" NORMAL,incomingLabels[src],src,config->hierarchyElements[trg].joint,trg);
trgJointResolved = 1;
route->routedValues[trg*3+0] = 0.0;//Set everything to zero initially..
route->routedValues[trg*3+1] = 0.0;//Set everything to zero initially..
route->routedValues[trg*3+2] = 0.0;//Set everything to zero initially..
route->routingRules[trg] = src;
}
}
if (!trgJointResolved)
{
fprintf(stderr,YELLOW "Could not match %s \n" NORMAL,config->hierarchyElements[trg].joint);
routingFailures+=1;
}
}
if (routingFailures==0)
{
fprintf(stderr,GREEN "Successfully routed all %u input rules\n" NORMAL,route->numberOfRoutingRules);
} else
{
fprintf(stderr,RED "Failed routing %u out of %u input rules\n" NORMAL, routingFailures,route->numberOfRoutingRules);
}
route->resolved = (routingFailures==0);
return (routingFailures==0);
}
static int routeInput(
float * preexistingOutput2DJoints,
int * output2DJointsLength,
struct ModelConfigurationData * config,
struct inputRouting * route,
float * raw2DPoints,
int raw2DPointsLength
)
{
if (route->resolved)
{
//if (raw2DPointsLength==route->numberOfRoutingRules)
{
float * output = preexistingOutput2DJoints;
int val = 0;
for (int i=0; i<route->numberOfRoutingRules; i++)
{
fprintf(stderr,"%s ",config->hierarchyElements[i].joint);
//Each rule has 3 values 2DX, 2DY, 2DVisibility
//--------------------------------------------------------------------------
output[val]=raw2DPoints[(route->routingRules[i]*3) + 0];
fprintf(stderr,"2DX=%0.2f ",output[val]);
val+=1;
//--------------------------------------------------------------------------
output[val]=raw2DPoints[(route->routingRules[i]*3) + 1];
fprintf(stderr,"2DY=%0.2f ",output[val]);
val+=1;
//--------------------------------------------------------------------------
output[val]=raw2DPoints[(route->routingRules[i]*3) + 2];
fprintf(stderr,"2DVisibility=%0.2f \n",output[val]);
val+=1;
//--------------------------------------------------------------------------
}
return 1;
}
}
return 0;
}
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,389 @@
/*
* Copyright (c) 2013 Yaroslav Stavnichiy <yarosla@gmail.com>
*
* This file is part of NXJSON.
*
* NXJSON is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* NXJSON is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with NXJSON. If not, see <http://www.gnu.org/licenses/>.
*/
// this file can be #included in your code
#ifndef NXJSON_C
#define NXJSON_C
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include "nxjson.h"
// redefine NX_JSON_CALLOC & NX_JSON_FREE to use custom allocator
#ifndef NX_JSON_CALLOC
#define NX_JSON_CALLOC() calloc(1, sizeof(nx_json))
#define NX_JSON_FREE(json) free((void*)(json))
#endif
// redefine NX_JSON_REPORT_ERROR to use custom error reporting
#ifndef NX_JSON_REPORT_ERROR
#define NX_JSON_REPORT_ERROR(msg, p) fprintf(stderr, "NXJSON PARSE ERROR (%d): " msg " at %s\n", __LINE__, p)
#endif
#define IS_WHITESPACE(c) ((unsigned char)(c)<=(unsigned char)' ')
static const nx_json dummy={ NX_JSON_NULL };
static nx_json* create_json(nx_json_type type, const char* key, nx_json* parent) {
nx_json* js=NX_JSON_CALLOC();
assert(js);
js->type=type;
js->key=key;
if (!parent->last_child) {
parent->child=parent->last_child=js;
}
else {
parent->last_child->next=js;
parent->last_child=js;
}
parent->length++;
return js;
}
void nx_json_free(const nx_json* js) {
nx_json* p=js->child;
nx_json* p1;
while (p) {
p1=p->next;
nx_json_free(p);
p=p1;
}
NX_JSON_FREE(js);
}
static int unicode_to_utf8(unsigned int codepoint, char* p, char** endp) {
// code from http://stackoverflow.com/a/4609989/697313
if (codepoint<0x80) *p++=codepoint;
else if (codepoint<0x800) *p++=192+codepoint/64, *p++=128+codepoint%64;
else if (codepoint-0xd800u<0x800) return 0; // surrogate must have been treated earlier
else if (codepoint<0x10000) *p++=224+codepoint/4096, *p++=128+codepoint/64%64, *p++=128+codepoint%64;
else if (codepoint<0x110000) *p++=240+codepoint/262144, *p++=128+codepoint/4096%64, *p++=128+codepoint/64%64, *p++=128+codepoint%64;
else return 0; // error
*endp=p;
return 1;
}
nx_json_unicode_encoder nx_json_unicode_to_utf8=unicode_to_utf8;
static inline int hex_val(char c) {
if (c>='0' && c<='9') return c-'0';
if (c>='a' && c<='f') return c-'a'+10;
if (c>='A' && c<='F') return c-'A'+10;
return -1;
}
static char* unescape_string(char* s, char** end, nx_json_unicode_encoder encoder) {
char* p=s;
char* d=s;
char c;
while ((c=*p++)) {
if (c=='"') {
*d='\0';
*end=p;
return s;
}
else if (c=='\\') {
switch (*p) {
case '\\':
case '/':
case '"':
*d++=*p++;
break;
case 'b':
*d++='\b'; p++;
break;
case 'f':
*d++='\f'; p++;
break;
case 'n':
*d++='\n'; p++;
break;
case 'r':
*d++='\r'; p++;
break;
case 't':
*d++='\t'; p++;
break;
case 'u': // unicode
if (!encoder) {
// leave untouched
*d++=c;
break;
}
char* ps=p-1;
int h1, h2, h3, h4;
if ((h1=hex_val(p[1]))<0 || (h2=hex_val(p[2]))<0 || (h3=hex_val(p[3]))<0 || (h4=hex_val(p[4]))<0) {
NX_JSON_REPORT_ERROR("invalid unicode escape", p-1);
return 0;
}
unsigned int codepoint=h1<<12|h2<<8|h3<<4|h4;
if ((codepoint & 0xfc00)==0xd800) { // high surrogate; need one more unicode to succeed
p+=6;
if (p[-1]!='\\' || *p!='u' || (h1=hex_val(p[1]))<0 || (h2=hex_val(p[2]))<0 || (h3=hex_val(p[3]))<0 || (h4=hex_val(p[4]))<0) {
NX_JSON_REPORT_ERROR("invalid unicode surrogate", ps);
return 0;
}
unsigned int codepoint2=h1<<12|h2<<8|h3<<4|h4;
if ((codepoint2 & 0xfc00)!=0xdc00) {
NX_JSON_REPORT_ERROR("invalid unicode surrogate", ps);
return 0;
}
codepoint=0x10000+((codepoint-0xd800)<<10)+(codepoint2-0xdc00);
}
if (!encoder(codepoint, d, &d)) {
NX_JSON_REPORT_ERROR("invalid codepoint", ps);
return 0;
}
p+=5;
break;
default:
// leave untouched
*d++=c;
break;
}
}
else {
*d++=c;
}
}
NX_JSON_REPORT_ERROR("no closing quote for string", s);
return 0;
}
static char* skip_block_comment(char* p) {
// assume p[-2]=='/' && p[-1]=='*'
char* ps=p-2;
if (!*p) {
NX_JSON_REPORT_ERROR("endless comment", ps);
return 0;
}
REPEAT:
p=strchr(p+1, '/');
if (!p) {
NX_JSON_REPORT_ERROR("endless comment", ps);
return 0;
}
if (p[-1]!='*') goto REPEAT;
return p+1;
}
static char* parse_key(const char** key, char* p, nx_json_unicode_encoder encoder) {
// on '}' return with *p=='}'
char c;
while ((c=*p++)) {
if (c=='"') {
*key=unescape_string(p, &p, encoder);
if (!*key) return 0; // propagate error
while (*p && IS_WHITESPACE(*p)) p++;
if (*p==':') return p+1;
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0;
}
else if (IS_WHITESPACE(c) || c==',') {
// continue
}
else if (c=='}') {
return p-1;
}
else if (c=='/') {
if (*p=='/') { // line comment
char* ps=p-1;
p=strchr(p+1, '\n');
if (!p) {
NX_JSON_REPORT_ERROR("endless comment", ps);
return 0; // error
}
p++;
}
else if (*p=='*') { // block comment
p=skip_block_comment(p+1);
if (!p) return 0;
}
else {
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
return 0; // error
}
}
else {
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
return 0; // error
}
}
NX_JSON_REPORT_ERROR("unexpected chars", p-1);
return 0; // error
}
static char* parse_value(nx_json* parent, const char* key, char* p, nx_json_unicode_encoder encoder) {
nx_json* js;
while (1) {
switch (*p) {
case '\0':
NX_JSON_REPORT_ERROR("unexpected end of text", p);
return 0; // error
case ' ': case '\t': case '\n': case '\r':
case ',':
// skip
p++;
break;
case '{':
js=create_json(NX_JSON_OBJECT, key, parent);
p++;
while (1) {
const char* new_key;
p=parse_key(&new_key, p, encoder);
if (!p) return 0; // error
if (*p=='}') return p+1; // end of object
p=parse_value(js, new_key, p, encoder);
if (!p) return 0; // error
}
case '[':
js=create_json(NX_JSON_ARRAY, key, parent);
p++;
while (1) {
p=parse_value(js, 0, p, encoder);
if (!p) return 0; // error
if (*p==']') return p+1; // end of array
}
case ']':
return p;
case '"':
p++;
js=create_json(NX_JSON_STRING, key, parent);
js->text_value=unescape_string(p, &p, encoder);
if (!js->text_value) return 0; // propagate error
return p;
case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
{
js=create_json(NX_JSON_INTEGER, key, parent);
char* pe;
errno = 0;
js->int_value=strtoll(p, &pe, 0);
if (pe==p || errno==ERANGE) {
NX_JSON_REPORT_ERROR("invalid number", p);
return 0; // error
}
if (*pe=='.' || *pe=='e' || *pe=='E') { // double value
js->type=NX_JSON_DOUBLE;
errno = 0;
js->dbl_value=strtod(p, &pe);
if (pe==p || errno==ERANGE) {
NX_JSON_REPORT_ERROR("invalid number", p);
return 0; // error
}
}
else {
js->dbl_value=js->int_value;
}
return pe;
}
case 't':
if (!strncmp(p, "true", 4)) {
js=create_json(NX_JSON_BOOL, key, parent);
js->int_value=1;
return p+4;
}
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
case 'f':
if (!strncmp(p, "false", 5)) {
js=create_json(NX_JSON_BOOL, key, parent);
js->int_value=0;
return p+5;
}
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
case 'n':
if (!strncmp(p, "null", 4)) {
create_json(NX_JSON_NULL, key, parent);
return p+4;
}
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
case '/': // comment
if (p[1]=='/') { // line comment
char* ps=p;
p=strchr(p+2, '\n');
if (!p) {
NX_JSON_REPORT_ERROR("endless comment", ps);
return 0; // error
}
p++;
}
else if (p[1]=='*') { // block comment
p=skip_block_comment(p+2);
if (!p) return 0;
}
else {
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
}
break;
default:
NX_JSON_REPORT_ERROR("unexpected chars", p);
return 0; // error
}
}
}
const nx_json* nx_json_parse_utf8(char* text) {
return nx_json_parse(text, unicode_to_utf8);
}
const nx_json* nx_json_parse(char* text, nx_json_unicode_encoder encoder) {
nx_json js={0};
if (!parse_value(&js, 0, text, encoder)) {
if (js.child) nx_json_free(js.child);
return 0;
}
return js.child;
}
const nx_json* nx_json_get(const nx_json* json, const char* key) {
if (!json || !key) return &dummy; // never return null
nx_json* js;
for (js=json->child; js; js=js->next) {
if (js->key && !strcmp(js->key, key)) return js;
}
return &dummy; // never return null
}
const nx_json* nx_json_item(const nx_json* json, int idx) {
if (!json) return &dummy; // never return null
nx_json* js;
for (js=json->child; js; js=js->next) {
if (!idx--) return js;
}
return &dummy; // never return null
}
#ifdef __cplusplus
}
#endif
#endif /* NXJSON_C */
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2013 Yaroslav Stavnichiy <yarosla@gmail.com>
*
* This file is part of NXJSON.
*
* NXJSON is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* NXJSON is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with NXJSON. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NXJSON_H
#define NXJSON_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum nx_json_type {
NX_JSON_NULL, // this is null value
NX_JSON_OBJECT, // this is an object; properties can be found in child nodes
NX_JSON_ARRAY, // this is an array; items can be found in child nodes
NX_JSON_STRING, // this is a string; value can be found in text_value field
NX_JSON_INTEGER, // this is an integer; value can be found in int_value field
NX_JSON_DOUBLE, // this is a double; value can be found in dbl_value field
NX_JSON_BOOL // this is a boolean; value can be found in int_value field
} nx_json_type;
typedef struct nx_json {
nx_json_type type; // type of json node, see above
const char* key; // key of the property; for object's children only
const char* text_value; // text value of STRING node
long long int_value; // the value of INTEGER or BOOL node
double dbl_value; // the value of DOUBLE node
int length; // number of children of OBJECT or ARRAY
struct nx_json* child; // points to first child
struct nx_json* next; // points to next child
struct nx_json* last_child;
} nx_json;
typedef int (*nx_json_unicode_encoder)(unsigned int codepoint, char* p, char** endp);
extern nx_json_unicode_encoder nx_json_unicode_to_utf8;
const nx_json* nx_json_parse(char* text, nx_json_unicode_encoder encoder);
const nx_json* nx_json_parse_utf8(char* text);
void nx_json_free(const nx_json* js);
const nx_json* nx_json_get(const nx_json* json, const char* key); // get object's property by key
const nx_json* nx_json_item(const nx_json* json, int idx); // get array element by index
#ifdef __cplusplus
}
#endif
#endif /* NXJSON_H */
@@ -0,0 +1,173 @@
/** @file readListFile.h
* @brief An implementation of reading a list from a text file
* @author Ammar Qammaz (AmmarkoV)
*/
#ifndef READ_LIST_FILE_H_INCLUDED
#define READ_LIST_FILE_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <stdlib.h>
struct listFileEntry
{
int strLength;
char * str;
};
struct listFileData
{
unsigned int numberOfEntries;
struct listFileEntry * entry;
};
static int slowLineCounter(const char * filename)
{
char ch;
int linesCount=0;
//open file in read more
FILE * fp=fopen(filename,"r");
if(fp==NULL) {
printf("File \"%s\" does not exist!!!\n",filename);
return -1;
}
//read character by character and check for new line
while((ch=fgetc(fp))!=EOF)
{
if(ch=='\n')
linesCount++;
}
//close the file
fclose(fp);
return linesCount;
}
static int destroyListFile(struct listFileData * listOutput)
{
fprintf(stderr,"destroying List File..! \n");
if (listOutput!=0)
{
if (listOutput->entry!=0)
{
for (int i=0; i<listOutput->numberOfEntries; i++)
{
if (listOutput->entry[i].str!=0)
{
free(listOutput->entry[i].str);
listOutput->entry[i].strLength = 0;
}
}
//------------------------------------------------
free(listOutput->entry);
listOutput->entry=0;
}
}
fprintf(stderr,"destroyed List File..! \n");
return 1;
}
static int printListFile(struct listFileData * listOutput,const char * label)
{
if (listOutput==0) { return 0; }
if (listOutput->entry!=0)
{
printf("Listing %s\n",label);
printf("_______________________\n");
for (int i=0; i<listOutput->numberOfEntries; i++)
{
printf("Line %u === `%s`\n",i,listOutput->entry[i].str);
}
printf("\n\n\n");
return 1;
}
return 0;
}
static int readListFile(struct listFileData * listOutput,const char * filename)
{
if (listOutput==0) { return 0; }
//We now know the number of entries
listOutput->numberOfEntries = slowLineCounter(filename);
if (listOutput!=0)
{
//Clean up everything!
destroyListFile(listOutput);
}
listOutput->entry = (struct listFileEntry *) malloc(sizeof(struct listFileEntry) * listOutput->numberOfEntries );
if (listOutput->entry==0) { return 0; }
char * line = NULL;
size_t len = 0;
ssize_t read = 0;
FILE * fp = fopen(filename, "r");
if (fp == NULL)
{ return 0; }
unsigned int entryNumber = 0;
int i=0;
while ((read=getline(&line, &len, fp)) != -1)
{
int stringLength = strlen(line);
int stringLengthWithoutNull = stringLength-1;
while ( (stringLengthWithoutNull>0) && ( (line[stringLengthWithoutNull]==10) || (line[stringLengthWithoutNull]==13) ) )
{
line[stringLengthWithoutNull]=0;
stringLengthWithoutNull-=1;
stringLength-=1;
}
//fprintf(stderr,"reading line %s (%u)..! \n",line,stringLength);
if (entryNumber<listOutput->numberOfEntries)
{
listOutput->entry[i].str = (char *) malloc(sizeof(char) * (stringLength+2));
if (listOutput->entry[i].str!=0)
{
listOutput->entry[i].strLength = stringLength;
strncpy(listOutput->entry[i].str,line,stringLength);
listOutput->entry[i].str[stringLength]=0; //Null termination
//snprintf(listOutput->entry[i].str,stringLength+1,"%s",line);
}
++entryNumber;
}
i+=1;
}
fclose(fp);
if (line)
{ free(line); }
return 1;
}
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,753 @@
/** @file readModelConfiguration.h
* @brief Parsing the JSON files accompanying models..!
* @author Ammar Qammaz (AmmarkoV)
*/
#ifndef READ_JSON_CONFIGURATION_H_INCLUDED
#define READ_JSON_CONFIGURATION_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <stdlib.h>
#include "nxjson.h"
#include "../tools.h"
#define SMALL_STR 32
#define BIG_STR 128
#define MAX_JOINT_NAME 32
#define MAX_DESCRIPTOR_ELEMENTS 64
#define MAX_HIERARCHY_ELEMENTS 64
#define MAX_BANNED_ELEMENTS 16
//--------------------------------------
struct jointName
{
char joint[MAX_JOINT_NAME];
};
//--------------------------------------
struct jointPair
{
char jointStart[MAX_JOINT_NAME];
unsigned int jointStartID;
char jointEnd[MAX_JOINT_NAME];
unsigned int jointEndID;
};
//--------------------------------------
struct jointDescriptorItem
{
char joint[MAX_JOINT_NAME];
unsigned int jointID;
char isVirtual;
float xOffset;
float yOffset;
char halfwayFromJointAndThis[MAX_JOINT_NAME];
unsigned int secondTargetJointID;
};
//--------------------------------------
struct jointHierarchyItem
{
char joint[MAX_JOINT_NAME];
char inheritNetwork[MAX_JOINT_NAME];
char parent[MAX_JOINT_NAME];
unsigned int parentID;
unsigned int importance;
char immuneToSelfOcclusions;
};
//--------------------------------------
struct ModelConfigurationData
{
float version;
//--------------------------------------
char backend[SMALL_STR];
char precision[SMALL_STR];
char BVH[BIG_STR];
char outputDirectory[BIG_STR];
unsigned int veryHighNumberOfEpochs;
unsigned int highNumberOfEpochs;
unsigned int defaultNumberOfEpochs;
unsigned int defaultBatchSize;
float learningRate;
float minEarlyStoppingDelta;
char activationFunction[SMALL_STR];
float dropoutRate;
float lamda;
char useQuadLoss;
char useSquaredLoss;
unsigned int earlyStoppingPatience;
char rememberWeights;
char rememberConsecutiveWeights;
char useOnlineHardExampleMining;
unsigned int hardMiningEpochs;
unsigned int normalMiningEpochs;
unsigned int groupOutputs;
char ignoreOcclusions;
char NSDMNormalizationMasterSwitch;
char NSDMAlsoUseAlignmentAngles;
unsigned int neuralNetworkDepth;
char EDM;
char eNSRM;
char doPCA[BIG_STR];
unsigned int PCADimensionsKept;
unsigned int padEnsembleInput;
//--------------------------------------
struct jointPair normalizedBasedOn[3];
unsigned int numberOfNormalizedBasedOnRules;
//--------------------------------------
struct jointPair alignment[3];
unsigned int numberOfAlignmentRules;
//--------------------------------------
struct jointDescriptorItem descriptorElements[MAX_DESCRIPTOR_ELEMENTS];
unsigned int numberOfDescriptorElements;
//--------------------------------------
struct jointHierarchyItem hierarchyElements[MAX_HIERARCHY_ELEMENTS];
unsigned int numberOfHierarchyElements;
//--------------------------------------
struct jointName bannedJoints[MAX_BANNED_ELEMENTS];
unsigned int numberOfBannedJoints;
};
static void printModelConfigurationData(struct ModelConfigurationData* out)
{
fprintf(stderr,"Version : %0.2f\n", out->version);
fprintf(stderr,"Backend : %s\n", out->backend);
fprintf(stderr,"Precision : %s\n", out->precision);
fprintf(stderr,"BVH : %s\n", out->BVH);
fprintf(stderr,"outputDirectory : %s\n", out->outputDirectory);
fprintf(stderr,"veryHighNumberOfEpochs : %u\n", out->veryHighNumberOfEpochs);
fprintf(stderr,"highNumberOfEpochs : %u\n", out->highNumberOfEpochs);
fprintf(stderr,"defaultNumberOfEpochs : %u\n", out->defaultNumberOfEpochs);
fprintf(stderr,"defaultBatchSize : %u\n", out->defaultBatchSize);
fprintf(stderr,"learningRate : %f\n", out->learningRate);
fprintf(stderr,"minEarlyStoppingDelta : %f\n", out->minEarlyStoppingDelta);
fprintf(stderr,"activationFunction : %s\n", out->activationFunction);
fprintf(stderr,"dropoutRate : %f\n", out->dropoutRate);
fprintf(stderr,"lamda : %f\n", out->lamda);
fprintf(stderr,"useQuadLoss : %u\n", out->useQuadLoss);
fprintf(stderr,"useSquaredLoss : %u\n", out->useSquaredLoss);
fprintf(stderr,"earlyStoppingPatience : %u\n", out->earlyStoppingPatience);
fprintf(stderr,"rememberWeights : %u\n", out->rememberWeights);
fprintf(stderr,"rememberConsecutiveWeights : %u\n", out->rememberConsecutiveWeights);
fprintf(stderr,"useOnlineHardExampleMining : %u\n", out->useOnlineHardExampleMining);
fprintf(stderr,"hardMiningEpochs : %u\n", out->hardMiningEpochs);
fprintf(stderr,"normalMiningEpochs : %u\n", out->normalMiningEpochs);
fprintf(stderr,"groupOutputs : %u\n", out->groupOutputs);
fprintf(stderr,"ignoreOcclusions : %u\n", out->ignoreOcclusions);
fprintf(stderr,"NSDMNormalizationMasterSwitch : %u\n",out->NSDMNormalizationMasterSwitch);
fprintf(stderr,"NSDMAlsoUseAlignmentAngles : %u\n", out->NSDMAlsoUseAlignmentAngles);
fprintf(stderr,"neuralNetworkDepth : %u\n", out->neuralNetworkDepth);
fprintf(stderr,"EDM : %u\n", out->EDM);
fprintf(stderr,"eNSRM : %u\n", out->eNSRM);
fprintf(stderr,"BVH : %s\n", out->doPCA);
fprintf(stderr,"PCADimensionsKept : %u\n", out->PCADimensionsKept);
fprintf(stderr,"padEnsembleInput : %u\n", out->padEnsembleInput);
fprintf(stderr,"Normalization Rules : %u\n",out->numberOfNormalizedBasedOnRules);
for (int i=0; i<out->numberOfNormalizedBasedOnRules; i++)
{
fprintf(stderr,"Rule %u : \n",i);
fprintf(stderr," jointStart:%s\n" ,out->normalizedBasedOn[i].jointStart);
fprintf(stderr," jointStartID:%u\n",out->normalizedBasedOn[i].jointStartID);
fprintf(stderr," jointEnd:%s\n" ,out->normalizedBasedOn[i].jointEnd);
fprintf(stderr," jointEndID:%u\n" ,out->normalizedBasedOn[i].jointEndID);
}
fprintf(stderr,"Alignment Rules : %u\n",out->numberOfAlignmentRules);
for (int i=0; i<out->numberOfAlignmentRules; i++)
{
fprintf(stderr,"Rule %u : \n",i);
fprintf(stderr," jointStart:%s\n" ,out->alignment[i].jointStart);
fprintf(stderr," jointStartID:%u\n",out->alignment[i].jointStartID);
fprintf(stderr," jointEnd:%s\n" ,out->alignment[i].jointEnd);
fprintf(stderr," jointEndID:%u\n" ,out->alignment[i].jointEndID);
}
fprintf(stderr,"Descriptor Rules : %u\n",out->numberOfDescriptorElements);
for (int i=0; i<out->numberOfDescriptorElements; i++)
{
fprintf(stderr,"Rule %u : \n",i);
fprintf(stderr," joint:%s\n" ,out->descriptorElements[i].joint);
fprintf(stderr," jointID:%u\n" ,out->descriptorElements[i].jointID);
fprintf(stderr," isVirtual:%u\n" ,out->descriptorElements[i].isVirtual);
fprintf(stderr," xOffset:%f\n" ,out->descriptorElements[i].xOffset);
fprintf(stderr," yOffset:%f\n" ,out->descriptorElements[i].yOffset);
fprintf(stderr," halfwayFromJointAndThis:%s\n",out->descriptorElements[i].halfwayFromJointAndThis);
fprintf(stderr," secondTargetJointID:%u\n" ,out->descriptorElements[i].secondTargetJointID);
}
//TODO POPULATE JOINT ID!
fprintf(stderr,"Hierarchy Rules : %u\n",out->numberOfHierarchyElements);
for (int i=0; i<out->numberOfHierarchyElements; i++)
{
fprintf(stderr,"Rule %u : \n",i);
fprintf(stderr," joint:%s\n" ,out->hierarchyElements[i].joint);
fprintf(stderr," inheritNetwork:%s\n" ,out->hierarchyElements[i].inheritNetwork);
fprintf(stderr," parent:%s\n" ,out->hierarchyElements[i].parent);
fprintf(stderr," parentID:%u\n" ,out->hierarchyElements[i].parentID);
fprintf(stderr," importance:%u\n" ,out->hierarchyElements[i].importance);
fprintf(stderr," immuneToSelfOcclusions:%u\n" ,out->hierarchyElements[i].immuneToSelfOcclusions);
}
fprintf(stderr,"Banned Encoders Rules : %u\n",out->numberOfBannedJoints);
for (int i=0; i<out->numberOfBannedJoints; i++)
{
fprintf(stderr,"Rule %u : \n",i);
fprintf(stderr," joint:%s\n" ,out->bannedJoints[i].joint);
}
}
static int resolveConfigurationData(struct ModelConfigurationData* config)
{
if (config!=0)
{ //Found a configuration to resolve..
printModelConfigurationData(config);
fprintf(stderr,"Resolving %u NSxM matrix elements..\n",config->numberOfDescriptorElements);
fprintf(stderr,"Using %u hierarchy elements..\n",config->numberOfHierarchyElements);
//---------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------
for (unsigned int descID=0; descID<config->numberOfDescriptorElements; descID++)
{
//Resolve NSxM to Joint ID
for (unsigned int jointID=0; jointID<config->numberOfHierarchyElements; jointID++)
{
fprintf(stderr,"Trying to match %s(%u/%u) with %s(%u/%u)\n",config->descriptorElements[descID].joint,descID,config->numberOfDescriptorElements,config->hierarchyElements[jointID].joint,jointID,config->numberOfHierarchyElements);
if (strcmp(config->descriptorElements[descID].joint,config->hierarchyElements[jointID].joint)==0)
{
fprintf(stderr,"Found\n");
config->descriptorElements[descID].jointID = jointID;
break;
}
}
//Resolve NSxM to Joint ID for halfway
for (int jointID=0; jointID<config->numberOfHierarchyElements; jointID++)
{
if (config->descriptorElements[descID].isVirtual==2)
{
fprintf(stderr,"Trying to match %s(%u) with %s(%u)\n",config->descriptorElements[descID].halfwayFromJointAndThis,descID,config->hierarchyElements[jointID].joint,jointID);
if (strcmp(config->descriptorElements[descID].halfwayFromJointAndThis,config->hierarchyElements[jointID].joint)==0)
{
fprintf(stderr,"Found\n");
config->descriptorElements[descID].secondTargetJointID = jointID;
break;
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------
const int INVALID_VALUE=666;
//Resolve normalized based on order..
//---------------------------------------------------------------------------------------------------------------------------
for (unsigned int descID=0; descID<config->numberOfNormalizedBasedOnRules; descID++)
{
config->normalizedBasedOn[descID].jointStartID=INVALID_VALUE;
config->normalizedBasedOn[descID].jointEndID =INVALID_VALUE;
}
//---------------------------------------------------------------------------------------------------------------------------
for (unsigned int descID=0; descID<config->numberOfDescriptorElements; descID++)
{
for (int jointID=0; jointID<config->numberOfHierarchyElements; jointID++)
{
fprintf(stderr,"Trying to match norm rule %s(%u/%u) with %s(%u/%u)\n",config->descriptorElements[descID].joint,descID,config->numberOfNormalizedBasedOnRules,config->hierarchyElements[jointID].joint,jointID,config->numberOfHierarchyElements);
if (strcmp(config->normalizedBasedOn[descID].jointStart,config->hierarchyElements[jointID].joint)==0)
{
fprintf(stderr,"Found\n");
config->normalizedBasedOn[descID].jointStartID = jointID;
}
if (strcmp(config->normalizedBasedOn[descID].jointEnd,config->hierarchyElements[jointID].joint)==0)
{
fprintf(stderr,"Found\n");
config->normalizedBasedOn[descID].jointEndID = jointID;
}
}
}
//---------------------------------------------------------------------------------------------------------------------------
for (unsigned int descID=0; descID<config->numberOfNormalizedBasedOnRules; descID++)
{
if ( config->normalizedBasedOn[descID].jointStartID == INVALID_VALUE )
{
fprintf(stderr,"Normalization Rule %u/%u for start of joint is unresolved, stopping..\n",descID,config->numberOfNormalizedBasedOnRules);
return 0;
}
if ( config->normalizedBasedOn[descID].jointEndID == INVALID_VALUE )
{
fprintf(stderr,"Normalization Rule %u/%u for end of joint is unresolved, stopping..\n",descID,config->numberOfNormalizedBasedOnRules);
return 0;
}
}
//---------------------------------------------------------------------------------------------------------------------------
// Resolve joint alignment..
//---------------------------------------------------------------------------------------------------------------------------
for (unsigned int descID=0; descID<config->numberOfAlignmentRules; descID++)
{
config->alignment[descID].jointStartID=INVALID_VALUE;
config->alignment[descID].jointEndID =INVALID_VALUE;
}
//---------------------------------------------------------------------------------------------------------------------------
for (unsigned int descID=0; descID<config->numberOfAlignmentRules; descID++)
{
for (int jointID=0; jointID<config->numberOfHierarchyElements; jointID++)
{
fprintf(stderr,"Trying to match norm rule %s(%u/%u) with %s(%u/%u)\n",config->descriptorElements[descID].joint,descID,config->numberOfNormalizedBasedOnRules,config->hierarchyElements[jointID].joint,jointID,config->numberOfHierarchyElements);
if (strcmp(config->alignment[descID].jointStart,config->hierarchyElements[jointID].joint)==0)
{
fprintf(stderr,"Found\n");
config->alignment[descID].jointStartID = jointID;
}
if (strcmp(config->alignment[descID].jointEnd,config->hierarchyElements[jointID].joint)==0)
{
fprintf(stderr,"Found\n");
config->alignment[descID].jointEndID = jointID;
}
}
}
//---------------------------------------------------------------------------------------------------------------------------
for (unsigned int descID=0; descID<config->numberOfAlignmentRules; descID++)
{
if ( config->alignment[descID].jointStartID == INVALID_VALUE )
{
fprintf(stderr,"Normalization Rule %u/%u for start of joint is unresolved, stopping..\n",descID,config->numberOfNormalizedBasedOnRules);
return 0;
}
if ( config->alignment[descID].jointEndID == INVALID_VALUE )
{
fprintf(stderr,"Normalization Rule %u/%u for end of joint is unresolved, stopping..\n",descID,config->numberOfNormalizedBasedOnRules);
return 0;
}
}
//---------------------------------------------------------------------------------------------------------------------------
//Resolve parent order for OpenCV drawing..
for (unsigned int jointID=0; jointID<config->numberOfHierarchyElements; jointID++)
{
//Resolve NSxM to Joint ID
for (unsigned int parentID=0; parentID<config->numberOfHierarchyElements; parentID++)
{
if (strcmp(config->hierarchyElements[parentID].joint,config->hierarchyElements[jointID].joint)==0)
{
fprintf(stderr,"Found\n");
config->hierarchyElements[jointID].parentID = jointID;
break;
}
}
}
return 1;
}
return 0;
}
static int loadModelConfigurationData(struct ModelConfigurationData* out,const char * jsonFilename)
{
fprintf(stderr,"Loading Configuration file %s ...\n",jsonFilename);
unsigned int inputLength=0;
char* input = readFileToMemory(jsonFilename,&inputLength);
if (input!=0)
{
fprintf(stderr,"Parsing %s ...\n",jsonFilename);
const nx_json* json=nx_json_parse_utf8(input);
const nx_json* rule=0;
const nx_json* item=0;
//-------------------------------------------------------------------
const nx_json* j = nx_json_get(json,"version");
if ((j!=0) && (j->type==NX_JSON_STRING)) { out->version = atof(j->text_value); }
//-------------------------------------------------------------------
j = nx_json_get(json,"backend");
if ((j!=0) && (j->type==NX_JSON_STRING)) { snprintf(out->backend,SMALL_STR,"%s",j->text_value); }
//-------------------------------------------------------------------
j = nx_json_get(json,"precision");
if ((j!=0) && (j->type==NX_JSON_STRING)) { snprintf(out->precision,SMALL_STR,"%s",j->text_value); }
//-------------------------------------------------------------------
j = nx_json_get(json,"BVH");
if ((j!=0) && (j->type==NX_JSON_STRING)) { snprintf(out->BVH,BIG_STR,"%s",j->text_value); }
//-------------------------------------------------------------------
j = nx_json_get(json,"OutputDirectory");
if ((j!=0) && (j->type==NX_JSON_STRING)) { snprintf(out->outputDirectory,BIG_STR,"%s",j->text_value); }
//-------------------------------------------------------------------
j = nx_json_get(json,"veryHighNumberOfEpochs");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->veryHighNumberOfEpochs = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"highNumberOfEpochs");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->highNumberOfEpochs = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"defaultNumberOfEpochs");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->defaultNumberOfEpochs = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"defaultBatchSize");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->defaultBatchSize = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"learningRate");
if ((j!=0) && (j->type==NX_JSON_DOUBLE)) { out->learningRate = (float) j->dbl_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"minEarlyStoppingDelta");
if ((j!=0) && (j->type==NX_JSON_DOUBLE)) { out->minEarlyStoppingDelta = (float) j->dbl_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"activationFunction");
if ((j!=0) && (j->type==NX_JSON_STRING)) { snprintf(out->activationFunction,SMALL_STR,"%s",j->text_value); }
//-------------------------------------------------------------------
j = nx_json_get(json,"dropoutRate");
if ((j!=0) && (j->type==NX_JSON_DOUBLE)) { out->dropoutRate = (float) j->dbl_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"lamda");
if ((j!=0) && (j->type==NX_JSON_DOUBLE)) { out->lamda = (float) j->dbl_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"useQuadLoss");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->useQuadLoss = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"useSquaredLoss");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->useSquaredLoss = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"earlyStoppingPatience");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->earlyStoppingPatience = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"rememberWeights");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->rememberWeights = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"rememberConsecutiveWeights");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->rememberConsecutiveWeights = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"useOnlineHardExampleMining");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->useOnlineHardExampleMining = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"hardMiningEpochs");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->hardMiningEpochs = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"normalMiningEpochs");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->normalMiningEpochs = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"groupOutputs");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->groupOutputs = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"ignoreOcclusions");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->ignoreOcclusions = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"NSDMNormalizationMasterSwitch");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->NSDMNormalizationMasterSwitch = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"NSDMAlsoUseAlignmentAngles");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->NSDMAlsoUseAlignmentAngles = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"neuralNetworkDepth");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->neuralNetworkDepth = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"EDM");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->EDM = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"eNSRM");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->eNSRM = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"doPCA");
if ((j!=0) && (j->type==NX_JSON_STRING)) { snprintf(out->doPCA,BIG_STR,"%s",j->text_value); }
//-------------------------------------------------------------------
j = nx_json_get(json,"PCADimensionsKept");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->PCADimensionsKept = j->int_value; }
//-------------------------------------------------------------------
j = nx_json_get(json,"padEnsembleInput");
if ((j!=0) && (j->type==NX_JSON_INTEGER)) { out->padEnsembleInput = j->int_value; }
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------
fprintf(stderr,"Parsed Initial Variables...\n");
//Now to parse Normalization elements..
//-------------------------------------------------------------------
j = nx_json_get(json,"NormalizeNSDMBasedOn");
if (j!=0) {
out->numberOfNormalizedBasedOnRules = j->length;
if (out->numberOfNormalizedBasedOnRules>3)
{
fprintf(stderr,"Maximum Accepted Normalization rules are 3!");
out->numberOfNormalizedBasedOnRules = 3;
}
for (int i=0; i<out->numberOfNormalizedBasedOnRules; i++)
{
rule = nx_json_item(j,i);
//---------------------------------------------------------------------------------------------------
item = nx_json_get(rule,"jointStart");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->normalizedBasedOn[i].jointStart,MAX_JOINT_NAME,"%s",item->text_value); }
item = nx_json_get(rule,"jointStartID");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->normalizedBasedOn[i].jointStartID = item->int_value; }
item = nx_json_get(rule,"jointEnd");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->normalizedBasedOn[i].jointEnd,MAX_JOINT_NAME,"%s",item->text_value); }
item = nx_json_get(rule,"jointEndID");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->normalizedBasedOn[i].jointEndID = item->int_value; }
}
}
//-------------------------------------------------------------------
//Now to parse Alignment elements..
//-------------------------------------------------------------------
j = nx_json_get(json,"Alignment");
if (j!=0) {
out->numberOfAlignmentRules = j->length;
if (out->numberOfAlignmentRules>3)
{
fprintf(stderr,"Maximum Accepted Alignment rules are 3!");
out->numberOfAlignmentRules = 3;
}
for (int i=0; i<out->numberOfAlignmentRules; i++)
{
rule = nx_json_item(j,i);
//---------------------------------------------------------------------------------------------------
item = nx_json_get(rule,"jointStart");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->alignment[i].jointStart,MAX_JOINT_NAME,"%s",item->text_value); }
item = nx_json_get(rule,"jointStartID");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->alignment[i].jointStartID = item->int_value; }
item = nx_json_get(rule,"jointEnd");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->alignment[i].jointEnd,MAX_JOINT_NAME,"%s",item->text_value); }
item = nx_json_get(rule,"jointEndID");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->alignment[i].jointEndID = item->int_value; }
}
}
//-------------------------------------------------------------------
//Now to parse NSxM elements..
//-------------------------------------------------------------------
j = nx_json_get(json,"NSDM");
if (j!=0) {
out->numberOfDescriptorElements = j->length;
if (out->numberOfDescriptorElements>MAX_DESCRIPTOR_ELEMENTS)
{
fprintf(stderr,"Maximum Accepted NSxM rules are %u!",MAX_DESCRIPTOR_ELEMENTS);
out->numberOfDescriptorElements = MAX_DESCRIPTOR_ELEMENTS;
}
for (int i=0; i<out->numberOfDescriptorElements; i++)
{
rule = nx_json_item(j,i);
//---------------------------------------------------------------------------------------------------
item = nx_json_get(rule,"joint");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->descriptorElements[i].joint,MAX_JOINT_NAME,"%s",item->text_value); }
item = nx_json_get(rule,"jointID");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->descriptorElements[i].jointID = item->int_value; }
item = nx_json_get(rule,"isVirtual");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->descriptorElements[i].isVirtual = item->int_value; }
item = nx_json_get(rule,"xOffset");
if ((item!=0) && (item->type==NX_JSON_DOUBLE)) { out->descriptorElements[i].xOffset = (float) item->dbl_value; }
item = nx_json_get(rule,"yOffset");
if ((item!=0) && (item->type==NX_JSON_DOUBLE)) { out->descriptorElements[i].yOffset = (float) item->dbl_value; }
item = nx_json_get(rule,"halfWayFromThisAnd");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->descriptorElements[i].halfwayFromJointAndThis,MAX_JOINT_NAME,"%s",item->text_value); }
item = nx_json_get(rule,"secondTargetJointID");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->descriptorElements[i].secondTargetJointID = item->int_value; }
}
}
//-------------------------------------------------------------------
//Now to parse Hierarchy elements..
//-------------------------------------------------------------------
j = nx_json_get(json,"hierarchy");
if (j!=0) {
out->numberOfHierarchyElements = j->length;
if (out->numberOfHierarchyElements>MAX_HIERARCHY_ELEMENTS)
{
fprintf(stderr,"Maximum Accepted Hierarchy rules are %u!",MAX_HIERARCHY_ELEMENTS);
out->numberOfHierarchyElements = MAX_HIERARCHY_ELEMENTS;
}
for (int i=0; i<out->numberOfHierarchyElements; i++)
{
rule = nx_json_item(j,i);
//---------------------------------------------------------------------------------------------------
item = nx_json_get(rule,"joint");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->hierarchyElements[i].joint,MAX_JOINT_NAME,"%s",item->text_value); }
item = nx_json_get(rule,"inheritNetwork");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->hierarchyElements[i].inheritNetwork,MAX_JOINT_NAME,"%s",item->text_value); }
item = nx_json_get(rule,"parent");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->hierarchyElements[i].parent,MAX_JOINT_NAME,"%s",item->text_value); }
item = nx_json_get(rule,"parentID");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->hierarchyElements[i].parentID = item->int_value; }
item = nx_json_get(rule,"importance");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->hierarchyElements[i].importance = item->int_value; }
item = nx_json_get(rule,"immuneToSelfOcclusions");
if ((item!=0) && (item->type==NX_JSON_INTEGER)) { out->hierarchyElements[i].immuneToSelfOcclusions = item->int_value; }
}
}
//-------------------------------------------------------------------
//Now to parse Hierarchy elements..
//-------------------------------------------------------------------
j = nx_json_get(json,"banned");
if (j!=0) {
out->numberOfBannedJoints = j->length;
if (out->numberOfBannedJoints>MAX_BANNED_ELEMENTS)
{
fprintf(stderr,"Maximum Accepted Banned rules are %u!",MAX_BANNED_ELEMENTS);
out->numberOfBannedJoints = MAX_BANNED_ELEMENTS;
}
for (int i=0; i<out->numberOfBannedJoints; i++)
{
rule = nx_json_item(j,i);
//---------------------------------------------------------------------------------------------------
item = nx_json_get(rule,"output");
if ((item!=0) && (item->type==NX_JSON_STRING)) { snprintf(out->bannedJoints[i].joint,MAX_JOINT_NAME,"%s",item->text_value); }
}
}
//-------------------------------------------------------------------
return resolveConfigurationData(out);
}
return 0;
}
static int getCompositePoint(
float * iXOut,
float * iYOut,
float * iVisibilityOut,
int * invalidPointOut,
struct ModelConfigurationData* rules,
int i,
float * points2D,
unsigned int points2DLength
)
{
if (i > rules->numberOfDescriptorElements)
{
fprintf(stderr,"Point %u out of bounds for descriptor elements\n",i);
return 0;
}
int invalidPoint = 0;
int numberOfNSDMRules = rules->numberOfDescriptorElements;
int iJointID = rules->descriptorElements[i].jointID;
if (iJointID*3 > points2DLength)
{
fprintf(stderr,"Unable to get composite point %u\n",i);
return 0;
}
float iX = points2D[iJointID*3+0];
float iY = points2D[iJointID*3+1];
float iVisibility = points2D[iJointID*3+2];
//---------------------------------------------------------------------------
//In case we fall through..
*iXOut = iX;
*iYOut = iY;
*iVisibilityOut = iVisibility;
*invalidPointOut = invalidPoint;
//---------------------------------------------------------------------------
if ((iX!=0) || (iY!=0))
{
//---------------------------------------------------------------------------
// Synthetic Points
//---------------------------------------------------------------------------
if (rules->descriptorElements[i].isVirtual==1)
{
iX=iX+rules->descriptorElements[i].xOffset;
iY=iY+rules->descriptorElements[i].yOffset;
}
else
if (rules->descriptorElements[i].isVirtual==2)
{
int secondTargetJointID = rules->descriptorElements[i].secondTargetJointID;// rules['NSDM'][i]['secondTargetJointID']
float secondTargetX = points2D[secondTargetJointID*3+0];
float secondTargetY = points2D[secondTargetJointID*3+1];
if ((secondTargetX==0) && (secondTargetY==0))
{
invalidPoint=1;
iX=0;
iY=0;
}
else
{
iX=(float) (iX+secondTargetX)/2;
iY=(float) (iY+secondTargetY)/2;
}
}
//---------------------------------------------------------------------------
//Return values..
*iXOut = iX;
*iYOut = iY;
*iVisibilityOut = iVisibility;
*invalidPointOut = invalidPoint;
return 1;
}
return 0;
}
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,103 @@
/** @file EDM.h
* @brief An implementation of an EDM descriptor
* @author Ammar Qammaz (AmmarkoV)
*/
#ifndef EDM_H_INCLUDED
#define EDM_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
#include "../JSON/readModelConfiguration.h"
#include "NSxM.h"
#include <math.h>
static int countEDMElements(int numberOfJointRules)
{
int count = 0;
for (int i=0; i<numberOfJointRules; i++)
{
for (int j=0; j<numberOfJointRules; j++)
{
if (i>j)
{
count+=1;
}
}
}
return count;
}
/** @brief This function returns the euclidean distance between two input 2D joints and zero if either of them is invalid*/
static float getJoint2DDistanceEDM(float aX,float aY,float bX,float bY)
{
if ( ((aX==0) && (aY==0)) || ((bX==0) && (bY==0)) )
{
return 0.0;
}
//-------------------------
float xDistance=(float) bX-aX;
float yDistance=(float) bY-aY;
float result = sqrt( (xDistance*xDistance) + (yDistance*yDistance) );
if (result!=result)
{
fprintf(stderr,"getJoint2DDistanceEDM yielded NaN..\n");
return 0.0;
}
return result;
}
static int appendEDMElements(
float * input2DJoints,
unsigned int input2DJointsLength,
float * output,
struct ModelConfigurationData* rules
)
{
int numberOfJointRules = rules->numberOfDescriptorElements;
//----------------------
float iX=0.0,iY=0.0,iVisibility=0.0;
int iInvalidPoint=0;
//----------------------
float jX=0.0,jY=0.0,jVisibility=0.0;
int jInvalidPoint=0;
//----------------------
int count = 0;
for (int i=0; i<numberOfJointRules; i++)
{
getCompositePoint(&iX,&iY,&iVisibility,&iInvalidPoint,rules,i,input2DJoints,input2DJointsLength);
for (int j=0; j<numberOfJointRules; j++)
{
if (i>j)
{
getCompositePoint(&jX,&jY,&jVisibility,&jInvalidPoint,rules,j,input2DJoints,input2DJointsLength);
if ( (iInvalidPoint) && (jInvalidPoint) ) //<- Why is this AND and not OR ? also in EDM.py code
{
output[count] = 0.0;
} else
{
output[count] = getJoint2DDistanceEDM(iX,iY,jX,jY);
}
count+=1;
}
}
}
return count;
}
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,45 @@
/** @file NSDM.h
* @brief An implementation of an NSRM descriptor
* @author Ammar Qammaz (AmmarkoV)
*/
#ifndef NSDM_H_INCLUDED
#define NSDM_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
#include "../JSON/readModelConfiguration.h"
#include "NSxM.h"
#include <math.h>
static int countNSDMElements(int numberOfJointRules)
{
return 2*numberOfJointRules*numberOfJointRules;
}
static int appendNSDMElements(
float * input2DJoints,
struct descriptor * output,
int numberOfJointRules
)
{
return 0;
}
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,343 @@
/** @file NSRM.h
* @brief An implementation of an NSRM descriptor
* @author Ammar Qammaz (AmmarkoV)
*/
#ifndef NSRM_H_INCLUDED
#define NSRM_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
#include <math.h>
const float goFromRadToDegrees=(float) 180.0 / M_PI;
const float goFromDegreesToRad=(float) M_PI / 180.0;
/** @brief This function returns the euclidean distance between two input 2D joints and zero if either of them is invalid*/
static float getJoint2DDistance_NSRM(float aX,float aY,float bX,float bY)
{
float xDistance=(float) bX-aX;
float yDistance=(float) bY-aY;
return (float) sqrt( (xDistance*xDistance) + (yDistance*yDistance) );
}
static float getAngleToAlignToZero_NSRM(float aX,float aY,float bX,float bY)
{
if ( (aX==bX) && (aY==bY) ) { return 0; }
//Bigger magnitudes..
aX=100*aX;
aY=100*aY;
bX=100*bX;
bY=100*bY;
//We have points a, b and c and we want to calculate angle b
float lengthBetweenAAndB = getJoint2DDistance_NSRM(aX,aY,bX,bY);
//We align vertically.. , Point C is B offset in Y direction
float cX = bX;
float cY = bY - lengthBetweenAAndB;
//fprintf(stderr,"We want to align A(%0.2f,%0.2f) to C(%0.2f,%0.2f) with pivot B(%0.2f,%0.2f)\n",aX,aY,cX,cY,bX,bY);
//fprintf(stderr,"length AB = %0.2f\n",lengthBetweenAAndB);
//fprintf(stderr,"bY = %0.2f\n",bY);
//fprintf(stderr,"cY = %0.2f = %0.2f - %0.2f\n",cY,bY,lengthBetweenAAndB);
//Calulate vector a->b
float abX = bX - aX;
float abY = bY - aY;
//calculate vector c->b
float cbX = bX - cX;
float cbY = bY - cY;
float dot = ((abX * cbX) + (abY * cbY)); // dot product
float cross = ((abX * cbY) - (abY * cbX)); // cross product
float alpha = atan2(cross,dot);
//fprintf(stderr,"Angle is %0.2f rad or %0.2f degrees \n",alpha,alpha*goFromRadToDegrees);
return (float) alpha;// * goFromRadToDegrees ;
}
static float getAngleToAlignToZeroJoints_NSRM(float * positions,unsigned int centerJoint,unsigned int referenceJoint)
{
//We have points a, b and c and we want to calculate angle b
float aX= positions[referenceJoint*3+0];
float aY= positions[referenceJoint*3+1];
float bX= positions[centerJoint*3+0];
float bY= positions[centerJoint*3+1];
return getAngleToAlignToZero_NSRM(aX,aY,bX,bY);
}
/*
static int rotate2DPointsBasedOnJointAsCenter_NSRM(float * positions,int positionsSize,float angle,unsigned int centerJoint)
{
if (positionsSize%3!=0)
{
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: incorrect positions.. \n" NORMAL);
return 0;
}
if (positionsSize<=centerJoint*3)
{
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: centerJoint out of bounds.. \n" NORMAL);
return 0;
}
float s = sin((float) angle * goFromDegreesToRad);
float c = cos((float) angle * goFromDegreesToRad);
//=================================================
float cx = positions[centerJoint*3+0];
float cy = positions[centerJoint*3+1];
float cVisibility = positions[centerJoint*3+2];
//=================================================
if (cVisibility==0.0)
{
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: cannot work without pivot joint.. \n" NORMAL);
return 0;
}
for (unsigned int jID=0; jID<positionsSize/3; jID++)
{
float jX=positions[jID*3+0];
float jY=positions[jID*3+1];
float jVisibility=positions[jID*3+2];
//fprintf(stderr,"Rotating point %0.2f,%0.2f using pivot %0.2f,%0.2f by %0.2f deg -> ",jX,jY,cx,cy,angle);
//Translate point back to origin:
jX -= cx;
jY -= cy;
//Rotate point
float xnew = jX * c - jY * s;
float ynew = jX * s + jY * c;
//Translate point back:
positions[jID*3+0] = xnew + cx;
positions[jID*3+1] = ynew + cy;
//fprintf(stderr,"%0.2f,%0.2f\n",positions[jID*3+0],positions[jID*3+1]);
}
return 1;
}*/
static int countNSRMElements(int numberOfJointRules)
{
return numberOfJointRules*numberOfJointRules;
}
static int rotate2DPointsBasedOnJointAsCenter_NSRM(float * positions,unsigned int positionsLength,float angle,unsigned int centerJoint)
{
if (positionsLength%3!=0)
{
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: incorrect positions.. \n" NORMAL);
return 0;
}
if (positionsLength<=centerJoint*3)
{
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: centerJoint out of bounds.. \n" NORMAL);
return 0;
}
float s = sin((float) angle * goFromDegreesToRad );
float c = cos((float) angle * goFromDegreesToRad );
float cx=positions[centerJoint*3+0];
float cy=positions[centerJoint*3+1];
float cVisibility=positions[centerJoint*3+2];
if (cVisibility==0.0)
{
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: cannot work with invisible pivot joint.. \n" NORMAL);
return 0;
}
for (unsigned int jID=0; jID<positionsLength/3; jID++)
{
float jX=positions[jID*3+0];
float jY=positions[jID*3+1];
float jVisibility=positions[jID*3+2];
//fprintf(stderr,"Rotating point %0.2f,%0.2f using pivot %0.2f,%0.2f by %0.2f deg -> ",jX,jY,cx,cy,angle);
//Translate point back to origin:
jX -= cx;
jY -= cy;
//Rotate point
float xnew = jX * c - jY * s;
float ynew = jX * s + jY * c;
//Translate point back:
positions[jID*3+0] = xnew + cx;
positions[jID*3+1] = ynew + cy;
//fprintf(stderr,"%0.2f,%0.2f\n",positions[jID*3+0],positions[jID*3+1]);
}
return 1;
}
static float performNSRMAlignment(float * input2DJoints,
unsigned int input2DJointsLength,
struct ModelConfigurationData* rules)
{
//Enforce alignment rule..
//------------------------------------------------------------
int pivotPoint = rules->alignment[0].jointStartID;// rules['Alignment'][0]['jointStartID']
int referencePoint = rules->alignment[0].jointEndID; // rules['Alignment'][0]['jointEndID']
//------------------------------------------------------------
float pivotX = input2DJoints[pivotPoint*3+0];
float pivotY = input2DJoints[pivotPoint*3+1];
float pivotVisibility = input2DJoints[pivotPoint*3+2];
float referenceX = input2DJoints[referencePoint*3+0];
float referenceY = input2DJoints[referencePoint*3+1];
float referenceVisibility = input2DJoints[referencePoint*3+2];
//------------------------------------------------------------
float angleToRotate = 0.0;
if ((pivotVisibility!=0) && (referenceVisibility!=0))
{
angleToRotate = getAngleToAlignToZero_NSRM(pivotX,pivotY,referenceX,referenceY);
rotate2DPointsBasedOnJointAsCenter_NSRM(input2DJoints,input2DJointsLength,angleToRotate,pivotPoint);
}
return angleToRotate;
}
static int appendNSRMElements(
float * input2DJoints,
unsigned int input2DJointsLength,
float * output,
struct ModelConfigurationData* rules,
float angleUsedToRotateInput
)
{
int numberOfJointRules = rules->numberOfDescriptorElements;
//----------------------
float iX=0.0,iY=0.0,iVisibility=0.0;
int iInvalidPoint=0;
//----------------------
float jX=0.0,jY=0.0,jVisibility=0.0;
int jInvalidPoint=0;
//----------------------
//-----------------------------------------------------------------------------------------------------
// ..Main NSRM parameters ..
//-----------------------------------------------------------------------------------------------------
int count = 0;
for (int i=0; i<numberOfJointRules; i++)
{
getCompositePoint(&iX,&iY,&iVisibility,&iInvalidPoint,rules,i,input2DJoints,input2DJointsLength);
for (int j=0; j<numberOfJointRules; j++)
{
getCompositePoint(&jX,&jY,&jVisibility,&jInvalidPoint,rules,j,input2DJoints,input2DJointsLength);
if ( (iInvalidPoint) || (jInvalidPoint) )
{
output[count] = 0.0;
} else
{
output[count] = getAngleToAlignToZero_NSRM(iX,iY,jX,jY);// getJoint2DDistanceEDM(input2DJoints,i,j);
}
count+=1;
}
}
//-----------------------------------------------------------------------------------------------------
// ..New eNSRM diagonal parameters ..
//-----------------------------------------------------------------------------------------------------
if (rules->eNSRM)
{
count=0;
int iJointID = rules->descriptorElements[0].jointID;
iX = input2DJoints[iJointID*3+0];
iY = input2DJoints[iJointID*3+1];
//getCompositePoint(&iX,&iY,&iVisibility,&iInvalidPoint,rules,i,input2DJoints,input2DJointsLength);
for (int i=0; i<numberOfJointRules; i++)
{
for (int j=0; j<numberOfJointRules; j++)
{
if (i==j)
{
output[count] == angleUsedToRotateInput;
if (i>0)
{
int jJointID = rules->descriptorElements[j].jointID;
jX = input2DJoints[jJointID*3+0];
jY = input2DJoints[jJointID*3+1];
//getCompositePoint(&jX,&jY,&jVisibility,&jInvalidPoint,rules,j,input2DJoints,input2DJointsLength);
output[count] = getJoint2DDistance_NSRM(iX,iY,jX,jY);
}
}
count+=1;
}
}
}
//NSDM Normalization rule does not apply on NSRM
//SKIPPED
//-----------------------------------------------------------------------------------------------------
//Enforce alignment rule..
//------------------------------------------------------------
int iJointID = rules->alignment[0].jointStartID;// rules['Alignment'][0]['jointStartID']
int jJointID = rules->alignment[0].jointEndID; // rules['Alignment'][0]['jointEndID']
//------------------------------------------------------------
float aX = input2DJoints[iJointID*3+0];
float aY = input2DJoints[iJointID*3+1];
float bX = input2DJoints[jJointID*3+0];
float bY = input2DJoints[jJointID*3+1];
//------------------------------------------------------------
float alignmentAngle = getAngleToAlignToZero_NSRM(aX,aY,bX,bY);
//fprintf(stderr,"ALIGNMENT %u %u %f",iJointID,jJointID,alignmentAngle);
for (int i=0; i<count; i++)
{
if (output[i]!=0.0)
{ output[i]=(float) alignmentAngle+output[i]; }
}
return count;
}
#ifdef __cplusplus
}
#endif
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,137 @@
#include "calculations.h"
#include <stdio.h>
#include <stdlib.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 */
const float goFromRadToDegrees=(float) 180.0 / M_PI;
const float goFromDegreesToRad=(float) M_PI / 180.0;
/** @brief This function returns the euclidean distance between two input 2D joints and zero if either of them is invalid*/
float getJoint2DDistance_tools(float aX,float aY,float bX,float bY)
{
float xDistance=(float) bX-aX;
float yDistance=(float) bY-aY;
return (float) sqrt( (xDistance*xDistance) + (yDistance*yDistance) );
}
float getAngleToAlignToZero_tools(float aX,float aY,float bX,float bY)
{
if ( (aX==bX) && (aY==bY) ) { return 0; }
//Bigger magnitudes..
aX=100*aX;
aY=100*aY;
bX=100*bX;
bY=100*bY;
//We have points a, b and c and we want to calculate angle b
float lengthBetweenAAndB = getJoint2DDistance_tools(aX,aY,bX,bY);
//We align vertically.. , Point C is B offset in Y direction
float cX = bX;
float cY = bY - lengthBetweenAAndB;
//fprintf(stderr,"We want to align A(%0.2f,%0.2f) to C(%0.2f,%0.2f) with pivot B(%0.2f,%0.2f)\n",aX,aY,cX,cY,bX,bY);
//fprintf(stderr,"length AB = %0.2f\n",lengthBetweenAAndB);
//fprintf(stderr,"bY = %0.2f\n",bY);
//fprintf(stderr,"cY = %0.2f = %0.2f - %0.2f\n",cY,bY,lengthBetweenAAndB);
//Calulate vector a->b
float abX = bX - aX;
float abY = bY - aY;
//calculate vector c->b
float cbX = bX - cX;
float cbY = bY - cY;
float dot = (abX * cbX + abY * cbY); // dot product
float cross = (abX * cbY - abY * cbX); // cross product
float alpha = atan2(cross, dot);
//fprintf(stderr,"Angle is %0.2f rad or %0.2f degrees \n",alpha,alpha*goFromRadToDegrees);
return (float) alpha;// * goFromRadToDegrees ;
}
float getAngleToAlignToZero(float *positions,unsigned int centerJoint,unsigned int referenceJoint)
{
//We have points a, b and c and we want to calculate angle b
float aX= positions[referenceJoint*3+0];
float aY= positions[referenceJoint*3+1];
float bX= positions[centerJoint*3+0];
float bY= positions[centerJoint*3+1];
return getAngleToAlignToZero_tools(aX,aY,bX,bY);
}
int rotate2DPointsBasedOnJointAsCenter(float * positions,unsigned int positionsLength,float angle,unsigned int centerJoint)
{
if (positionsLength%3!=0)
{
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: incorrect positions.. \n" NORMAL);
return 0;
}
if (positionsLength<=centerJoint*3)
{
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: centerJoint out of bounds.. \n" NORMAL);
return 0;
}
float s = sin((float) angle * goFromDegreesToRad );
float c = cos((float) angle * goFromDegreesToRad );
float cx=positions[centerJoint*3+0];
float cy=positions[centerJoint*3+1];
float cVisibility=positions[centerJoint*3+2];
if (cVisibility==0.0)
{
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: cannot work without pivot joint.. \n" NORMAL);
return 0;
}
for (unsigned int jID=0; jID<positionsLength/3; jID++)
{
float jX=positions[jID*3+0];
float jY=positions[jID*3+1];
float jVisibility=positions[jID*3+2];
//fprintf(stderr,"Rotating point %0.2f,%0.2f using pivot %0.2f,%0.2f by %0.2f deg -> ",jX,jY,cx,cy,angle);
//Translate point back to origin:
jX -= cx;
jY -= cy;
//Rotate point
float xnew = jX * c - jY * s;
float ynew = jX * s + jY * c;
//Translate point back:
positions[jID*3+0] = xnew + cx;
positions[jID*3+1] = ynew + cy;
//fprintf(stderr,"%0.2f,%0.2f\n",positions[jID*3+0],positions[jID*3+1]);
}
return 1;
}
@@ -0,0 +1,27 @@
/** @file calculations.h
* @brief calculations used for descriptors
* @author Ammar Qammaz (AmmarkoV)
*/
#ifndef CALCULATIONS_H_INCLUDED
#define CALCULATIONS_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
#include <math.h>
float getJoint2DDistance_tools(float aX,float aY,float bX,float bY);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,446 @@
/** @file PCA.h
* @brief An implementation of a PCA data loader
* @author Ammar Qammaz (AmmarkoV)
*/
#ifndef PCA_H_INCLUDED
#define PCA_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <stdlib.h>
#include "../JSON/nxjson.h"
#include "../tools.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 */
struct eigenVectorOpt
{
float __attribute__((aligned(16))) * value;
};
struct complexNumber
{
float realPart;
float imaginaryPart;
};
struct eigenVector
{
struct complexNumber * value;
};
struct PCAData
{
unsigned int numberOfSamplesUsedToCreatePCA;
unsigned int numberOfEigenValues;
float mean;
float std;
struct complexNumber * eigenValues;
struct eigenVector * eigenVectors;
float * screeProportion;
float * screeCumulative;
};
//Complex Numbers
//http://ebooks.edu.gr/ebooks/v/html/8547/2754/Mathimatika-B-Lykeiou-ThSp_html-apli/index5_2.html
static struct complexNumber addComplexNumbers(struct complexNumber a,struct complexNumber b)
{
struct complexNumber result={0};
result.realPart = a.realPart + b.realPart;
result.imaginaryPart = a.imaginaryPart + b.imaginaryPart;
return result;
}
static struct complexNumber multiplyComplexNumbers(struct complexNumber a,struct complexNumber b)
{
struct complexNumber result={0};
// (A + B i) * (C + D i) = (AC-BD) + (AD+BC) i
// (a.realPart + a.imaginaryPart i) * (b.realPart + b.imaginaryPart i) = (a.realPart b.realPart - a.imaginaryPart b.imaginaryPart) + (a.realPart b.imaginaryPart + a.imaginaryPart b.realPart) i
result.realPart = (a.realPart*b.realPart) - (a.imaginaryPart*b.imaginaryPart);
result.imaginaryPart = (a.realPart*b.imaginaryPart) + (a.imaginaryPart*b.realPart);
return result;
}
static char * recognizeComplexNumberStart(char * complexNumber)
{
int l = strlen(complexNumber);
char * res = complexNumber;
//All Complex Numbers end with j
//-------------------------------
//We expect something like :
// -4.1106844e-12-4.560428e-12j
// or
// -4.1106844e-12-4.560428e+12j
// or
// -4.1106844e-12-4.560428j
// or
// -4.1106844e-12+48j
//-------------------------------
if (l>2)
{
if (complexNumber[l-1]=='j')
{
l=l-2;
while (l>0)
{
if (
(complexNumber[l]=='+') ||
(complexNumber[l]=='-')
)
{
//We have reache a +/- symbol there are three cases :
//Case A ) if the previous character is an e then it is a scientific notation complex number!
//Case B ) if not then we found the complex number start!
//Case C ) if l is 0 then we reached the start of the string!
if (l>0)
{
if (complexNumber[l-1]!='e')
{
//This is not a scientific notation so Case B we found our result!
res = complexNumber+l;
break;
}
}
}
l=l-1;
}
}
}
return res;
}
static struct complexNumber parseComplexNumber(const char * complexNumberString)
{
struct complexNumber result={0};
//---------------------------------------------------------------------------------------------
if ( complexNumberString == 0 ) { return result; }
if (complexNumberString[0]=='(') { complexNumberString++; } //Point to second element to skip (
char localBuffer[128];
snprintf(localBuffer,128,"%s",complexNumberString);
float imaginaryPart = 0.0;
char * seperator = strchr(localBuffer,')');
if (seperator!=0) { *seperator = 0; } //Trim last )
seperator = strstr(localBuffer,"+0j");
if (seperator!=0)
{
//This is the easy case which means that the value is a clear float value and the +0j can be easily discarded!
*seperator = 0;
} else
{
unsigned int l = strlen(localBuffer);
if (localBuffer[l-1]=='j')
{
fprintf(stderr,"Parsing complex number `%s`\n",localBuffer);
seperator = recognizeComplexNumberStart(localBuffer);
if (seperator!=0)
{
*seperator = 0;
fprintf(stderr,"Imaginary part `%s` / keeping real part `%s` \n",seperator+1,localBuffer);
char * imaginaryPartString = seperator+1;
int lastCharacter = strlen(imaginaryPartString);
if (imaginaryPartString[lastCharacter-1]=='j')
{ imaginaryPartString[lastCharacter-1]=0; }
imaginaryPart = strtof(imaginaryPartString,NULL);
}
}
}
float cleanedFloat = strtof(localBuffer,NULL);
//fprintf(stderr,"Cleaned float is %f \n",cleanedFloat);
if (cleanedFloat!=cleanedFloat)
{
//If we got a NaN value then clean it..
cleanedFloat = 0.0;
}
result.realPart = cleanedFloat;
result.imaginaryPart = imaginaryPart;
return result;
}
static int unloadPCAData(struct PCAData* pca)
{
if (pca!=0)
{
if (pca->screeProportion!=0) { free(pca->screeProportion); pca->screeProportion=0; }
if (pca->screeCumulative!=0) { free(pca->screeCumulative); pca->screeCumulative=0; }
if (pca->eigenValues!=0) { free(pca->eigenValues); pca->eigenValues=0; }
if (pca->eigenVectors!=0)
{
for (int i=0; i<pca->numberOfEigenValues; i++)
{
free(pca->eigenVectors[i].value);
}
free(pca->eigenVectors);
}
return 1;
}
return 0;
}
static int loadPCADataFromJSON(struct PCAData* output, const char * jsonFilename)
{
fprintf(stderr,"Loading PCA file %s ...\n",jsonFilename);
unsigned int inputLength=0;
char* input = readFileToMemory(jsonFilename,&inputLength);
if (input!=0)
{
//fprintf(stderr,"JSON DATA %s ...\n",input);
fprintf(stderr,"Parsing %s ...\n",jsonFilename);
const nx_json* json=nx_json_parse_utf8(input);
//-------------------------------------------------------------------
const nx_json* j = nx_json_get(json,"numberOfSamplesFittedOn");
fprintf(stderr,"key(%s)/type(%u)\n",j->key,j->type);
output->numberOfSamplesUsedToCreatePCA = (unsigned int) atoi(j->text_value);
//-------------------------------------------------------------------
j = nx_json_get(json,"expectedInputs");
fprintf(stderr,"key(%s)/type(%u)\n",j->key,j->type);
output->numberOfEigenValues = (unsigned int) atoi(j->text_value);
//-------------------------------------------------------------------
j = nx_json_get(json,"std");
fprintf(stderr,"key(%s)/type(%u)\n",j->key,j->type);
output->std = (float) atof(j->text_value);
j = nx_json_get(json,"mean");
fprintf(stderr,"key(%s)/type(%u)\n",j->key,j->type);
output->mean = (float) atof(j->text_value);
//-------------------------------------------------------------------
//Our Summary..!
//----------------------------------------------------------------------------------------------------------------------------
fprintf(stderr,"Number Of Samples %u\n",output->numberOfSamplesUsedToCreatePCA);
fprintf(stderr,"Number Of Eigen Values %u\n",output->numberOfEigenValues);
fprintf(stderr,"Mean %0.2f / Std %0.2f\n",output->mean,output->std );
//We have now allocated enough space and are ready to parse all incoming values..
//----------------------------------------------------------------------------------------------------------------------------
output->eigenValues = (struct complexNumber*) malloc(sizeof(struct complexNumber) * output->numberOfEigenValues);
output->eigenVectors = (struct eigenVector*) malloc(sizeof(struct eigenVector) * output->numberOfEigenValues);
if (output->eigenVectors)
{
for (int i=0; i<output->numberOfEigenValues; i++)
{
output->eigenVectors[i].value = (struct complexNumber*) malloc(sizeof(struct complexNumber) * output->numberOfEigenValues);
}
}
output->screeProportion = (float*) malloc(sizeof(float) * output->numberOfEigenValues);
output->screeCumulative = (float*) malloc(sizeof(float) * output->numberOfEigenValues);
//----------------------------------------------------------------------------------------------------------------------------
j = nx_json_get(json,"eigenvalues");
fprintf(stderr,"We encountered %u eigenvalues (header says %u) \n",j->length,output->numberOfEigenValues);
if (j->length == output->numberOfEigenValues)
{
//We have a correct number of eigenvalues so let's read them!
for (int idx=0; idx<output->numberOfEigenValues; idx++)
{
const nx_json* item = nx_json_item(j,idx);
//fprintf(stderr,"key(%s)/index(%u)/type(%u)\n",j->key,idx,item->type);
output->eigenValues[idx] = parseComplexNumber(item->text_value);
}
}
const nx_json* jY = nx_json_get(json,"eigenvectors");
if (jY->length == output->numberOfEigenValues)
{
fprintf(stderr,"We encountered %u eigenvectors (header says %u) \n",jY->length,output->numberOfEigenValues);
//We have a correct number of eigenvalues so let's read them!
for (int idy=0; idy<output->numberOfEigenValues; idy++)
{
const nx_json* itemY = nx_json_item(jY,idy);
if (itemY->length == output->numberOfEigenValues)
{
for (int idx=0; idx<output->numberOfEigenValues; idx++)
{
const nx_json* itemX = nx_json_item(itemY,idx);
//fprintf(stderr,"key(%s)/index(%u)/type(%u)\n",j->key,idx,item->type);
output->eigenVectors[idx].value[idy] = parseComplexNumber(itemX->text_value);
}
} else
{
fprintf(stderr,"Eigen Vector %d has an incorrect number of values (%u)\n",idy,itemY->length);
}
}
}
j = nx_json_get(json,"scree_proportion");
fprintf(stderr,"We encountered %u scree_proportions (header says %u) \n",j->length,output->numberOfEigenValues);
if (j->length == output->numberOfEigenValues)
{
//We have a correct number of eigenvalues so let's read them!
for (int idx=0; idx<output->numberOfEigenValues; idx++)
{
const nx_json* item = nx_json_item(j,idx);
//fprintf(stderr,"key(%s)/index(%u)/type(%u)\n",j->key,idx,item->type);
output->screeProportion[idx] = strtof(item->text_value,NULL);
}
}
j = nx_json_get(json,"scree_cumulative");
fprintf(stderr,"We encountered %u scree_cumulatives (header says %u) \n",j->length,output->numberOfEigenValues);
if (j->length == output->numberOfEigenValues)
{
//We have a correct number of eigenvalues so let's read them!
for (int idx=0; idx<output->numberOfEigenValues; idx++)
{
const nx_json* item = nx_json_item(j,idx);
//fprintf(stderr,"key(%s)/index(%u)/type(%u)\n",j->key,idx,item->type);
output->screeCumulative[idx] = strtof(item->text_value,NULL);
}
}
nx_json_free(json);
free(input);
return 1;
}
return 0;
}
float dotProduct(float * vect_A, float * vect_B, int n)
{
float product = 0.0;
for (int i = 0; i < n; i++)
{ product += vect_A[i] * vect_B[i]; }
return product;
}
static int doPCATransform(float * output,int * outputSize,struct PCAData* pca,float * inputRaw,int inputSize,int selectedPCADimensions)
{
if (pca==0) { return 0; }
if (pca->numberOfEigenValues!=inputSize) { fprintf(stderr, RED "PCA: Shape given as input (%d,) is not aligned with PCA loaded (%u,%d) \n" NORMAL,inputSize,pca->numberOfEigenValues,*outputSize); return 0; }
float mean = pca->mean;
float std = pca->std;
if (std == 0.0 ) { std=1.0; } //Don't ever divide by zero
fprintf(stderr," sample = list()\n");
for (int i=0; i<inputSize; i++)
{
fprintf(stderr," sample.append(%f) #%u\n",inputRaw[i],i);
}
//float __attribute__((aligned(16))) * input = (float*) aligned_alloc(16, inputSize * sizeof(float));
//float * input = (float*) malloc(inputSize * sizeof(float));
struct complexNumber * inputComplex = (struct complexNumber *) malloc(inputSize * sizeof(struct complexNumber));
struct complexNumber * outputComplex = (struct complexNumber *) malloc(*outputSize * sizeof(struct complexNumber));
//if (input!=0)
if ((inputComplex!=0) && (outputComplex!=0))
{
for (int i=0; i<inputSize; i++)
{
//input[i] = (inputRaw[i]-mean)/std;
inputComplex[i].realPart = (inputRaw[i]-mean)/std;
inputComplex[i].imaginaryPart = 0.0;
}
if (selectedPCADimensions>inputSize)
{
selectedPCADimensions = inputSize;
}
fprintf(stderr,"We want dot product of %u dimensions : \n",selectedPCADimensions);
fprintf(stderr,"Input of size 0->%u\n",inputSize);
fprintf(stderr,"EigenVector of size 0->%u\n",pca->numberOfEigenValues);
/*
* input is 1 x 458
eigenvectors is 458 x 458
result is 1 x 210
data is 1 x 461
eigenvectors is 461 x 461
result is 1 x 210
a = [[0, 1 , 2]]
b = [[4, 1], [3, 2], [10,10] ]
#[[23 22]]
print(np.dot(a,b))
* ./MocapNET4TestD
* python3 DNN_Tensorflow2/principleComponentAnalysis.py
*/
for (int i=0; i<selectedPCADimensions; i++)
{
output[i] = 0.0;
outputComplex[i].realPart = 0.0;
outputComplex[i].imaginaryPart = 0.0;
}
for (int i=0; i<selectedPCADimensions; i++)
{
//---------------------------------
for (int j=0; j<pca->numberOfEigenValues; j++)
{
//fprintf(stderr,"%0.2f * %0.2f \n",input[j],pca->eigenVectors[i].value[j]);
//output[i] += input[j] * pca->eigenVectors[i].value[j];
//output[i] += input[j] * pca->eigenVectors[i].value[j].realPart;
struct complexNumber thisOutputComplex = multiplyComplexNumbers(inputComplex[j],pca->eigenVectors[i].value[j]);
outputComplex[i].realPart += thisOutputComplex.realPart;
outputComplex[i].imaginaryPart += thisOutputComplex.imaginaryPart;
}
//---------------------------------
}
//We have gone through all of the complex arithmetic, now we will keep only the real part
for (int i=0; i<selectedPCADimensions; i++)
{
output[i] = outputComplex[i].realPart;
}
//free(input);
free(inputComplex);
free(outputComplex);
} else
{
fprintf(stderr,"Could not allocate aligned memory block..\n");
return 0;
}
//------------------------------------------
return 1;
}
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,327 @@
#!/usr/bin/python3
"""
Author : "Ammar Qammaz"
Copyright : "2022 Foundation of Research and Technology, Computer Science Department Greece, See license.txt"
License : "FORTH"
"""
import sys
import numpy as np
#python3 principleComponentAnalysisTester.py --config dataset/body_configuration.json --mem 1000 --highlight 4 --mode 3
"""
Debug sanity check function to do PCA using SK Learn to make sure there are no errors on my numpy implementation
"""
def doPCAUsingSKLearn(data,label):
from sklearn.decomposition import PCA
import pandas as pd
numberOfDimensions = 20
pca = PCA(n_components=numberOfDimensions)
# Standardizing the features
from sklearn.preprocessing import StandardScaler
data = StandardScaler().fit_transform(data)
principalComponents = pca.fit_transform(data)
#print(principalComponents)
import matplotlib.pyplot as plt
fig = plt.figure(figsize = (8,8))
fig.set_size_inches(19.2, 10.8, forward=True)
ax1 = fig.add_subplot(2, 1, 1,projection='3d')
ax2 = fig.add_subplot(2, 1, 2)
#ax = fig.add_subplot(1,1,1)
ax1.set_xlabel('Principal Component 1', fontsize = 15)
ax1.set_ylabel('Principal Component 2', fontsize = 15)
ax1.set_zlabel('Principal Component 3', fontsize = 15)
ax1.set_title('%u component PCA %s '%(numberOfDimensions,label), fontsize = 20)
ax1.scatter(principalComponents[:,0],
principalComponents[:,1],
principalComponents[:,2],
c = principalComponents[:,3]
#,s = principalComponents[:,3]
)
print("PCA variange ration : ",pca.explained_variance_ratio_)
PC_values = np.arange(pca.n_components_) + 1
ax2.plot(PC_values, pca.explained_variance_ratio_, 'o-', linewidth=2, color='blue')
ax2.set_title('Scree Plot %s'%label)
ax2.set_xlabel('Principal Component')
ax2.set_ylabel('Variance Explained')
plt.show()
sys.exit(0)
"""
Debug function to check the stats per column for our input
"""
def getStatsPerColumn(NSxM):
print("NSxM is ",NSxM.shape[0]," x ",NSxM.shape[1])
#NSxM.tofile('dump.csv', sep=',')
for column in range(0,NSxM.shape[1]):
singleNSxMElement = splitNumpyArray(NSxM,column,1,0)
median = np.median(singleNSxMElement)
mean = np.mean(singleNSxMElement)
std = np.std(singleNSxMElement)
var = np.var(singleNSxMElement)
print("Element ",column,"/",NSxM.shape[1]," => Median is ",median,"Mean is ",mean," Std is ",std," Var is ",var)
sys.exit(0)
class PCA():
def __init__(self,
inputData:np.array=np.array([]),
savedFile:str=""
):
self.mean = 0.0
self.std = 1.0
self.eigenvalues = np.array([])
self.eigenvectors = np.array([])
self.proportional = list()
self.cumulative = list()
self.numberOfSamplesFittedOn = 0
self.expectedInputs = 0
if (savedFile!=""):
self.load(savedFile)
elif inputData.size != 0:
self.fit(inputData)
else:
print("No PCA input given..!")
def ok(self):
return self.numberOfSamplesFittedOn!=0
def getNumberOfExpectedSamples(self):
#return len(self.eigenvalues)
return np.size(self.eigenvalues, axis = 0)
def fit(self,data):
#doPCAUsingSKLearn(data,"Test")
#getStatsPerColumn(data)
#print(data)
self.numberOfSamplesFittedOn = data.shape[0]
print("Doing PCA fit on ",self.numberOfSamplesFittedOn)
print(" please wait .. ")
#Standardize data
#-------------------------------------------------------------------------------------------------
self.mean = data.mean()
data = data - self.mean
# Normalize
self.std = data.std()
if (self.std!=0.0):
data = data / self.std
#print('Data Mean : ',self.mean,'STD: ',self.std)
#-------------------------------------------------------------------------------------------------
#Take the matrix, transpose it, and multiply the transposed matrix. This is the covariance matrix.
covarianceMatrix = np.dot(data.T,data)
#Get an array of computed eigenvalues and a matrix whose columns are the normalized eigenvectors corresponding to the eigenvalues in that order.
#In this step it is important to make sure that the eigenvalues and its eigenvectors are sorted in descending order (from largest to smallest). Sort the eigenvalues and then the eigenvectors, accordingly.
self.eigenvalues, self.eigenvectors = np.linalg.eig(covarianceMatrix)
#Sort eigenvectors according to eigenvalues
idx = self.eigenvalues.argsort()[::-1]
self.eigenvalues = self.eigenvalues[idx]
self.eigenvectors = self.eigenvectors[:,idx]
#Assign P to the matrix of eigenvectors and D to the diagonal matrix with eigenvalues on the diagonal and values of zero everywhere else.
#The eigenvalues on the diagonal of D will be associated with the corresponding column in P.
D = np.diag(self.eigenvalues)
P = self.eigenvectors
self.expectedInputs = len(self.eigenvalues)
#1. Calculate the proportion of variance explained by each feature
sumOfEigenvalues = np.sum(self.eigenvalues)
self.proportional = [i/sumOfEigenvalues for i in self.eigenvalues]
#2. Calculate the cumulative variance
self.cumulative = [np.sum(self.proportional[:i+1]) for i in range(len(self.proportional))]
def transform(self,data,selectedPCADimensions=0):
if (self.numberOfSamplesFittedOn==0):
print("Can't transform input with no PCA loaded ..")
return data
#Normalize input data
data = data - self.mean
if (self.std!=0.0):
data = data / self.std
#Do transform..
if (selectedPCADimensions==0):
#Transform using all PCA components
return np.dot(data,self.eigenvectors)
else:
#print("eigenvectors is ",eigenvectors.shape[0]," x ",eigenvectors.shape[1])
return data.dot(self.eigenvectors[:,:selectedPCADimensions])
def save(self,filename):
print("Saving PCA to ",filename)
outputDict = dict()
#------------------------------------------
outputDict["numberOfSamplesFittedOn"]= str(self.numberOfSamplesFittedOn)
outputDict["expectedInputs"] = str(self.expectedInputs)
outputDict["mean"] = str(self.mean)
outputDict["std"] = str(self.std)
outputDict["eigenvalues"] = list()
outputDict["eigenvectors"] = list()
outputDict["scree_proportion"] = list()
outputDict["scree_cumulative"] = list()
#------------------------------------------
for v in range(0,len(self.proportional)):
outputDict["scree_proportion"].append(str(self.proportional[v]))
outputDict["scree_cumulative"].append(str(self.cumulative[v]))
#------------------------------------------
print("eigenvalues ",self.eigenvalues.shape[0])
for v in range(0,self.eigenvalues.shape[0]):
outputDict["eigenvalues"].append(str(self.eigenvalues[v]))
#------------------------------------------
print("eigenvectors ",self.eigenvectors.shape[0]," x ",self.eigenvectors.shape[1])
for r in range(0,self.eigenvectors.shape[0]):
thisRow = list()
for c in range(0,self.eigenvectors.shape[1]):
thisRow.append(str(self.eigenvectors[r,c]))
outputDict["eigenvectors"].append(thisRow)
#------------------------------------------
import json
json_obj = json.dumps(outputDict)
file = open(filename,'w',encoding="utf-8")
file.write(json_obj)
file.close()
def load(self,filename):
print("Loading PCA from ",filename)
import json
file = open(filename,'r',encoding="utf-8")
data = json.load(file)
#-----------------------------------------------------
self.numberOfSamplesFittedOn = int(data["numberOfSamplesFittedOn"])
self.expectedInputs = int(data["expectedInputs"])
self.mean = float(data["mean"])
self.std = float(data["std"])
#-----------------------------------------------------
numberOfEigenValues = len(data["eigenvalues"])
print("Eigen values = ",numberOfEigenValues)
self.eigenvalues = np.full([numberOfEigenValues],fill_value=0,dtype=np.complex_,order='C')
for i in range(0,numberOfEigenValues):
self.eigenvalues[i] = complex(data["eigenvalues"][i])
#-----------------------------------------------------
numberOfEigenVectors = len(data["eigenvectors"])
print("Eigen vectors = ",numberOfEigenVectors)
self.eigenvectors = np.full([numberOfEigenVectors,numberOfEigenVectors],fill_value=0,dtype=np.complex_,order='C')
for r in range(0,numberOfEigenVectors):
for c in range(0,numberOfEigenVectors):
self.eigenvectors[r,c] = complex(data["eigenvectors"][r][c])
#-----------------------------------------------------
file.close()
return self.mean,self.std,self.eigenvalues,self.eigenvectors
def visualize(self,data,saveToFile="",onlyScreePlotNDimensions=0,label="PCA",colors=list(),colorLabel="Highlighting PC-4",viewAzimuth=45,viewElevation=45,showScree=1):
import matplotlib.pyplot as plt
font = {'family' : 'normal',
'weight' : 'bold',
'size' : 28}
plt.rc('font', **font)
plt.rc('xtick', labelsize=15)
plt.rc('ytick', labelsize=15)
# === Plot =========================================================================
fig = plt.figure()
fig.set_size_inches(19.2, 10.8, forward=True)
if (showScree==1):
ax2 = fig.add_subplot(1, 2, 1)
ax1 = fig.add_subplot(1, 2, 2,projection='3d')
else:
ax1 = fig.add_subplot(1, 1, 1,projection='3d')
#===================================================================================
#Number of PCA components to plot on first plot (our plot is 3D so max is 4 if we dont have a color ..! )
keepNDimensions = 3
if (len(colors)==0):
keepNDimensions = 4
#Do transform of our input using the PCA dimensions as new basis
#===================================================================================
transformedData = self.transform(data,selectedPCADimensions=keepNDimensions).real
#===================================================================================
if (len(colors)==0):
colors = transformedData[:,3]
colorLabel = "highlighting PC-4"
else:
print("Using provided set of colorValues")
keepNDimensions = 3
#If there is no limit on Scree plot dimensions then plot all
if (onlyScreePlotNDimensions==0):
onlyScreePlotNDimensions = len(eigenvalues)
#===================================================================================
plottedEigenValues = self.eigenvalues
plottedEigenValues=list()
for i in range(0,onlyScreePlotNDimensions):
plottedEigenValues.append(self.eigenvalues[i])
#===================================================================================
#1. Calculate the proportion of variance explained by each feature
sum_eigenvalues = np.sum(plottedEigenValues)
prop_var = [i/sum_eigenvalues for i in plottedEigenValues]
#2. Calculate the cumulative variance
cum_var = [np.sum(prop_var[:i+1]) for i in range(len(prop_var))]
#===================================================================================
ax1.view_init(viewAzimuth,viewElevation)
#===================================================================================
ax1.scatter(transformedData[:,0],transformedData[:,1],transformedData[:,2],c=colors)
#===================================================================================
# Adding title, xlabel and ylabel
ax1.set_title('PCA %s %s '%(label,colorLabel)) # Title of the plot
ax1.set_xlabel('PC-1 (%0.2f %%) '% (100.0*float(prop_var[0])),labelpad=30) # X-Label
ax1.set_ylabel('PC-2 (%0.2f %%) '% (100.0*float(prop_var[1])),labelpad=30) # Y-Label
ax1.set_zlabel('PC-3 (%0.2f %%) '% (100.0*float(prop_var[2])),labelpad=30) # Z-Label
#ax1.tick_params(axis='x', pad=5) #fine tune numbers of plot
#===================================================================================
#===================================================================================
#===================================================================================
if (showScree==1):
# Plot scree plot from PCA
x_labels = ['PC{}'.format(i+1) for i in range(len(prop_var))]
ax2.plot(x_labels, prop_var, marker='o', markersize=6, color='skyblue', linewidth=2, label='Proportion of variance')
ax2.plot(x_labels, cum_var, marker='o', color='orange', linewidth=2, label="Cumulative variance")
ax2.legend()
ax2.set_title('Scree plot %s '%label)
ax2.set_xlabel('Principal components')
ax2.set_ylabel('Proportion of variance')
#===================================================================================
#===================================================================================
#===================================================================================
plt.subplots_adjust(left=0.05, right=0.95, top=0.95, bottom=0.08)
if (saveToFile!=""):
fig.savefig(saveToFile)
else:
plt.show()
if __name__ == '__main__':
pca = PCA(savedFile="../../../../dataset/combinedModel/mocapnet4/mode1/1.0/step1_upperbody_all/upperbody_all.pca")
inptR = [1.0] * 458
inpt =np.asarray(inptR,dtype=np.float32)
outLength = 210
out = pca.transform(inpt,selectedPCADimensions=outLength)
for i in range(0,outLength):
print("%u = %0.6f" % (i,out[i]))
@@ -0,0 +1,46 @@
#ifndef MOCAPNET_CONFIGURATION_H_INCLUDED
#define MOCAPNET_CONFIGURATION_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
//Neural network orientations centered around 0
#define NN_ORIENTATIONS_TRAINED_AROUND_ZERO_AND_REQUIRE_TRICK 0
//Also swap bvh rotations before IK step
#define APPLY_BVH_FIX_TO_IK_INPUT 0
//Test swapped
#define SWAP_LEFT_RIGHT_ENSEMBLES 0
//Hands mode ( 1 / 3 (deprecated) / 5 )
#define HANDS_MODE 1
//Use flip for RHand Regression..!
#define RHAND_FLIP 1
//Limits synced to scripts/createRandomizedDatset.sh
const float FRONT_MIN_ORIENTATION = -45.0;
const float FRONT_MAX_ORIENTATION = 45.0;
//--------------------------------
const float BACK_MIN_ORIENTATION = 135.0;
const float BACK_MAX_ORIENTATION = 225.0;
const float BACK_ALT_MIN_ORIENTATION = -225;
const float BACK_ALT_MAX_ORIENTATION = -135;
//--------------------------------
const float LEFT_MIN_ORIENTATION = -135.0;
const float LEFT_MAX_ORIENTATION = -45.0;
//--------------------------------
const float RIGHT_MIN_ORIENTATION = 45.0;
const float RIGHT_MAX_ORIENTATION = 135.0;
//--------------------------------
#ifdef __cplusplus
}
#endif
#endif // MOCAPNET_CONFIGURATION_H_INCLUDED
@@ -0,0 +1,61 @@
//MOCAPNET2 ------------------------------------
#include "../MocapNETLib4/mocapnet4.h"
//----------------------------------------------
#include "../MocapNETLib4/config.h"
#include "../MocapNETLib4/JSON/readModelConfiguration.h"
//----------------------------------------------
#include "tools.h"
#include "../../../dependencies/nxjson/nxjson.h"
#include <stdio.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 */
int loadMocapNET4(
struct MocapNET4 * mnet,
const char * description
)
{
unsigned int length = 0;
char * data = readFileToMemory("dataset/combinedModel/mocapnet4/mode1/1.0/step1_upperbody_all",&length);
struct ModelConfigurationData modelConfiguration={0};
loadModelConfigurationData(&modelConfiguration,"dataset/combinedModel/mocapnet4/mode1/1.0/step1_upperbody_all/upperbody_configuration.json");
return 0;
}
std::vector<float> runMocapNET4(
struct MocapNET4 * mnet,
struct skeletonSerialized * input,
int doLowerbody,
int doHands,
int doFace,
int doGestureDetection,
unsigned int useInverseKinematics,
int doOutputFiltering
)
{
std::vector<float> emptyResult;
return emptyResult;
}
int unloadMocapNET4(struct MocapNET4 * mnet)
{
return 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,86 @@
/** @file tools.h
* @brief Various Tools!
* @author Ammar Qammaz (AmmarkoV)
*/
#ifndef MNET4_TOOLS_H_INCLUDED
#define MNET4_TOOLS_H_INCLUDED
#ifdef __cplusplus
extern "C"
{
#endif
#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 <stdio.h>
#include <string.h>
static char * readFileToMemory(const char * filename,unsigned int *length)
{
if (filename==0)
{
fprintf(stderr,RED "No Path Given to readFileToMemory\n" NORMAL);
return 0;
}
*length = 0;
FILE * pFile = fopen ( filename , "rb" );
if (pFile==0)
{
fprintf(stderr,RED "readFileToMemory failed\n" NORMAL);
fprintf(stderr,RED "Could not read file %s \n" NORMAL,filename);
return 0;
}
// obtain file size:
fseek (pFile , 0 , SEEK_END);
unsigned long lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
unsigned long bufferSize = sizeof(char)*(lSize+1);
char * buffer = (char*) malloc (bufferSize);
if (buffer == 0 )
{
fprintf(stderr,RED "Could not allocate enough memory for file %s \n" NORMAL,filename);
fclose(pFile);
return 0;
}
// copy the file into the buffer:
size_t result = fread (buffer,1,lSize,pFile);
if (result != lSize)
{
free(buffer);
fprintf(stderr,RED "Could not read the whole file onto memory %s \n" NORMAL,filename);
fclose(pFile);
return 0;
}
/* the whole file is now loaded in the memory buffer. */
// terminate
fclose (pFile);
buffer[lSize]=0; //Null Terminate Buffer!
*length = (unsigned int) lSize;
return buffer;
}
#ifdef __cplusplus
}
#endif
#endif