mirror of
https://github.com/storytold/storyteller-ml.git
synced 2026-10-15 00:03:06 +00:00
Add MocapNET
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user