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( BVHGUI2 )
|
||||
cmake_minimum_required( VERSION 2.8.13 )
|
||||
#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})
|
||||
|
||||
|
||||
add_executable(BVHGUI2 bvhGUI2.cpp
|
||||
${BVH_SOURCE} )
|
||||
|
||||
target_link_libraries(BVHGUI2 rt dl m ${OpenCV_LIBRARIES} ${OPENGL_LIBS} Tensorflow TensorflowFramework MocapNETLib2 )
|
||||
set_target_properties(BVHGUI2 PROPERTIES DEBUG_POSTFIX "D")
|
||||
|
||||
|
||||
set_target_properties(BVHGUI2 PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,554 @@
|
||||
#include "opencv2/opencv.hpp"
|
||||
/** @file bvhgui.cpp
|
||||
* @brief This is a simple test file to play with the BVH armature
|
||||
* #Hands up
|
||||
* // ./BVHGUI --set 241 290.0 --set 242 80 --set 284 117 --set 283 113
|
||||
* #Close up hands / face
|
||||
* // ./BVHGUI --set 1 -70 --set 2 -60 --set 241 290.0 --set 242 80 --set 282 187 --set 283 252 --set 284 112
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "../MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../MocapNETLib2/IO/bvh.hpp"
|
||||
#include "../MocapNETLib2/visualization/visualization.hpp"
|
||||
#include "../MocapNETLib2/visualization/opengl.hpp"
|
||||
#include <vector>
|
||||
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/bvh_loader.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_rename.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 */
|
||||
|
||||
|
||||
using namespace cv;
|
||||
|
||||
int visualizeOpenGLEnabled=0;
|
||||
|
||||
struct applicationState
|
||||
{
|
||||
std::vector<float>bvhConfiguration;
|
||||
std::vector<std::vector<float> > bvh2DPoints;
|
||||
unsigned int numberOfBVHMotionValuesPerFrame;
|
||||
int previousDistance;
|
||||
int distance;
|
||||
int positiveRotation;
|
||||
int negativeRotation;
|
||||
int previousPositiveRotation;
|
||||
int previousNegativeRotation;
|
||||
int rotation;
|
||||
int selectedMotionChannel,previousSelection;
|
||||
int visualizationType,previousVisualizationType;
|
||||
int play;
|
||||
int stop;
|
||||
int save;
|
||||
int copyClipboard;
|
||||
int frameID;
|
||||
int numberOfFrames;
|
||||
int redraw;
|
||||
};
|
||||
|
||||
|
||||
int controls(cv::Mat & controlMat,struct applicationState * state)
|
||||
{
|
||||
cv::imshow("3D Control",controlMat);
|
||||
cv::createTrackbar("Stop Demo", "3D Control", &state->stop, 1);
|
||||
|
||||
cv::createTrackbar("Play", "3D Control", &state->play,1);
|
||||
cv::createTrackbar("Frame", "3D Control", &state->frameID,state->numberOfFrames);
|
||||
cv::createTrackbar("Clipboard Pose", "3D Control", &state->copyClipboard, 1);
|
||||
|
||||
if (visualizeOpenGLEnabled)
|
||||
{
|
||||
cv::createTrackbar("Visualization Type", "3D Control", &state->visualizationType, 1);
|
||||
}
|
||||
|
||||
cv::createTrackbar("Save", "3D Control", &state->save, 1);
|
||||
|
||||
cv::createTrackbar("Distance ", "3D Control", &state->distance, 1360);
|
||||
|
||||
cv::createTrackbar("Selected Motion Channel", "3D Control", &state->selectedMotionChannel, state->numberOfBVHMotionValuesPerFrame-1);
|
||||
cv::createTrackbar("Positive Value ", "3D Control", &state->positiveRotation, 360);
|
||||
cv::createTrackbar("Negative Value ", "3D Control", &state->negativeRotation, 360);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void onMouse( int event, int x, int y, int, void* stateUncast)
|
||||
{
|
||||
struct applicationState * state = (struct applicationState *) stateUncast;
|
||||
if( event != EVENT_LBUTTONDOWN )
|
||||
return;
|
||||
|
||||
if (visualizeOpenGLEnabled)
|
||||
{
|
||||
clickOpenGLView(x,y,event);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Unhandled click @ %u,%u \n",x,y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int visWidth=1920;
|
||||
unsigned int visHeight=1080;
|
||||
|
||||
struct applicationState state;
|
||||
state.numberOfBVHMotionValuesPerFrame=MOCAPNET_OUTPUT_NUMBER;
|
||||
state.rotation=0;
|
||||
state.previousDistance=0;
|
||||
state.distance=150;
|
||||
state.numberOfFrames=1;
|
||||
state.previousSelection=0;
|
||||
state.selectedMotionChannel=0;
|
||||
state.visualizationType=0;
|
||||
state.stop=0;
|
||||
state.save=0;
|
||||
state.copyClipboard=0;
|
||||
state.previousVisualizationType=2;// <- force redraw on first loop
|
||||
state.redraw=1;
|
||||
|
||||
int useBVH=0;
|
||||
int forcePosition=1; //By default we want the output to be centered..
|
||||
int forceRotation=0;
|
||||
float forcedRotation=0;
|
||||
|
||||
const char * bvhFilename=0;
|
||||
|
||||
struct BVH_MotionCapture bvhMotion= {0};
|
||||
|
||||
|
||||
for (int i=0; i<argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--distance")==0)
|
||||
{
|
||||
if(argc>i+1)
|
||||
{
|
||||
state.distance=atoi(argv[i+1]);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--size")==0)
|
||||
{
|
||||
if(argc>i+2)
|
||||
{
|
||||
visWidth=atoi(argv[i+1]);
|
||||
visHeight=atoi(argv[i+2]);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--unconstrained")==0)
|
||||
{
|
||||
forcePosition=0;
|
||||
forceRotation=0;
|
||||
}
|
||||
else if (strcmp(argv[i],"--rotation")==0)
|
||||
{
|
||||
if(argc>i+1)
|
||||
{
|
||||
forceRotation=1;
|
||||
forcedRotation=atof(argv[i+1]);
|
||||
state.selectedMotionChannel=4;
|
||||
state.rotation=atoi(argv[i+1]);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--from")==0)
|
||||
{
|
||||
if(argc>i+1)
|
||||
{
|
||||
if ( bvh_loadBVH(argv[i+1], &bvhMotion, 1.0) )
|
||||
{
|
||||
bvhFilename=argv[i+1];
|
||||
bvh_renameJointsForCompatibility(&bvhMotion);
|
||||
state.frameID=0;
|
||||
state.numberOfFrames=bvhMotion.numberOfFrames;
|
||||
state.play=1;
|
||||
state.numberOfBVHMotionValuesPerFrame=bvhMotion.numberOfValuesPerFrame;
|
||||
useBVH=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"File `%s` does not exist\n",argv[i+1]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (strcmp(argv[i],"--opengl")==0)
|
||||
{
|
||||
visualizeOpenGLEnabled=1;
|
||||
state.visualizationType=1;
|
||||
state.previousVisualizationType=state.visualizationType;
|
||||
state.redraw=3; //Draw 3 consequtive frames to take care of OGL initialization
|
||||
state.previousSelection=6;
|
||||
state.selectedMotionChannel=6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( !initializeBVHConverter(bvhFilename,visWidth,visHeight,1) )
|
||||
{
|
||||
fprintf(stderr,"Failed to initialize BVH code from %s ..\n",bvhFilename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (getBVHNumberOfValuesPerFrame() != state.numberOfBVHMotionValuesPerFrame)
|
||||
{
|
||||
fprintf(stderr,"Inconsistency, internal BVH state reports different number of frames compared to external BVH state..\n");
|
||||
fprintf(stderr,"Internal(%u) External(%u) ..\n",getBVHNumberOfValuesPerFrame(),state.numberOfBVHMotionValuesPerFrame);
|
||||
fprintf(stderr,"Cannot continue ..\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
state.bvhConfiguration.clear();
|
||||
for (int i=0; i<state.numberOfBVHMotionValuesPerFrame; i++)
|
||||
{
|
||||
state.bvhConfiguration.push_back(0.0);
|
||||
}
|
||||
state.bvhConfiguration[2]=(float) -1 * state.distance;
|
||||
|
||||
fprintf(stderr,"Our bvh configuration will be held in vectors of %lu elements\n",state.bvhConfiguration.size());
|
||||
|
||||
fprintf(stderr,"Initializing OpenCV Visualization code ... ");
|
||||
cv::Mat viewMat = Mat(Size(visWidth,visHeight),CV_8UC3, Scalar(0,0,0));
|
||||
cv::imshow("BVH", viewMat);
|
||||
cv::moveWindow("BVH",300,0);
|
||||
setMouseCallback("BVH", onMouse, (void*) &state );
|
||||
|
||||
|
||||
cv::Mat controlMat = Mat(Size(300,1),CV_8UC3, Scalar(0,0,0));
|
||||
controls(controlMat,&state);
|
||||
cv::moveWindow("3D Control",0,0); //y=inputHeight2DJointDetector
|
||||
|
||||
fprintf(stderr,"ok!\n");
|
||||
|
||||
|
||||
for (int i=0; i<argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--changeJointDimensions")==0)
|
||||
{
|
||||
if(argc>i+7)
|
||||
{
|
||||
changeJointDimensions(
|
||||
atof(argv[i+1]),
|
||||
atof(argv[i+2]),
|
||||
atof(argv[i+3]),
|
||||
atof(argv[i+4]),
|
||||
atof(argv[i+5]),
|
||||
atof(argv[i+6]),
|
||||
atof(argv[i+7]),
|
||||
atof(argv[i+8]),
|
||||
atof(argv[i+9])
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Incorrect number of parameters given..\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--set")==0)
|
||||
{
|
||||
// To focus only on head..
|
||||
//./BVHGUI2 --set 1 -65 --set 2 -25
|
||||
// In OpenGL mode
|
||||
//./BVHGUI2 --set 1 -14.8 --set 2 2 --opengl
|
||||
// To focus on RHand
|
||||
// ./BVHGUI2 --from dataset/rhand.bvh --set 2 -45 --set 3 -90 --set 5 -90
|
||||
if(argc>i+2)
|
||||
{
|
||||
unsigned int bvhMotionID = atoi(argv[i+1]);
|
||||
float bvhMotionValue = atof(argv[i+2]);
|
||||
|
||||
unsigned int maximumValidMotionID = getBVHNumberOfValuesPerFrame();
|
||||
if (useBVH)
|
||||
{
|
||||
maximumValidMotionID = bvhMotion.jointHierarchySize;
|
||||
}
|
||||
|
||||
if (bvhMotionID<maximumValidMotionID)
|
||||
{
|
||||
char name[512]= {0};
|
||||
|
||||
|
||||
if (useBVH)
|
||||
{
|
||||
bvh_getMotionChannelName(&bvhMotion,bvhMotionID,name,512);
|
||||
bvhMotion.motionValues[bvhMotionID]=bvhMotionValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
getBVHMotionValueName(bvhMotionID,name,512);
|
||||
}
|
||||
|
||||
fprintf(stderr,YELLOW "joint[%s]=%0.2f\n" NORMAL,name,bvhMotionValue);
|
||||
state.bvhConfiguration[bvhMotionID]=bvhMotionValue;
|
||||
if (bvhMotionID==2)
|
||||
{
|
||||
state.distance=-1*bvhMotionValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Set command jID out of bounds ( requested %u , limit is %u )\n" NORMAL,bvhMotionID,maximumValidMotionID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Not enough arguments for set command\n" NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(!state.stop)
|
||||
{
|
||||
if (useBVH)
|
||||
{
|
||||
unsigned int mIDStart=state.frameID * bvhMotion.numberOfValuesPerFrame;
|
||||
|
||||
if (state.bvhConfiguration.size() != state.numberOfBVHMotionValuesPerFrame)
|
||||
{
|
||||
fprintf(stderr,"Inconsistency in number of vector allocated and motion values loaded..\n");
|
||||
}
|
||||
else if (bvhMotion.numberOfFrames * bvhMotion.numberOfValuesPerFrame != bvhMotion.motionValuesSize)
|
||||
{
|
||||
fprintf(stderr,"Inconsistency in number of frames and motion values..\n");
|
||||
}
|
||||
else if (mIDStart<bvhMotion.motionValuesSize)
|
||||
{
|
||||
for (unsigned int i=0; i<state.numberOfBVHMotionValuesPerFrame; i++)
|
||||
{
|
||||
state.bvhConfiguration[i]=bvhMotion.motionValues[(mIDStart+i)%bvhMotion.motionValuesSize];
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
if (forcePosition)
|
||||
{
|
||||
state.bvhConfiguration[0]=0;
|
||||
state.bvhConfiguration[1]=0;
|
||||
state.bvhConfiguration[2]=(float) -1 * state.distance;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
if (forceRotation)
|
||||
{
|
||||
state.bvhConfiguration[3]=0;
|
||||
state.bvhConfiguration[4]=forcedRotation;
|
||||
state.bvhConfiguration[5]=0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------
|
||||
if (!state.redraw)
|
||||
{
|
||||
state.redraw=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Frame %u exceeds allocated number of motion values\n",state.frameID);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.copyClipboard)
|
||||
{
|
||||
char valueStr[10];
|
||||
char motionVectorStringUnsafe[10000]={0};
|
||||
snprintf(motionVectorStringUnsafe,10000,"echo \"%0.2f",state.bvhConfiguration[0]);
|
||||
|
||||
for (unsigned int i=1; i<state.numberOfBVHMotionValuesPerFrame; i++)
|
||||
{
|
||||
snprintf(valueStr,10,",%0.2f",state.bvhConfiguration[i]);
|
||||
strcat(motionVectorStringUnsafe,valueStr);
|
||||
}
|
||||
strcat(motionVectorStringUnsafe,"\" | xclip -selection clipboard");
|
||||
int i=system(motionVectorStringUnsafe);
|
||||
if (i!=0)
|
||||
{
|
||||
fprintf(stderr,"Failed copying to clipboard.. :( \n");
|
||||
}
|
||||
state.copyClipboard=0;
|
||||
}
|
||||
|
||||
if (state.save)
|
||||
{
|
||||
std::vector<std::vector<float> > bvhFrames;
|
||||
bvhFrames.push_back(state.bvhConfiguration);
|
||||
state.save=0;
|
||||
controls(controlMat,&state);
|
||||
writeBVHFile(
|
||||
"out.bvh",
|
||||
bvhHeader,
|
||||
0,// int prependTPose,
|
||||
bvhFrames
|
||||
);
|
||||
fprintf(stderr,GREEN "Saved..\n" NORMAL);
|
||||
}
|
||||
|
||||
|
||||
if (state.previousDistance!=state.distance)
|
||||
{
|
||||
if (!state.redraw)
|
||||
{
|
||||
state.redraw=1;
|
||||
}
|
||||
state.previousDistance=state.distance;
|
||||
state.bvhConfiguration[2]=(float) -1 * state.distance;
|
||||
}
|
||||
|
||||
//if (!state.play)
|
||||
//{
|
||||
|
||||
if (state.visualizationType!=state.previousVisualizationType)
|
||||
{
|
||||
if (!state.redraw)
|
||||
{
|
||||
state.redraw=1;
|
||||
}
|
||||
state.previousVisualizationType=state.visualizationType;
|
||||
}
|
||||
|
||||
if (state.selectedMotionChannel!=state.previousSelection)
|
||||
{
|
||||
if (!state.redraw)
|
||||
{
|
||||
state.redraw=1;
|
||||
}
|
||||
state.previousSelection=state.selectedMotionChannel;
|
||||
state.rotation=state.bvhConfiguration[state.selectedMotionChannel];
|
||||
if (state.rotation<0)
|
||||
{
|
||||
state.negativeRotation=-1*state.rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.positiveRotation=state.rotation;
|
||||
}
|
||||
controls(controlMat,&state);
|
||||
}
|
||||
|
||||
|
||||
if (state.previousPositiveRotation!=state.positiveRotation)
|
||||
{
|
||||
state.previousPositiveRotation=state.positiveRotation;
|
||||
state.rotation=state.positiveRotation;
|
||||
}
|
||||
else if (state.previousNegativeRotation!=state.negativeRotation)
|
||||
{
|
||||
state.previousNegativeRotation=state.negativeRotation;
|
||||
state.rotation=-1* state.negativeRotation;
|
||||
}
|
||||
|
||||
if ( state.bvhConfiguration[state.selectedMotionChannel]!=state.rotation )
|
||||
{
|
||||
if (!state.redraw)
|
||||
{
|
||||
state.redraw=1;
|
||||
}
|
||||
state.bvhConfiguration[state.selectedMotionChannel]=state.rotation;
|
||||
if (state.rotation<0)
|
||||
{
|
||||
state.negativeRotation=-1*state.rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.positiveRotation=state.rotation;
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
if (state.redraw)
|
||||
{
|
||||
//fprintf(stderr,"redraw..\n");
|
||||
memset(viewMat.data,0,visWidth*visHeight*3*sizeof(char));
|
||||
|
||||
|
||||
//cv::Mat * openGLMatForVisualization = 0;
|
||||
if ( (visualizeOpenGLEnabled) && (state.visualizationType) )
|
||||
{
|
||||
//fprintf(stderr,"updateOpenGLView\n");
|
||||
updateOpenGLView(state.bvhConfiguration);
|
||||
|
||||
//fprintf(stderr,"visualizeOpenGL\n");
|
||||
unsigned int openGLFrameWidth=visWidth,openGLFrameHeight=visHeight;
|
||||
char * openGLFrame = visualizeOpenGL(&openGLFrameWidth,&openGLFrameHeight);
|
||||
//=====================================================================
|
||||
if (openGLFrame!=0)
|
||||
{
|
||||
fprintf(stderr,"Got Back an OpenGL frame..!\n");
|
||||
cv::Mat openGLMat(openGLFrameHeight, openGLFrameWidth, CV_8UC3);
|
||||
unsigned char * initialPointer = openGLMat.data;
|
||||
openGLMat.data=(unsigned char * ) openGLFrame;
|
||||
cv::cvtColor(openGLMat,viewMat,COLOR_RGB2BGR);
|
||||
openGLMat.data=initialPointer;
|
||||
}//=====================================================================
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Failed getting an OpenGL frame..!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state.bvhConfiguration.size()>0)
|
||||
{
|
||||
//fprintf(stderr,"Converting %lu bvh vector\n",state.bvhConfiguration.size());
|
||||
state.bvh2DPoints = convertBVHFrameTo2DPoints(state.bvhConfiguration);//visWidth,visHeight);
|
||||
|
||||
drawSkeleton(viewMat,state.bvh2DPoints,0,0,1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char message[1024];
|
||||
snprintf(message,1024,"Frame : %u / %u",state.frameID,state.numberOfFrames);
|
||||
cv::putText(viewMat,message, cv::Point(10,30), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar::all(255), 0.2, 8 );
|
||||
|
||||
|
||||
if (useBVH)
|
||||
{
|
||||
char motionChannelName[512];
|
||||
getBVHMotionValueName(state.selectedMotionChannel,motionChannelName,512);
|
||||
snprintf(message,1024,"Selected motion channel #%u : %s ( value %0.2f )",state.selectedMotionChannel,motionChannelName,state.bvhConfiguration[state.selectedMotionChannel]);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(message,1024,"Selected motion channel #%u : %s ( value %0.2f )",state.selectedMotionChannel,MocapNETOutputArrayNames[state.previousSelection],state.bvhConfiguration[state.selectedMotionChannel]);
|
||||
}
|
||||
cv::putText(viewMat,message, cv::Point(10,50), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar::all(255), 0.2, 8 );
|
||||
|
||||
if (visualizeOpenGLEnabled)
|
||||
{
|
||||
snprintf(message,1024,"OpenGL Model motion channel name : %s",OpenCOLLADANames[state.previousSelection/3]);
|
||||
cv::putText(viewMat,message, cv::Point(10,70), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar::all(255), 0.2, 8 );
|
||||
}
|
||||
|
||||
if (state.redraw>=1)
|
||||
{
|
||||
--state.redraw;
|
||||
}
|
||||
//state.redraw=0;
|
||||
}
|
||||
|
||||
|
||||
imshow("BVH", viewMat);
|
||||
|
||||
waitKey(15);
|
||||
|
||||
if (useBVH)
|
||||
{
|
||||
if (state.play)
|
||||
{
|
||||
++state.frameID;
|
||||
state.frameID = state.frameID % state.numberOfFrames;
|
||||
}
|
||||
}
|
||||
}
|
||||
// the camera will be deinitialized automatically in VideoCapture destructor
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
project( BVHTemplate )
|
||||
cmake_minimum_required( VERSION 2.8.7 )
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules ${CMAKE_MODULE_PATH})
|
||||
|
||||
|
||||
add_executable(BVHTemplate main.c ${BVH_SOURCE} )
|
||||
|
||||
target_link_libraries(BVHTemplate rt m pthread )
|
||||
#add_dependencies(BVHTemplate OGLRendererSandbox)
|
||||
|
||||
|
||||
set_target_properties(BVHTemplate PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
@@ -0,0 +1,29 @@
|
||||
project( CSVClusterPlot )
|
||||
cmake_minimum_required( VERSION 2.8.13 )
|
||||
#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})
|
||||
|
||||
|
||||
add_executable(
|
||||
CSVClusterPlot
|
||||
csvClusterPlot.cpp
|
||||
perform2DClustering.cpp
|
||||
perform3DClustering.cpp
|
||||
${BVH_SOURCE}
|
||||
)
|
||||
|
||||
target_link_libraries(CSVClusterPlot rt dl m ${OpenCV_LIBRARIES} ${OPENGL_LIBS} Tensorflow TensorflowFramework MocapNETLib2 )
|
||||
#set_target_properties(CSVClusterPlot PROPERTIES DEBUG_POSTFIX "D")
|
||||
|
||||
|
||||
set_target_properties(CSVClusterPlot PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,759 @@
|
||||
#include "opencv2/opencv.hpp"
|
||||
/** @file csvClusterPlot.cpp
|
||||
* @brief
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/stat.h> //mkdir
|
||||
#include "../MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../MocapNETLib2/IO/bvh.hpp"
|
||||
#include "../MocapNETLib2/visualization/visualization.hpp"
|
||||
#include "../MocapNETLib2/visualization/opengl.hpp"
|
||||
#include "../MocapNETLib2/IO/csvRead.hpp"
|
||||
#include <vector>
|
||||
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/bvh_loader.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_filter.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_rename.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_randomize.h"
|
||||
|
||||
#include "perform2DClustering.hpp"
|
||||
#include "perform3DClustering.hpp"
|
||||
|
||||
|
||||
//#include <stdint.h>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
int visualizeOpenGLEnabled=0;
|
||||
|
||||
|
||||
#define BOOST_CONTRAST 2.0
|
||||
|
||||
|
||||
|
||||
char MocapNET1List[]="src/MocapNET2/CSVClusterPlot/listOfFilesToClusterMocapNET1";
|
||||
char defaultList[]="src/MocapNET2/CSVClusterPlot/listOfFilesToCluster";
|
||||
|
||||
|
||||
const char * perturbList1[] =
|
||||
{
|
||||
" ",
|
||||
"rshoulder",
|
||||
"lshoulder",
|
||||
"rhip",
|
||||
"lhip"
|
||||
};
|
||||
|
||||
const char * perturbList2[] =
|
||||
{
|
||||
" ",
|
||||
"rhand",
|
||||
"relbow",
|
||||
"lelbow",
|
||||
"lhand",
|
||||
"lknee",
|
||||
"rknee",
|
||||
"lfoot",
|
||||
"rfoot"
|
||||
};
|
||||
|
||||
|
||||
const char * perturbList3[] =
|
||||
{
|
||||
" ",
|
||||
"abdomen",
|
||||
"chest"
|
||||
};
|
||||
|
||||
/*
|
||||
#define rotationSetting 0"
|
||||
#define handToCloseHipMin "45"
|
||||
#define handToCloseHipMax "90"
|
||||
#define handToFarHipMin "100"
|
||||
#define handToFarHipMax "160"
|
||||
#define handToHandMin "150"
|
||||
#define handToHandMax "250"
|
||||
*/
|
||||
|
||||
|
||||
#define rotationSetting "90"
|
||||
#define handToCloseHipMin "0"
|
||||
#define handToCloseHipMax "120"
|
||||
#define handToFarHipMin "0"
|
||||
#define handToFarHipMax "120"
|
||||
#define handToHandMin "0"
|
||||
#define handToHandMax "150"
|
||||
|
||||
|
||||
const char * removeNeutralPosesRules[] =
|
||||
{
|
||||
"0", // 0 | Move Armature to 0 X Position
|
||||
"0", // 1 | Move Armature to 0 Y Position
|
||||
"-130.0", // 2 | Move Armature to -130.0 Z Position
|
||||
"0", // 3 | Rotate Armature to 0deg X Rotation
|
||||
rotationSetting, // 4 | Rotate Armature to 0deg Y Rotation
|
||||
"0", // 5 | Rotate Armature to 0deg Z Rotation
|
||||
//--------------------------------------------------------------------------
|
||||
"1920", // 6 | Virtual 2D Rendering Width
|
||||
"1080",// 7 | Virtual 2D Rendering Height
|
||||
"570.7", // 8 | Virtual 2D Rendering Focal Length X
|
||||
"570.3", // 9 | Virtual 2D Rendering Focal Length Y
|
||||
//--------------------------------------------------------------------------
|
||||
"6", // 10 | Number of joint rules
|
||||
//--------------------------------------------------------------------------
|
||||
"rhand", // 11 | Joint A
|
||||
"lhip", // 12 | Joint B
|
||||
handToFarHipMin, // 13 | Minimum Acceptable 2D Distance
|
||||
handToFarHipMax, // 14 | Maximum Acceptable 2D Distance
|
||||
"rhand", // 15 | Joint A
|
||||
"rhip", // 16| Joint B
|
||||
handToCloseHipMin, // 17 | Minimum Acceptable 2D Distance
|
||||
handToCloseHipMax, // 18 | Maximum Acceptable 2D Distance
|
||||
"rhand", // 19 | Joint A
|
||||
"lhand", // 20 | Joint B
|
||||
handToHandMin, // 21 | Minimum Acceptable 2D Distance
|
||||
handToHandMax, // 22 | Maximum Acceptable 2D Distance
|
||||
//--------------------------------------------------------------------------
|
||||
"lhand", // 23 | Joint A
|
||||
"rhip", // 24| Joint B
|
||||
handToFarHipMin, // 25 | Minimum Acceptable 2D Distance
|
||||
handToFarHipMax, // 26 | Maximum Acceptable 2D Distance
|
||||
"lhand", // 27 | Joint A
|
||||
"lhip", // 28| Joint B
|
||||
handToCloseHipMin, // 29 | Minimum Acceptable 2D Distance
|
||||
handToCloseHipMax, // 30 | Maximum Acceptable 2D Distance
|
||||
"lhand", // 31 | Joint A
|
||||
"rhand", // 32 | Joint B
|
||||
handToHandMin, // 33 | Minimum Acceptable 2D Distance
|
||||
handToHandMax // 34 | Maximum Acceptable 2D Distance
|
||||
};
|
||||
|
||||
|
||||
void convertHeatmapValueToRGB(float heatmap,unsigned char * R,unsigned char * G,unsigned char * B)
|
||||
{
|
||||
float r = fminf(1.0f, (fmaxf(0.5f, heatmap) - 0.5f) * 6.0f);
|
||||
float g = fminf(1.0f, heatmap * 3.0f) - fminf(1.0f, fmaxf(0.0f, heatmap - 0.666f) * 3.0f);
|
||||
float b = fmaxf(0.0f, 1.0f - fmaxf(0.0f, heatmap - 0.333f) * 6.0f);
|
||||
|
||||
if (heatmap==0.0)
|
||||
{
|
||||
r=0.0;
|
||||
g=0.0;
|
||||
b=0.0;
|
||||
}
|
||||
else if (heatmap<0.1)
|
||||
{
|
||||
r=0.0;
|
||||
g=0.0;
|
||||
b=0.3+10*heatmap;
|
||||
if (b>=1.0)
|
||||
{
|
||||
b=1.0;
|
||||
}
|
||||
}
|
||||
else if (heatmap>=1.0) //Cap
|
||||
{
|
||||
if (heatmap>=2.0)
|
||||
{
|
||||
r=1.0;
|
||||
g=0.0;
|
||||
b=1.0; //Final Limit
|
||||
}
|
||||
else
|
||||
{
|
||||
r=1.0 ;
|
||||
g=0.0;
|
||||
b=heatmap-1.0;
|
||||
}
|
||||
}
|
||||
|
||||
r=r*255.0;
|
||||
g=g*255.0;
|
||||
b=b*255.0;
|
||||
|
||||
*R = (unsigned char) r;
|
||||
*G = (unsigned char) g;
|
||||
*B = (unsigned char) b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int draw2DClustering(cv::Mat &viewMat,struct BVH_MotionCapture * bvhMotion,std::vector<std::vector<float> > aPose,struct applicationState * state,const char * line, char * videoPath,unsigned int width,unsigned int height)
|
||||
{
|
||||
char buffer[1024]= {0};
|
||||
memset(viewMat.data,0,width*height*3*sizeof(char));
|
||||
/*
|
||||
if ( state->maxAccumulatedSample > state->accumulatedSamples )
|
||||
{
|
||||
state->maxAccumulatedSample=state->accumulatedSamples;
|
||||
}*/
|
||||
|
||||
unsigned char R,G,B;
|
||||
//------------------------------------------------------------------------------
|
||||
for (int y=0; y<height; y++)
|
||||
{
|
||||
for (int x=0; x<width; x++)
|
||||
{
|
||||
float heatmap = (float) state->accumulatedImage[y*width+x] / state->maxAccumulatedSample;
|
||||
heatmap*=BOOST_CONTRAST;
|
||||
|
||||
convertHeatmapValueToRGB(heatmap,&R,&G,&B);
|
||||
|
||||
unsigned int pos=(y*width*3) + x*3;
|
||||
viewMat.data[pos++]=B;
|
||||
viewMat.data[pos++]=G;
|
||||
viewMat.data[pos]=R;
|
||||
}
|
||||
|
||||
|
||||
//add a sidebar with the colors legend..
|
||||
for (int x=width-5; x<width; x++)
|
||||
{
|
||||
float heatmapScaleValue = 1.0 - ((float) y / height);
|
||||
heatmapScaleValue*=BOOST_CONTRAST; //;
|
||||
|
||||
convertHeatmapValueToRGB(heatmapScaleValue,&R,&G,&B);
|
||||
|
||||
unsigned int pos=(y*width*3) + x*3;
|
||||
viewMat.data[pos++]=B;
|
||||
viewMat.data[pos++]=G;
|
||||
viewMat.data[pos]=R;
|
||||
}
|
||||
|
||||
|
||||
if (y%50==0)
|
||||
{
|
||||
float heatmapScaleValue = 1.0 - ((float) y / height);
|
||||
heatmapScaleValue*=state->maxAccumulatedSample;
|
||||
snprintf(buffer,1024,"%0.0f",heatmapScaleValue);
|
||||
cv::putText(viewMat,buffer, cv::Point(width-50,y), cv::FONT_HERSHEY_DUPLEX, 0.3, cv::Scalar::all(255), 0.2, 8 );
|
||||
}
|
||||
}
|
||||
|
||||
drawSkeleton(viewMat,aPose,0,0,1);
|
||||
|
||||
snprintf(buffer,1024,"%lu accumulated samples, max heatmap value = %lu",state->accumulatedSamples,state->maxAccumulatedSample);
|
||||
cv::putText(viewMat,buffer, cv::Point(10,30), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar::all(255), 0.2, 8 );
|
||||
|
||||
snprintf(buffer,1024,"%s added with %u samples",line,bvhMotion->numberOfFrames);
|
||||
cv::putText(viewMat,buffer, cv::Point(10,50), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar::all(255), 0.2, 8 );
|
||||
|
||||
if (videoPath!=0)
|
||||
{
|
||||
snprintf(buffer,1024,"Label : %s ",videoPath);
|
||||
cv::putText(viewMat,buffer, cv::Point(10,70), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar::all(255), 0.2, 8 );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int draw3DClustering(cv::Mat &viewMat,struct clusteringOf3DPoses * state,unsigned int width,unsigned int height,unsigned int depth)
|
||||
{
|
||||
memset(viewMat.data,0,width*height*3*sizeof(char));
|
||||
|
||||
unsigned char R,G,B;
|
||||
//------------------------------------------------------------------------------
|
||||
for (int y=0; y<height; y++)
|
||||
{
|
||||
for (int x=0; x<width; x++)
|
||||
{
|
||||
unsigned int hits=0;
|
||||
for (int z=0; z<depth; z++)
|
||||
{
|
||||
unsigned long memoryLocation = (unsigned long) (z*width*height) + (y*width)+ x;
|
||||
|
||||
hits+=state->space[memoryLocation].element;
|
||||
}
|
||||
float heatmap = (float) hits / (depth*255);
|
||||
heatmap*=10;
|
||||
|
||||
convertHeatmapValueToRGB(heatmap,&R,&G,&B);
|
||||
|
||||
unsigned int pos=(y*width*3) + x*3;
|
||||
viewMat.data[pos++]=B;
|
||||
viewMat.data[pos++]=G;
|
||||
viewMat.data[pos]=R;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct clusteringOf3DPoses * state3D = (struct clusteringOf3DPoses *) malloc(sizeof(struct clusteringOf3DPoses) );
|
||||
if (state3D==0)
|
||||
{
|
||||
fprintf(stderr,"Could not allocate enough memory to start csvClusterPlot..\n");
|
||||
return 1;
|
||||
}
|
||||
memset(state3D,0,sizeof(struct clusteringOf3DPoses));
|
||||
|
||||
|
||||
struct applicationState * state = (struct applicationState *) malloc(sizeof(struct applicationState) );
|
||||
if (state==0)
|
||||
{
|
||||
fprintf(stderr,"Could not allocate enough memory to start csvClusterPlot..\n");
|
||||
free(state3D);
|
||||
return 1;
|
||||
}
|
||||
state->rotation=0;
|
||||
state->previousSelection=0;
|
||||
state->selectedJoint=0;
|
||||
state->visualizationType=0;
|
||||
state->stop=0;
|
||||
state->save=0;
|
||||
state->previousVisualizationType=2;// <- force redraw on first loop
|
||||
state->redraw=1;
|
||||
state->maxAccumulatedSample= 0;
|
||||
int randomize=0;
|
||||
int filterPoses=0;
|
||||
int go3DMode=0;
|
||||
|
||||
unsigned int visualizationFrameNumber=0;
|
||||
int saveVideo=0;
|
||||
char * videoPath=0;
|
||||
char videoFrameFinalFilename[512]= {0};
|
||||
|
||||
float skeletonDistance=-160;
|
||||
unsigned int WIDTH = 1000;
|
||||
unsigned int HEIGHT = 1000;
|
||||
unsigned int DEPTH = 1000;
|
||||
char * selectedSource = defaultList;
|
||||
|
||||
for (int i=0; i<argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--mocapnet1")==0)
|
||||
{
|
||||
selectedSource=MocapNET1List;
|
||||
}
|
||||
else if (strcmp(argv[i],"--saveVideo")==0)
|
||||
{
|
||||
if(argc>i+1)
|
||||
{
|
||||
videoPath=argv[i+1];
|
||||
saveVideo=1;
|
||||
mkdir(videoPath,0777);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--from")==0)
|
||||
{
|
||||
if(argc>i+1)
|
||||
{
|
||||
selectedSource=argv[i+1];
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--rotation")==0)
|
||||
{
|
||||
if(argc>i+1)
|
||||
{
|
||||
state->rotation=atoi(argv[i+1]);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--randomize")==0)
|
||||
{
|
||||
randomize=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--filter")==0)
|
||||
{
|
||||
filterPoses=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--size")==0)
|
||||
{
|
||||
//To produce higher resolution heatmap..
|
||||
// ./CSVClusterPlot --rotation 90 --onlyrhand --size 1920 1080 --distance -130 --filter
|
||||
if(argc>i+2)
|
||||
{
|
||||
WIDTH=atoi(argv[i+1]);
|
||||
HEIGHT=atoi(argv[i+2]);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--depth")==0)
|
||||
{
|
||||
if(argc>i+1)
|
||||
{
|
||||
DEPTH=atoi(argv[i+1]);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--distance")==0)
|
||||
{
|
||||
if(argc>i+1)
|
||||
{
|
||||
skeletonDistance=atof(argv[i+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
state->accumulatedImage = (unsigned long * ) malloc( (WIDTH) * (HEIGHT) * sizeof (unsigned long) );
|
||||
if (state->accumulatedImage==0)
|
||||
{
|
||||
fprintf(stderr,"Could not allocate enough memory to start csvClusterPlot..\n");
|
||||
free(state);
|
||||
free(state3D);
|
||||
return 1;
|
||||
}
|
||||
for (int y=0; y<HEIGHT; y++)
|
||||
{
|
||||
for (int x=0; x<WIDTH; x++)
|
||||
{
|
||||
state->accumulatedImage[y*WIDTH+x]=0;
|
||||
}
|
||||
}
|
||||
state->accumulatedSamples=0;;
|
||||
|
||||
|
||||
cv::Mat viewMat = Mat(Size(WIDTH,HEIGHT),CV_8UC3, Scalar(0,0,0));
|
||||
namedWindow("BVH",1);
|
||||
//controls(controlMat,&state);
|
||||
//cv::moveWindow("3D Control",0,0); //y=inputHeight2DJointDetector
|
||||
cv::moveWindow("BVH",0,0);
|
||||
|
||||
|
||||
initializeBVHConverter(0,WIDTH,HEIGHT,1);
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
std::vector<char> activeJoints;
|
||||
activeJoints.clear();
|
||||
for (int i=0; i<MOCAPNET_OUTPUT_NUMBER; i++)
|
||||
{
|
||||
activeJoints.push_back(1);
|
||||
}
|
||||
activeJoints[ getBVHJointIDFromJointName("hip")]=0;
|
||||
activeJoints[ getBVHJointIDFromJointName("lThigh")]=0;
|
||||
activeJoints[ getBVHJointIDFromJointName("rThigh")]=0;
|
||||
activeJoints[ getBVHJointIDFromJointName("lButtock")]=0;
|
||||
activeJoints[ getBVHJointIDFromJointName("rButtock")]=0;
|
||||
activeJoints[ getBVHJointIDFromJointName("abdomen")]=0;
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
for (int i=0; i<argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--3d")==0)
|
||||
{
|
||||
//Sample use
|
||||
// ./CSVClusterPlot --3d rHand --size 500 500 --depth 500 --distance -250
|
||||
// ./CSVClusterPlot --3d rHand --size 256 256 --depth 256 --distance -500
|
||||
go3DMode=1;
|
||||
for (int z=0; z<MOCAPNET_OUTPUT_NUMBER; z++)
|
||||
{
|
||||
activeJoints[z]=0;
|
||||
}
|
||||
//activeJoints[ getBVHJointIDFromJointName("rForeArm")]=1;
|
||||
if(argc>i+1)
|
||||
{
|
||||
activeJoints[ getBVHJointIDFromJointName(argv[i+1])]=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"We need a limb to focus on e.g. rHand <- capitalization is imporant..\n");
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--onlylimbs")==0)
|
||||
{
|
||||
for (int z=0; z<MOCAPNET_OUTPUT_NUMBER; z++)
|
||||
{
|
||||
activeJoints[z]=0;
|
||||
}
|
||||
activeJoints[ getBVHJointIDFromJointName("rShin")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("rFoot")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("lShin")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("lFoot")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("neck")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("head")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("lForeArm")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("lHand")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("rForeArm")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("rHand")]=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--onlyrhand")==0)
|
||||
{
|
||||
for (int z=0; z<MOCAPNET_OUTPUT_NUMBER; z++)
|
||||
{
|
||||
activeJoints[z]=0;
|
||||
}
|
||||
activeJoints[ getBVHJointIDFromJointName("rForeArm")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("rHand")]=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--onlylhand")==0)
|
||||
{
|
||||
for (int z=0; z<MOCAPNET_OUTPUT_NUMBER; z++)
|
||||
{
|
||||
activeJoints[z]=0;
|
||||
}
|
||||
activeJoints[ getBVHJointIDFromJointName("lForeArm")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("lHand")]=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--onlyrleg")==0)
|
||||
{
|
||||
for (int z=0; z<MOCAPNET_OUTPUT_NUMBER; z++)
|
||||
{
|
||||
activeJoints[z]=0;
|
||||
}
|
||||
activeJoints[ getBVHJointIDFromJointName("rShin")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("rFoot")]=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--onlylleg")==0)
|
||||
{
|
||||
for (int z=0; z<MOCAPNET_OUTPUT_NUMBER; z++)
|
||||
{
|
||||
activeJoints[z]=0;
|
||||
}
|
||||
activeJoints[ getBVHJointIDFromJointName("lShin")]=1;
|
||||
activeJoints[ getBVHJointIDFromJointName("lFoot")]=1;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
state->redraw=1;
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
//find dataset/MotionCapture/ -type f -name "*.bvh" > src/MocapNET2/CSVClusterPlot/listOfFilesToCluster
|
||||
struct BVH_MotionCapture bvhMotion= {0};
|
||||
|
||||
char buffer[1024]= {0};
|
||||
|
||||
FILE * fp =0;
|
||||
|
||||
fp=fopen(selectedSource,"r");
|
||||
|
||||
if (fp==0)
|
||||
{
|
||||
fprintf(stderr,"Cannot open list of files to cluster\n");
|
||||
free(state->accumulatedImage);
|
||||
free(state);
|
||||
free(state3D);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
unsigned int numberOfLinesProcessed=0;
|
||||
unsigned long numberOfPosesLoaded=0;
|
||||
|
||||
while ((read = getline(&line, &len, fp)) != -1)
|
||||
{
|
||||
if (line!=0)
|
||||
{
|
||||
++numberOfLinesProcessed;
|
||||
//-----------------------------------------------------------------
|
||||
int lineLength=strlen(line);
|
||||
if (lineLength>0)
|
||||
{
|
||||
if (line[lineLength-1]==10)
|
||||
{
|
||||
line[lineLength-1]=0;
|
||||
}
|
||||
if (line[lineLength-1]==13)
|
||||
{
|
||||
line[lineLength-1]=0;
|
||||
}
|
||||
}
|
||||
if (lineLength>1)
|
||||
{
|
||||
if (line[lineLength-2]==10)
|
||||
{
|
||||
line[lineLength-2]=0;
|
||||
}
|
||||
if (line[lineLength-2]==13)
|
||||
{
|
||||
line[lineLength-2]=0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
fprintf(stderr,"Loading `%s`\n",line);
|
||||
|
||||
if ( bvh_loadBVH(line, &bvhMotion, 1.0) )
|
||||
{
|
||||
numberOfPosesLoaded+=bvhMotion.numberOfFrames;
|
||||
|
||||
bvh_renameJointsForCompatibility(&bvhMotion);
|
||||
|
||||
if (filterPoses)
|
||||
{
|
||||
filterOutPosesThatAreCloseToRules(&bvhMotion,35,removeNeutralPosesRules);
|
||||
}
|
||||
|
||||
if (randomize)
|
||||
{
|
||||
//--perturbJointAngles 4 38.0 rshoulder lshoulder rhip lhip --perturbJointAngles 8 10.0 rhand relbow lelbow lhand lknee rknee lfoot rfoot
|
||||
|
||||
bvh_PerturbJointAngles(
|
||||
&bvhMotion,
|
||||
4,
|
||||
38.0,
|
||||
perturbList1,
|
||||
0
|
||||
);
|
||||
|
||||
bvh_PerturbJointAngles(
|
||||
&bvhMotion,
|
||||
8,
|
||||
10.0,
|
||||
perturbList2,
|
||||
0
|
||||
);
|
||||
|
||||
bvh_PerturbJointAngles(
|
||||
&bvhMotion,
|
||||
2,
|
||||
10.0,
|
||||
perturbList3,
|
||||
0
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (go3DMode)
|
||||
{
|
||||
//3D Voxel Clustering Mode
|
||||
std::vector<std::vector<float> > aPose = collect3DPoses(state3D,activeJoints,&bvhMotion,skeletonDistance,WIDTH,HEIGHT,DEPTH);
|
||||
|
||||
//memset(viewMat.data,0,WIDTH*HEIGHT*3*sizeof(char));
|
||||
|
||||
if (numberOfLinesProcessed%5==0)
|
||||
{ draw3DClustering(viewMat,state3D,WIDTH,HEIGHT,DEPTH); }
|
||||
drawSkeleton(viewMat,aPose,0,0,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//2D Projection Mode
|
||||
std::vector<std::vector<float> > aPose = collectPoses(state,activeJoints,&bvhMotion,skeletonDistance,WIDTH,HEIGHT);
|
||||
if ( aPose.size()>0 )
|
||||
{
|
||||
state->redraw=1;
|
||||
}
|
||||
|
||||
if (state->redraw)
|
||||
{
|
||||
draw2DClustering(viewMat,&bvhMotion,aPose,state,line,videoPath,WIDTH,HEIGHT);
|
||||
|
||||
state->redraw=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fprintf(stderr,"Done with %s\n",line);
|
||||
|
||||
bvh_free(&bvhMotion);
|
||||
|
||||
fprintf(stderr,"deallocation complete..\n");
|
||||
|
||||
|
||||
imshow("BVH", viewMat);
|
||||
|
||||
if (saveVideo)
|
||||
{
|
||||
snprintf(videoFrameFinalFilename,512,"%s/colorFrame_0_%05u.png",videoPath,visualizationFrameNumber);
|
||||
imwrite(videoFrameFinalFilename,viewMat);
|
||||
}
|
||||
|
||||
++visualizationFrameNumber;
|
||||
|
||||
waitKey(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Failed to load %s \n",line);
|
||||
}
|
||||
}//Line not empty
|
||||
} //New line read
|
||||
|
||||
if (line!=0)
|
||||
{
|
||||
free(line);
|
||||
line=0;
|
||||
len=0;
|
||||
}
|
||||
fclose(fp);
|
||||
// the camera will be deinitialized automatically in VideoCapture destructor
|
||||
|
||||
|
||||
|
||||
if (go3DMode)
|
||||
{
|
||||
fprintf(stderr,"3D clustering accumulated %lu samples \n",state3D->accumulatedSamples);
|
||||
if (state3D->fp!=0)
|
||||
{
|
||||
fclose(state3D->fp);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int i=system("cat dataset/header.bvh > filteredPoses.bvh");
|
||||
if (i!=0) { fprintf(stderr,"Could not use header for filterPoses.bvh\n"); }
|
||||
//------------------------------------------------------------------------
|
||||
i=system("echo \"MOTION\" >> filteredPoses.bvh");
|
||||
if (i!=0) { fprintf(stderr,"Could not add MOTION to filterPoses.bvh\n"); }
|
||||
//------------------------------------------------------------------------
|
||||
i=system("echo \"Frames: `cat filteredPoses.bvhm | wc -l`\" >> filteredPoses.bvh");
|
||||
if (i!=0) { fprintf(stderr,"Could not add number of poses\n"); }
|
||||
//------------------------------------------------------------------------
|
||||
i=system("echo \"Frame Time: 0.04\" >> filteredPoses.bvh");
|
||||
if (i!=0) { fprintf(stderr,"Could not add frame time\n"); }
|
||||
//------------------------------------------------------------------------
|
||||
i=system("cat filteredPoses.bvhm >> filteredPoses.bvh");
|
||||
if (i!=0) { fprintf(stderr,"Could not add motion frames\n"); }
|
||||
//------------------------------------------------------------------------
|
||||
i=system("rm filteredPoses.bvhm");
|
||||
if (i!=0) { fprintf(stderr,"Could not remove intermediate motion frames\n"); }
|
||||
//------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
|
||||
free(state);
|
||||
free(state3D);
|
||||
|
||||
fprintf(stderr,"Done overlaying %lu poses..!\n",numberOfPosesLoaded);
|
||||
imshow("BVH", viewMat);
|
||||
imwrite("csvCluster.png",viewMat);
|
||||
|
||||
if (saveVideo)
|
||||
{
|
||||
//Low-Res video encoding
|
||||
//snprintf(videoFrameFinalFilename,512,"ffmpeg -framerate 30 -i %s/colorFrame_0_%%05d.png -y -r 30 -threads 8 -crf 9 -pix_fmt yuv420p %s/video.mp4",videoPath,videoPath);
|
||||
|
||||
//High-Res video encoding
|
||||
snprintf(videoFrameFinalFilename,512,"ffmpeg -framerate 30 -i %s/colorFrame_0_%%05d.png -s 1200x720 -y -r 30 -pix_fmt yuv420p -threads 8 %s/video.mp4",videoPath,videoPath);
|
||||
int i=system(videoFrameFinalFilename);
|
||||
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
fprintf(stderr,"Successfully wrote video file %s/video.mp4.. \n",videoPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Failed to write a video file %s/video.mp4.. \n",videoPath);
|
||||
}
|
||||
|
||||
fprintf(stderr,"Since we wanted to output video this is probably a scripted run, will not wait for a keystroke..\n");
|
||||
waitKey(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
waitKey(0);
|
||||
}
|
||||
|
||||
|
||||
free(state->accumulatedImage);
|
||||
free(state);
|
||||
free(state3D);
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,282 @@
|
||||
dataset/MotionCapture/01/01_02.bvh
|
||||
dataset/MotionCapture/01/01_03.bvh
|
||||
dataset/MotionCapture/01/01_05.bvh
|
||||
dataset/MotionCapture/01/01_06.bvh
|
||||
dataset/MotionCapture/01/01_07.bvh
|
||||
dataset/MotionCapture/01/01_08.bvh
|
||||
dataset/MotionCapture/01/01_09.bvh
|
||||
dataset/MotionCapture/01/01_10.bvh
|
||||
dataset/MotionCapture/01/01_11.bvh
|
||||
dataset/MotionCapture/01/01_12.bvh
|
||||
dataset/MotionCapture/01/01_13.bvh
|
||||
dataset/MotionCapture/01/01_14.bvh
|
||||
dataset/MotionCapture/02/02_01.bvh
|
||||
dataset/MotionCapture/02/02_02.bvh
|
||||
dataset/MotionCapture/02/02_03.bvh
|
||||
dataset/MotionCapture/02/02_04.bvh
|
||||
dataset/MotionCapture/02/02_05.bvh
|
||||
dataset/MotionCapture/02/02_06.bvh
|
||||
dataset/MotionCapture/02/02_07.bvh
|
||||
dataset/MotionCapture/02/02_08.bvh
|
||||
dataset/MotionCapture/02/02_09.bvh
|
||||
dataset/MotionCapture/02/02_10.bvh
|
||||
dataset/MotionCapture/03/03_01.bvh
|
||||
dataset/MotionCapture/03/03_02.bvh
|
||||
dataset/MotionCapture/03/03_03.bvh
|
||||
dataset/MotionCapture/03/03_04.bvh
|
||||
dataset/MotionCapture/05/05_01.bvh
|
||||
dataset/MotionCapture/05/05_02.bvh
|
||||
dataset/MotionCapture/05/05_03.bvh
|
||||
dataset/MotionCapture/05/05_04.bvh
|
||||
dataset/MotionCapture/05/05_05.bvh
|
||||
dataset/MotionCapture/05/05_06.bvh
|
||||
dataset/MotionCapture/05/05_07.bvh
|
||||
dataset/MotionCapture/05/05_08.bvh
|
||||
dataset/MotionCapture/05/05_09.bvh
|
||||
dataset/MotionCapture/05/05_10.bvh
|
||||
dataset/MotionCapture/05/05_11.bvh
|
||||
dataset/MotionCapture/05/05_12.bvh
|
||||
dataset/MotionCapture/05/05_13.bvh
|
||||
dataset/MotionCapture/05/05_14.bvh
|
||||
dataset/MotionCapture/05/05_15.bvh
|
||||
dataset/MotionCapture/05/05_16.bvh
|
||||
dataset/MotionCapture/05/05_17.bvh
|
||||
dataset/MotionCapture/05/05_18.bvh
|
||||
dataset/MotionCapture/05/05_19.bvh
|
||||
dataset/MotionCapture/05/05_20.bvh
|
||||
dataset/MotionCapture/06/06_01.bvh
|
||||
dataset/MotionCapture/06/06_02.bvh
|
||||
dataset/MotionCapture/06/06_03.bvh
|
||||
dataset/MotionCapture/06/06_04.bvh
|
||||
dataset/MotionCapture/06/06_05.bvh
|
||||
dataset/MotionCapture/06/06_06.bvh
|
||||
dataset/MotionCapture/06/06_07.bvh
|
||||
dataset/MotionCapture/06/06_08.bvh
|
||||
dataset/MotionCapture/06/06_09.bvh
|
||||
dataset/MotionCapture/06/06_10.bvh
|
||||
dataset/MotionCapture/06/06_11.bvh
|
||||
dataset/MotionCapture/06/06_12.bvh
|
||||
dataset/MotionCapture/06/06_13.bvh
|
||||
dataset/MotionCapture/06/06_14.bvh
|
||||
dataset/MotionCapture/06/06_15.bvh
|
||||
dataset/MotionCapture/07/07_01.bvh
|
||||
dataset/MotionCapture/07/07_02.bvh
|
||||
dataset/MotionCapture/07/07_03.bvh
|
||||
dataset/MotionCapture/07/07_04.bvh
|
||||
dataset/MotionCapture/07/07_05.bvh
|
||||
dataset/MotionCapture/07/07_06.bvh
|
||||
dataset/MotionCapture/07/07_07.bvh
|
||||
dataset/MotionCapture/07/07_08.bvh
|
||||
dataset/MotionCapture/07/07_09.bvh
|
||||
dataset/MotionCapture/07/07_10.bvh
|
||||
dataset/MotionCapture/07/07_11.bvh
|
||||
dataset/MotionCapture/07/07_12.bvh
|
||||
dataset/MotionCapture/08/08_01.bvh
|
||||
dataset/MotionCapture/08/08_02.bvh
|
||||
dataset/MotionCapture/08/08_03.bvh
|
||||
dataset/MotionCapture/08/08_04.bvh
|
||||
dataset/MotionCapture/08/08_05.bvh
|
||||
dataset/MotionCapture/08/08_06.bvh
|
||||
dataset/MotionCapture/08/08_07.bvh
|
||||
dataset/MotionCapture/08/08_08.bvh
|
||||
dataset/MotionCapture/08/08_09.bvh
|
||||
dataset/MotionCapture/08/08_10.bvh
|
||||
dataset/MotionCapture/08/08_11.bvh
|
||||
dataset/MotionCapture/09/09_01.bvh
|
||||
dataset/MotionCapture/09/09_02.bvh
|
||||
dataset/MotionCapture/09/09_03.bvh
|
||||
dataset/MotionCapture/09/09_04.bvh
|
||||
dataset/MotionCapture/09/09_05.bvh
|
||||
dataset/MotionCapture/09/09_06.bvh
|
||||
dataset/MotionCapture/09/09_07.bvh
|
||||
dataset/MotionCapture/09/09_08.bvh
|
||||
dataset/MotionCapture/09/09_09.bvh
|
||||
dataset/MotionCapture/09/09_10.bvh
|
||||
dataset/MotionCapture/09/09_11.bvh
|
||||
dataset/MotionCapture/09/09_12.bvh
|
||||
dataset/MotionCapture/10/10_01.bvh
|
||||
dataset/MotionCapture/10/10_02.bvh
|
||||
dataset/MotionCapture/10/10_03.bvh
|
||||
dataset/MotionCapture/10/10_04.bvh
|
||||
dataset/MotionCapture/10/10_05.bvh
|
||||
dataset/MotionCapture/10/10_06.bvh
|
||||
dataset/MotionCapture/13/13_01.bvh
|
||||
dataset/MotionCapture/13/13_02.bvh
|
||||
dataset/MotionCapture/13/13_03.bvh
|
||||
dataset/MotionCapture/13/13_04.bvh
|
||||
dataset/MotionCapture/13/13_05.bvh
|
||||
dataset/MotionCapture/13/13_06.bvh
|
||||
dataset/MotionCapture/13/13_07.bvh
|
||||
dataset/MotionCapture/13/13_08.bvh
|
||||
dataset/MotionCapture/13/13_09.bvh
|
||||
dataset/MotionCapture/13/13_10.bvh
|
||||
dataset/MotionCapture/13/13_11.bvh
|
||||
dataset/MotionCapture/13/13_12.bvh
|
||||
dataset/MotionCapture/13/13_13.bvh
|
||||
dataset/MotionCapture/13/13_14.bvh
|
||||
dataset/MotionCapture/13/13_15.bvh
|
||||
dataset/MotionCapture/13/13_16.bvh
|
||||
dataset/MotionCapture/13/13_19.bvh
|
||||
dataset/MotionCapture/13/13_20.bvh
|
||||
dataset/MotionCapture/13/13_21.bvh
|
||||
dataset/MotionCapture/13/13_22.bvh
|
||||
dataset/MotionCapture/13/13_24.bvh
|
||||
dataset/MotionCapture/13/13_25.bvh
|
||||
dataset/MotionCapture/13/13_26.bvh
|
||||
dataset/MotionCapture/13/13_27.bvh
|
||||
dataset/MotionCapture/13/13_28.bvh
|
||||
dataset/MotionCapture/13/13_29.bvh
|
||||
dataset/MotionCapture/13/13_30.bvh
|
||||
dataset/MotionCapture/13/13_31.bvh
|
||||
dataset/MotionCapture/13/13_32.bvh
|
||||
dataset/MotionCapture/13/13_33.bvh
|
||||
dataset/MotionCapture/13/13_34.bvh
|
||||
dataset/MotionCapture/13/13_35.bvh
|
||||
dataset/MotionCapture/13/13_36.bvh
|
||||
dataset/MotionCapture/13/13_37.bvh
|
||||
dataset/MotionCapture/13/13_38.bvh
|
||||
dataset/MotionCapture/13/13_39.bvh
|
||||
dataset/MotionCapture/13/13_40.bvh
|
||||
dataset/MotionCapture/13/13_41.bvh
|
||||
dataset/MotionCapture/13/13_42.bvh
|
||||
dataset/MotionCapture/14/14_01.bvh
|
||||
dataset/MotionCapture/14/14_04.bvh
|
||||
dataset/MotionCapture/14/14_05.bvh
|
||||
dataset/MotionCapture/14/14_06.bvh
|
||||
dataset/MotionCapture/14/14_07.bvh
|
||||
dataset/MotionCapture/14/14_08.bvh
|
||||
dataset/MotionCapture/14/14_09.bvh
|
||||
dataset/MotionCapture/14/14_10.bvh
|
||||
dataset/MotionCapture/14/14_11.bvh
|
||||
dataset/MotionCapture/14/14_12.bvh
|
||||
dataset/MotionCapture/14/14_13.bvh
|
||||
dataset/MotionCapture/14/14_14.bvh
|
||||
dataset/MotionCapture/14/14_15.bvh
|
||||
dataset/MotionCapture/14/14_16.bvh
|
||||
dataset/MotionCapture/14/14_17.bvh
|
||||
dataset/MotionCapture/14/14_18.bvh
|
||||
dataset/MotionCapture/14/14_19.bvh
|
||||
dataset/MotionCapture/14/14_20.bvh
|
||||
dataset/MotionCapture/14/14_21.bvh
|
||||
dataset/MotionCapture/14/14_22.bvh
|
||||
dataset/MotionCapture/14/14_24.bvh
|
||||
dataset/MotionCapture/14/14_25.bvh
|
||||
dataset/MotionCapture/14/14_26.bvh
|
||||
dataset/MotionCapture/14/14_27.bvh
|
||||
dataset/MotionCapture/14/14_28.bvh
|
||||
dataset/MotionCapture/14/14_29.bvh
|
||||
dataset/MotionCapture/14/14_30.bvh
|
||||
dataset/MotionCapture/14/14_31.bvh
|
||||
dataset/MotionCapture/14/14_32.bvh
|
||||
dataset/MotionCapture/14/14_33.bvh
|
||||
dataset/MotionCapture/14/14_34.bvh
|
||||
dataset/MotionCapture/14/14_35.bvh
|
||||
dataset/MotionCapture/14/14_36.bvh
|
||||
dataset/MotionCapture/14/14_37.bvh
|
||||
dataset/MotionCapture/15/15_01.bvh
|
||||
dataset/MotionCapture/15/15_02.bvh
|
||||
dataset/MotionCapture/15/15_03.bvh
|
||||
dataset/MotionCapture/15/15_04.bvh
|
||||
dataset/MotionCapture/15/15_05.bvh
|
||||
dataset/MotionCapture/15/15_06.bvh
|
||||
dataset/MotionCapture/15/15_07.bvh
|
||||
dataset/MotionCapture/15/15_08.bvh
|
||||
dataset/MotionCapture/15/15_09.bvh
|
||||
dataset/MotionCapture/15/15_10.bvh
|
||||
dataset/MotionCapture/15/15_11.bvh
|
||||
dataset/MotionCapture/15/15_12.bvh
|
||||
dataset/MotionCapture/15/15_13.bvh
|
||||
dataset/MotionCapture/15/15_14.bvh
|
||||
dataset/MotionCapture/16/16_01.bvh
|
||||
dataset/MotionCapture/16/16_02.bvh
|
||||
dataset/MotionCapture/16/16_03.bvh
|
||||
dataset/MotionCapture/16/16_04.bvh
|
||||
dataset/MotionCapture/16/16_05.bvh
|
||||
dataset/MotionCapture/16/16_06.bvh
|
||||
dataset/MotionCapture/16/16_07.bvh
|
||||
dataset/MotionCapture/16/16_08.bvh
|
||||
dataset/MotionCapture/16/16_09.bvh
|
||||
dataset/MotionCapture/16/16_10.bvh
|
||||
dataset/MotionCapture/16/16_11.bvh
|
||||
dataset/MotionCapture/16/16_12.bvh
|
||||
dataset/MotionCapture/16/16_13.bvh
|
||||
dataset/MotionCapture/16/16_14.bvh
|
||||
dataset/MotionCapture/16/16_15.bvh
|
||||
dataset/MotionCapture/16/16_16.bvh
|
||||
dataset/MotionCapture/16/16_17.bvh
|
||||
dataset/MotionCapture/16/16_18.bvh
|
||||
dataset/MotionCapture/16/16_19.bvh
|
||||
dataset/MotionCapture/16/16_20.bvh
|
||||
dataset/MotionCapture/16/16_21.bvh
|
||||
dataset/MotionCapture/16/16_22.bvh
|
||||
dataset/MotionCapture/16/16_23.bvh
|
||||
dataset/MotionCapture/16/16_24.bvh
|
||||
dataset/MotionCapture/16/16_25.bvh
|
||||
dataset/MotionCapture/16/16_26.bvh
|
||||
dataset/MotionCapture/16/16_27.bvh
|
||||
dataset/MotionCapture/16/16_28.bvh
|
||||
dataset/MotionCapture/16/16_29.bvh
|
||||
dataset/MotionCapture/16/16_30.bvh
|
||||
dataset/MotionCapture/16/16_31.bvh
|
||||
dataset/MotionCapture/16/16_32.bvh
|
||||
dataset/MotionCapture/16/16_33.bvh
|
||||
dataset/MotionCapture/16/16_34.bvh
|
||||
dataset/MotionCapture/16/16_35.bvh
|
||||
dataset/MotionCapture/16/16_36.bvh
|
||||
dataset/MotionCapture/16/16_37.bvh
|
||||
dataset/MotionCapture/16/16_38.bvh
|
||||
dataset/MotionCapture/16/16_39.bvh
|
||||
dataset/MotionCapture/16/16_40.bvh
|
||||
dataset/MotionCapture/16/16_41.bvh
|
||||
dataset/MotionCapture/16/16_42.bvh
|
||||
dataset/MotionCapture/16/16_43.bvh
|
||||
dataset/MotionCapture/16/16_44.bvh
|
||||
dataset/MotionCapture/16/16_47.bvh
|
||||
dataset/MotionCapture/16/16_48.bvh
|
||||
dataset/MotionCapture/16/16_49.bvh
|
||||
dataset/MotionCapture/16/16_50.bvh
|
||||
dataset/MotionCapture/16/16_51.bvh
|
||||
dataset/MotionCapture/16/16_52.bvh
|
||||
dataset/MotionCapture/16/16_53.bvh
|
||||
dataset/MotionCapture/16/16_55.bvh
|
||||
dataset/MotionCapture/16/16_56.bvh
|
||||
dataset/MotionCapture/16/16_58.bvh
|
||||
dataset/MotionCapture/17/17_01.bvh
|
||||
dataset/MotionCapture/17/17_02.bvh
|
||||
dataset/MotionCapture/17/17_03.bvh
|
||||
dataset/MotionCapture/17/17_04.bvh
|
||||
dataset/MotionCapture/17/17_05.bvh
|
||||
dataset/MotionCapture/17/17_06.bvh
|
||||
dataset/MotionCapture/17/17_07.bvh
|
||||
dataset/MotionCapture/17/17_08.bvh
|
||||
dataset/MotionCapture/17/17_09.bvh
|
||||
dataset/MotionCapture/18/18_01.bvh
|
||||
dataset/MotionCapture/18/18_02.bvh
|
||||
dataset/MotionCapture/18/18_03.bvh
|
||||
dataset/MotionCapture/18/18_04.bvh
|
||||
dataset/MotionCapture/18/18_05.bvh
|
||||
dataset/MotionCapture/18/18_06.bvh
|
||||
dataset/MotionCapture/18/18_07.bvh
|
||||
dataset/MotionCapture/18/18_08.bvh
|
||||
dataset/MotionCapture/18/18_09.bvh
|
||||
dataset/MotionCapture/18/18_10.bvh
|
||||
dataset/MotionCapture/18/18_11.bvh
|
||||
dataset/MotionCapture/18/18_12.bvh
|
||||
dataset/MotionCapture/18/18_13.bvh
|
||||
dataset/MotionCapture/18/18_14.bvh
|
||||
dataset/MotionCapture/18/18_15.bvh
|
||||
dataset/MotionCapture/19/19_01.bvh
|
||||
dataset/MotionCapture/19/19_02.bvh
|
||||
dataset/MotionCapture/19/19_03.bvh
|
||||
dataset/MotionCapture/19/19_04.bvh
|
||||
dataset/MotionCapture/19/19_05.bvh
|
||||
dataset/MotionCapture/19/19_06.bvh
|
||||
dataset/MotionCapture/19/19_07.bvh
|
||||
dataset/MotionCapture/19/19_08.bvh
|
||||
dataset/MotionCapture/19/19_09.bvh
|
||||
dataset/MotionCapture/19/19_10.bvh
|
||||
dataset/MotionCapture/19/19_11.bvh
|
||||
dataset/MotionCapture/19/19_12.bvh
|
||||
dataset/MotionCapture/19/19_13.bvh
|
||||
dataset/MotionCapture/19/19_14.bvh
|
||||
dataset/MotionCapture/19/19_15.bvh
|
||||
@@ -0,0 +1,125 @@
|
||||
#include "perform2DClustering.hpp"
|
||||
|
||||
|
||||
#include "../MocapNETLib2/IO/bvh.hpp"
|
||||
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/bvh_loader.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_filter.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_rename.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_randomize.h"
|
||||
|
||||
|
||||
|
||||
std::vector<std::vector<float> > collectPoses(
|
||||
struct applicationState * state,
|
||||
std::vector<char> &activeJoints,
|
||||
struct BVH_MotionCapture * bvhMotion,
|
||||
float distance,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
)
|
||||
{
|
||||
|
||||
std::vector<std::vector<float> > bvh2DPoints;
|
||||
|
||||
if (bvhMotion==0)
|
||||
{
|
||||
return bvh2DPoints;
|
||||
}
|
||||
|
||||
|
||||
std::vector<float> bvhConfiguration;
|
||||
|
||||
bvhConfiguration.clear();
|
||||
for (int i=0; i<bvhMotion->numberOfValuesPerFrame; i++)
|
||||
{
|
||||
bvhConfiguration.push_back(0.0);
|
||||
}
|
||||
bvhConfiguration[2]=(float) -150.0;
|
||||
|
||||
|
||||
|
||||
if ( bvhConfiguration.size() < bvhMotion->numberOfValuesPerFrame)
|
||||
{
|
||||
return bvh2DPoints;
|
||||
}
|
||||
|
||||
unsigned int mID=0;
|
||||
|
||||
fprintf(stderr,"Collecting %u poses\n",bvhMotion->numberOfFrames);
|
||||
|
||||
// state->maxAccumulatedSample= 0;
|
||||
|
||||
for (int frameID=0; frameID<bvhMotion->numberOfFrames; frameID++)
|
||||
{
|
||||
//fprintf(stderr,".%u",frameID);
|
||||
|
||||
for (int i=0; i<bvhMotion->numberOfValuesPerFrame; i++)
|
||||
{
|
||||
//fprintf(stderr,"%u ",i);
|
||||
int motionValueID = mID % (bvhMotion->numberOfValuesPerFrame * bvhMotion->numberOfFrames);
|
||||
bvhConfiguration[i]=bvhMotion->motionValues[motionValueID];
|
||||
++mID;
|
||||
}
|
||||
//fprintf(stderr,"!");
|
||||
|
||||
|
||||
if (bvhConfiguration.size()>5)
|
||||
{
|
||||
bvhConfiguration[0]=0;
|
||||
bvhConfiguration[1]=0;
|
||||
bvhConfiguration[2]=distance;
|
||||
bvhConfiguration[3]=0;
|
||||
bvhConfiguration[4]=state->rotation;
|
||||
bvhConfiguration[5]=0;
|
||||
|
||||
bvh2DPoints = convertBVHFrameTo2DPoints(bvhConfiguration); //,width, height
|
||||
|
||||
|
||||
|
||||
if (bvh2DPoints.size()>0)
|
||||
{
|
||||
++state->accumulatedSamples;
|
||||
for (int i=0; i<bvh2DPoints.size(); i++)
|
||||
{
|
||||
//We want to exclude Hip joint because it is stuck in the same place for every frame..!
|
||||
if (
|
||||
( activeJoints[i] ) &&
|
||||
( (bvh2DPoints[i][0]>0) && (bvh2DPoints[i][1]>0) && (bvh2DPoints[i][0]<width) && (bvh2DPoints[i][1]<height) )
|
||||
)
|
||||
{
|
||||
unsigned int x=(unsigned int) bvh2DPoints[i][0];
|
||||
unsigned int y=(unsigned int) bvh2DPoints[i][1];
|
||||
|
||||
if ( (x<width) && (y<height) )
|
||||
{
|
||||
unsigned long newValue = state->accumulatedImage[y*width+x] + 1;
|
||||
|
||||
if (newValue<=state->accumulatedSamples)
|
||||
{
|
||||
state->accumulatedImage[y*width+x] = newValue;
|
||||
|
||||
if (state->maxAccumulatedSample<newValue)
|
||||
{
|
||||
state->maxAccumulatedSample=newValue;
|
||||
//fprintf(stderr,"Pixel %u,%u has largest value %lu\n",x,y,newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"%0.2f,%0.2f wrongly casted to %u,%u",bvh2DPoints[i][0],bvh2DPoints[i][1],x,y);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Could not project BVH 2D points\n");
|
||||
}
|
||||
}
|
||||
} //For every frame loop..
|
||||
|
||||
return bvh2DPoints;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
struct applicationState
|
||||
{
|
||||
int rotation;
|
||||
int selectedJoint,previousSelection;
|
||||
int visualizationType,previousVisualizationType;
|
||||
int stop;
|
||||
int save;
|
||||
int redraw;
|
||||
//-----------------
|
||||
unsigned long * accumulatedImage;
|
||||
unsigned long accumulatedSamples;
|
||||
unsigned long maxAccumulatedSample;
|
||||
};
|
||||
|
||||
|
||||
std::vector<std::vector<float> > collectPoses(
|
||||
struct applicationState * state,
|
||||
std::vector<char> &activeJoints,
|
||||
struct BVH_MotionCapture * bvhMotion,
|
||||
float distance,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
);
|
||||
@@ -0,0 +1,223 @@
|
||||
#include "perform3DClustering.hpp"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "../MocapNETLib2/IO/bvh.hpp"
|
||||
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/bvh_loader.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_filter.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_rename.h"
|
||||
#include "../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/edit/bvh_randomize.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 appendBVHVectorToFile(FILE * fp, std::vector<float> vec)
|
||||
{
|
||||
if ( (fp!=0) && (vec.size()>0) )
|
||||
{
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
{
|
||||
if (i!=0) { fprintf(fp," "); }
|
||||
fprintf(fp,"%0.2f",vec[i]);
|
||||
}
|
||||
fprintf(fp,"\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::vector<float> > collect3DPoses(
|
||||
struct clusteringOf3DPoses * state,
|
||||
std::vector<char> &activeJoints,
|
||||
struct BVH_MotionCapture * bvhMotion,
|
||||
float distance,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int depth
|
||||
)
|
||||
{
|
||||
std::vector<std::vector<float> > bvh2DPointsFront;
|
||||
std::vector<std::vector<float> > bvh2DPointsSide;
|
||||
|
||||
if (bvhMotion==0)
|
||||
{
|
||||
//Return an empty vector of vectors..
|
||||
return bvh2DPointsFront;
|
||||
}
|
||||
|
||||
if (state->fp==0)
|
||||
{
|
||||
state->fp = fopen("filteredPoses.bvhm","w");
|
||||
}
|
||||
|
||||
if (state->space==0)
|
||||
{
|
||||
state->allocatedSpaceMemorySize = width * height * depth * sizeof(struct voxelElement);
|
||||
fprintf(stderr,"Will now try to allocate a huge chunk of memory (%lu bytes)\n",state->allocatedSpaceMemorySize);
|
||||
state->space = (struct voxelElement * ) malloc(state->allocatedSpaceMemorySize);
|
||||
if (state->space!=0)
|
||||
{
|
||||
fprintf(stderr,"Will now try to cleanup the huge chunk of memory (%lu bytes)\n",state->allocatedSpaceMemorySize);
|
||||
memset(state->space,0,state->allocatedSpaceMemorySize);
|
||||
fprintf(stderr,"Survived..\n");
|
||||
} else
|
||||
{
|
||||
state->allocatedSpaceMemorySize=0;
|
||||
fprintf(stderr,"Error allocating a huge chunk of memory..!\n");
|
||||
return bvh2DPointsFront;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<float> bvhConfiguration;
|
||||
|
||||
bvhConfiguration.clear();
|
||||
for (int i=0; i<bvhMotion->numberOfValuesPerFrame; i++)
|
||||
{
|
||||
bvhConfiguration.push_back(0.0);
|
||||
}
|
||||
bvhConfiguration[2]=(float) -150.0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (bvhMotion==0)
|
||||
{
|
||||
return bvh2DPointsFront;
|
||||
}
|
||||
|
||||
if ( bvhConfiguration.size() < bvhMotion->numberOfValuesPerFrame)
|
||||
{
|
||||
return bvh2DPointsFront;
|
||||
}
|
||||
|
||||
unsigned int mID=0;
|
||||
|
||||
fprintf(stderr,"Collecting %u poses\n",bvhMotion->numberOfFrames);
|
||||
|
||||
// state->maxAccumulatedSample= 0;
|
||||
unsigned int negativesAtThisCall=0;
|
||||
unsigned int hitsAtThisCall=0;
|
||||
|
||||
for (int frameID=0; frameID<bvhMotion->numberOfFrames; frameID++)
|
||||
{
|
||||
//fprintf(stderr,".%u",frameID);
|
||||
|
||||
for (int i=0; i<bvhMotion->numberOfValuesPerFrame; i++)
|
||||
{
|
||||
//fprintf(stderr,"%u ",i);
|
||||
int motionValueID = mID % (bvhMotion->numberOfValuesPerFrame * bvhMotion->numberOfFrames);
|
||||
bvhConfiguration[i]=bvhMotion->motionValues[motionValueID];
|
||||
++mID;
|
||||
}
|
||||
//fprintf(stderr,"!");
|
||||
|
||||
|
||||
|
||||
if (bvhConfiguration.size()>5)
|
||||
{
|
||||
bvhConfiguration[0]=0;
|
||||
bvhConfiguration[1]=0;
|
||||
bvhConfiguration[2]=distance;
|
||||
bvhConfiguration[3]=0;
|
||||
bvhConfiguration[4]=0;
|
||||
bvhConfiguration[5]=0;
|
||||
|
||||
|
||||
bvhConfiguration[4]=0;
|
||||
bvh2DPointsFront = convertBVHFrameTo2DPoints(bvhConfiguration); //,width,height
|
||||
bvhConfiguration[4]=90;
|
||||
bvh2DPointsSide = convertBVHFrameTo2DPoints(bvhConfiguration); //,width,height
|
||||
bvhConfiguration[4]=0; // So the configuration we save is ok
|
||||
|
||||
if ( (bvh2DPointsFront.size()>0) && (bvh2DPointsSide.size()>0) && (bvh2DPointsFront.size()==bvh2DPointsSide.size()) )
|
||||
{
|
||||
for (int i=0; i<bvh2DPointsFront.size(); i++)
|
||||
{
|
||||
//We want to exclude Hip joint because it is stuck in the same place for every frame..!
|
||||
if (
|
||||
(activeJoints[i]) &&
|
||||
( (bvh2DPointsFront[i][0]>0) && (bvh2DPointsFront[i][1]>0) && (bvh2DPointsFront[i][0]<width) && (bvh2DPointsFront[i][1]<height) ) &&
|
||||
( (bvh2DPointsSide[i][0]>0) && (bvh2DPointsSide[i][1]>0) && (bvh2DPointsSide[i][0]<depth) && (bvh2DPointsSide[i][1]<height) )
|
||||
)
|
||||
{
|
||||
unsigned int x=(unsigned int) bvh2DPointsFront[i][0];
|
||||
unsigned int y=(unsigned int) bvh2DPointsFront[i][1];
|
||||
unsigned int z=(unsigned int) bvh2DPointsSide[i][0];
|
||||
|
||||
//fprintf(stderr,"x=%u,y=%u,z=%u\n",x,y,z);
|
||||
|
||||
if ( (x<width) && (y<height) && (z<depth) )
|
||||
{
|
||||
unsigned long memoryLocation = (unsigned long) (z*width*height) + (y*width)+ x;
|
||||
|
||||
if (state->allocatedSpaceMemorySize>memoryLocation)
|
||||
{
|
||||
if (state->space[memoryLocation].element==0)
|
||||
{
|
||||
++state->accumulatedSamples;
|
||||
appendBVHVectorToFile(state->fp, bvhConfiguration);
|
||||
++hitsAtThisCall;
|
||||
state->space[memoryLocation].element=1;
|
||||
} else
|
||||
{
|
||||
++negativesAtThisCall;
|
||||
if (state->space[memoryLocation].element<254)
|
||||
{
|
||||
state->space[memoryLocation].element+=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (newValue<=state->accumulatedSamples)
|
||||
{
|
||||
state->space[memoryLocation].element = newValue;
|
||||
|
||||
if (state->maxAccumulatedSample<newValue)
|
||||
{
|
||||
state->maxAccumulatedSample=newValue;
|
||||
//fprintf(stderr,"Pixel %u,%u has largest value %lu\n",x,y,newValue);
|
||||
}
|
||||
} */
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,"Bad memory location for %u,%u,%u \n",x,y,z);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"%0.2f,%0.2f wrongly casted to %u,%u",bvh2DPointsFront[i][0],bvh2DPointsFront[i][1],x,y);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Could not project BVH 2D points\n");
|
||||
}
|
||||
}
|
||||
} //For every frame loop..
|
||||
|
||||
if (hitsAtThisCall>0)
|
||||
{
|
||||
fprintf(stderr,GREEN "Added %u more poses (%0.2f%% of the dataset is novel)..\n" NORMAL,hitsAtThisCall,(float) (100*hitsAtThisCall)/bvhMotion->numberOfFrames);
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,YELLOW "No new poses observed ( %u/%u negatives )..\n" NORMAL,negativesAtThisCall,bvhMotion->numberOfFrames);
|
||||
}
|
||||
|
||||
return bvh2DPointsFront;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
struct voxelElement
|
||||
{
|
||||
char element;
|
||||
};
|
||||
|
||||
|
||||
struct clusteringOf3DPoses
|
||||
{
|
||||
FILE *fp;
|
||||
struct voxelElement * space;
|
||||
unsigned long allocatedSpaceMemorySize;
|
||||
unsigned int width,height,depth;
|
||||
unsigned long accumulatedSamples;
|
||||
unsigned long maxAccumulatedSample;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
std::vector<std::vector<float> > collect3DPoses(
|
||||
struct clusteringOf3DPoses * state,
|
||||
std::vector<char> &activeJoints,
|
||||
struct BVH_MotionCapture * bvhMotion,
|
||||
float distance,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int depth
|
||||
);
|
||||
@@ -0,0 +1,36 @@
|
||||
project( convertH36GroundTruthToMocapNETInput )
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
include_directories(${TENSORFLOW_INCLUDE_ROOT})
|
||||
|
||||
#-----------------------------------------------
|
||||
# This is the converter utilities..
|
||||
#-----------------------------------------------
|
||||
add_executable(
|
||||
convertH36GroundTruthToMocapNETInput
|
||||
convertH36GroundTruthToMocapNETInput.cpp
|
||||
../../MocapNETLib2/tools.cpp
|
||||
../../MocapNETLib2/IO/jsonRead.cpp
|
||||
../../MocapNETLib2/IO/jsonMocapNETHelpers.cpp
|
||||
../../../../dependencies/InputParser/InputParser_C.cpp
|
||||
${BVH_SOURCE}
|
||||
${OPENGL_SOURCE}
|
||||
../../MocapNETLib2/IO/bvh.cpp
|
||||
../../MocapNETLib2/IO/conversions.cpp
|
||||
../../MocapNETLib2/IO/csvRead.cpp
|
||||
../../MocapNETLib2/IO/csvWrite.cpp
|
||||
)
|
||||
|
||||
#-----------------------------------------------
|
||||
|
||||
target_link_libraries(convertH36GroundTruthToMocapNETInput rt dl m pthread MocapNETLib2)
|
||||
set_target_properties(convertH36GroundTruthToMocapNETInput PROPERTIES DEBUG_POSTFIX "D")
|
||||
set_target_properties(convertH36GroundTruthToMocapNETInput PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Export utility from OpenPose BODY 25 JSON format to a more regular CSV file
|
||||
* Sample call : ./convertBody25JSONToCSV --from frames/GOPR3223.MP4-data/ --label colorFrame_0_ -o .
|
||||
* */
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../../MocapNET2/MocapNETLib2/tools.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/commonSkeleton.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/jsonRead.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/csvRead.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/csvWrite.hpp"
|
||||
|
||||
|
||||
#if USE_BVH
|
||||
#include "../../../../dependencies/RGBDAcquisition/tools/AmMatrix/matrix4x4Tools.h"
|
||||
#include "../../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/bvh_loader.h"
|
||||
#include "../../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/calculate/bvh_project.h"
|
||||
#include "../../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/calculate/bvh_transform.h"
|
||||
#include "../../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/ik/bvh_inverseKinematics.h"
|
||||
#else
|
||||
#warning "BVH code not included.."
|
||||
#endif // USE_BVH
|
||||
|
||||
|
||||
#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 main(int argc, char *argv[])
|
||||
{
|
||||
#if USE_BVH
|
||||
|
||||
float fX = 582.18394; //570.0
|
||||
float fY = 582.52915; //570.0
|
||||
unsigned int width = 1920;
|
||||
unsigned int height = 1080;
|
||||
|
||||
struct simpleRenderer renderer= {0};
|
||||
|
||||
simpleRendererDefaults(
|
||||
&renderer,
|
||||
width,//1920
|
||||
height,//1080
|
||||
fX, //570.0
|
||||
fY //570.0
|
||||
);
|
||||
|
||||
simpleRendererInitialize(&renderer);
|
||||
|
||||
const char * path=0;
|
||||
const char * label=0;
|
||||
char outputPathFull[2048]= {"./h36ToMnet.csv"};
|
||||
const char * outputPath=outputPathFull;
|
||||
|
||||
float offsetX=0.0,offsetY=0.0,offsetZ=0.0;
|
||||
|
||||
int flipX=0;
|
||||
int flipY=1;
|
||||
|
||||
for (int i=0; i<argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--from")==0)
|
||||
{
|
||||
path = argv[i+1];
|
||||
}
|
||||
else if (strcmp(argv[i],"--to")==0)
|
||||
{
|
||||
outputPath = argv[i+1];
|
||||
}
|
||||
else if (strcmp(argv[i],"--offset")==0)
|
||||
{
|
||||
offsetX=atof(argv[i+1]);
|
||||
offsetY=atof(argv[i+2]);
|
||||
offsetZ=atof(argv[i+3]);
|
||||
}
|
||||
else if (strcmp(argv[i],"--flipX")==0)
|
||||
{
|
||||
offsetX=atof(argv[i+1]);
|
||||
offsetY=atof(argv[i+2]);
|
||||
offsetZ=atof(argv[i+3]);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::vector<float> > result;
|
||||
std::vector<float> points2DOfASpecificFrame;
|
||||
|
||||
struct CSVFileContext csv= {0};
|
||||
struct CSVFloatFileLine csvLine= {0};
|
||||
if ( openCSVFile(&csv,path) )
|
||||
{
|
||||
parseCSVHeader(&csv);
|
||||
while (parseNextCSVFloatLine(&csv,&csvLine))
|
||||
{
|
||||
points2DOfASpecificFrame.clear();
|
||||
|
||||
float pos3D[4]= {0};
|
||||
//pos3D[3]=1.0;
|
||||
|
||||
float position2DX=0,position2DY=0,position2DW=0;
|
||||
|
||||
float center[4]= {0};
|
||||
float rotation[3]= {0};
|
||||
|
||||
float hipX = csvLine.field[9 * 3 + 0];
|
||||
float hipY = csvLine.field[9 * 3 + 1];
|
||||
float hipZ = csvLine.field[9 * 3 + 2];
|
||||
|
||||
|
||||
for (unsigned int pointID=0; pointID<csv.numberOfHeaderFields/3; pointID++)
|
||||
{
|
||||
//--------------------------------------
|
||||
pos3D[0]=(float) (csvLine.field[pointID * 3 + 0]) + offsetX;
|
||||
pos3D[1]=(float) (csvLine.field[pointID * 3 + 1]) + offsetY;
|
||||
pos3D[2]=(float) -1 * (csvLine.field[pointID * 3 + 2]) + offsetZ;
|
||||
//fprintf(stderr,"Projecting %0.2f,%0.2f,%0.2f : ",pos3D[0],pos3D[1],pos3D[2]);
|
||||
//--------------------------------------
|
||||
if (
|
||||
simpleRendererRender(
|
||||
&renderer,
|
||||
pos3D,
|
||||
center,
|
||||
rotation,
|
||||
ROTATION_ORDER_RPY,
|
||||
&position2DX,
|
||||
&position2DY,
|
||||
&position2DW
|
||||
)
|
||||
)
|
||||
{
|
||||
if (flipX)
|
||||
{
|
||||
position2DX = width - position2DX;
|
||||
}
|
||||
|
||||
if (flipY)
|
||||
{
|
||||
position2DY = height - position2DY;
|
||||
}
|
||||
|
||||
|
||||
if (position2DW>0.0)
|
||||
{
|
||||
//fprintf(stderr,"output is %0.2f,%0.2f \n",position2DX,position2DY);
|
||||
points2DOfASpecificFrame.push_back((float) position2DX);
|
||||
points2DOfASpecificFrame.push_back((float) position2DY);
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr,"behind camera(%0.2f).. %0.2f,%0.2f \n",position2DW,position2DX,position2DY);
|
||||
points2DOfASpecificFrame.push_back(0.0);
|
||||
points2DOfASpecificFrame.push_back(0.0);
|
||||
}
|
||||
} else
|
||||
{
|
||||
points2DOfASpecificFrame.push_back(0.0);
|
||||
points2DOfASpecificFrame.push_back(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
result.push_back(points2DOfASpecificFrame);
|
||||
}
|
||||
|
||||
|
||||
if (result.size()>0)
|
||||
{
|
||||
FILE * fp = fopen(outputPath,"w");
|
||||
if (fp!=0)
|
||||
{
|
||||
|
||||
fprintf(fp,"frameNumber,skeletonID,totalSkeletons");
|
||||
|
||||
for (unsigned int pointID=0; pointID<csv.numberOfHeaderFields/3; pointID++)
|
||||
{
|
||||
char * pointLabel = csv.field[pointID*3].str + 4;
|
||||
|
||||
//Translate H36M labels to MNET labels..
|
||||
if ( strcmp(pointLabel,"nose")==0 ) { fprintf(fp,",2DX_head,2DY_head,visible_head"); } else
|
||||
if ( strcmp(pointLabel,"rwrist")==0 ) { fprintf(fp,",2DX_rhand,2DY_rhand,visible_rhand"); } else
|
||||
if ( strcmp(pointLabel,"lwrist")==0 ) { fprintf(fp,",2DX_lhand,2DY_lhand,visible_lhand"); } else
|
||||
if ( strcmp(pointLabel,"midhip")==0 ) { fprintf(fp,",2DX_hip,2DY_hip,visible_hip"); } else
|
||||
//rankle/lankle instead..
|
||||
if ( strcmp(pointLabel,"rheel")==0 ) { fprintf(fp,",2DX_rfoot,2DY_rfoot,visible_rfoot"); } else
|
||||
if ( strcmp(pointLabel,"lheel")==0 ) { fprintf(fp,",2DX_lfoot,2DY_lfoot,visible_lfoot"); } else
|
||||
if ( strcmp(pointLabel,"reye")==0 ) { fprintf(fp,",2DX_endsite_eye.r,2DY_endsite_eye.r,visible_endsite_eye.r"); } else
|
||||
if ( strcmp(pointLabel,"leye")==0 ) { fprintf(fp,",2DX_endsite_eye.l,2DY_endsite_eye.l,visible_endsite_eye.l"); } else
|
||||
if ( strcmp(pointLabel,"rbigtoe")==0 ) { fprintf(fp,",2DX_endsite_toe1-2.r,2DY_endsite_toe1-2.r,visible_endsite_toe1-2.r"); } else
|
||||
if ( strcmp(pointLabel,"lbigtoe")==0 ) { fprintf(fp,",2DX_endsite_toe1-2.l,2DY_endsite_toe1-2.l,visible_endsite_toe1-2.l"); } else
|
||||
if ( strcmp(pointLabel,"rsmalltoe")==0 ) { fprintf(fp,",2DX_endsite_toe5-3.r,2DY_endsite_toe5-3.r,visible_endsite_toe5-3.r"); } else
|
||||
if ( strcmp(pointLabel,"lsmalltoe")==0 ) { fprintf(fp,",2DX_endsite_toe5-3.l,2DY_endsite_toe5-3.l,visible_endsite_toe5-3.l"); } else
|
||||
{ fprintf(fp,",2DX_%s,2DY_%s,visible_%s",pointLabel,pointLabel,pointLabel); }
|
||||
|
||||
|
||||
}
|
||||
fprintf(fp,"\n");
|
||||
|
||||
for (unsigned int frameID=0; frameID<result.size(); frameID++)
|
||||
{
|
||||
|
||||
fprintf(fp,"%u,0,0",frameID);
|
||||
for (unsigned int pointID=0; pointID<result[frameID].size(); pointID++)
|
||||
{
|
||||
float normalizedPoint = result[frameID][pointID];
|
||||
|
||||
unsigned int element = pointID%2;
|
||||
|
||||
if (element==0) { normalizedPoint/= width; fprintf(fp,",%f",normalizedPoint); } else
|
||||
{ normalizedPoint/= height; fprintf(fp,",%f,1",normalizedPoint); }
|
||||
|
||||
}
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
closeCSVFile(&csv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#else
|
||||
fprintf(stderr,"This utility is only available if you compile the BVH code in..\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
project( convertOpenPoseJSONToCSV )
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
include_directories(${TENSORFLOW_INCLUDE_ROOT})
|
||||
|
||||
|
||||
#-----------------------------------------------
|
||||
# This is the converter utilities..
|
||||
#-----------------------------------------------
|
||||
add_executable(
|
||||
convertOpenPoseJSONToCSV
|
||||
convertOpenPoseJSONToCSV.cpp
|
||||
../../MocapNETLib2/tools.cpp
|
||||
../../MocapNETLib2/IO/jsonRead.cpp
|
||||
../../MocapNETLib2/IO/jsonMocapNETHelpers.cpp
|
||||
../../../../dependencies/InputParser/InputParser_C.cpp
|
||||
${BVH_SOURCE}
|
||||
${OPENGL_SOURCE}
|
||||
../../MocapNETLib2/IO/bvh.cpp
|
||||
../../MocapNETLib2/IO/csvWrite.cpp
|
||||
)
|
||||
|
||||
|
||||
#-----------------------------------------------
|
||||
|
||||
target_link_libraries(convertOpenPoseJSONToCSV rt dl m pthread MocapNETLib2)
|
||||
set_target_properties(convertOpenPoseJSONToCSV PROPERTIES DEBUG_POSTFIX "D")
|
||||
set_target_properties(convertOpenPoseJSONToCSV PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Export utility from OpenPose BODY25 + Hands + Face JSON format to a trivially parseable CSV file
|
||||
* Check https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/output.md on more information on OpenPose JSON files..
|
||||
*
|
||||
* Sample call : ./convertOpenPoseJSONToCSV --from frames/GOPR3223.MP4-data/ --label colorFrame_0_ -o .
|
||||
*
|
||||
* This utility converts OpenPose json output to a CSV file that can be easily parsed and used as MocapNET input
|
||||
*
|
||||
* My workflow when working with OpenPose is first dumping any video file that I want to process (let's call it video.mp4) to images using ffmpeg.
|
||||
* This ensures a well defined framerate and a well defined 1:1 correspondence of color/json/and my output frames regardless of video container.
|
||||
*
|
||||
* I typically use this script -> https://github.com/AmmarkoV/RGBDAcquisition/blob/master/grabber/frames/dump_video.sh to dump the video to files
|
||||
* but it is equivalent to running :
|
||||
* mkdir videoFiles && ffmpeg -i video.mp4 -r 30 -q:v 1 videoFiles/colorFrame_0_%05d.jpg && cp videoFiles/colorFrame_0_00001.jpg videoFiles/colorFrame_0_00000.jpg
|
||||
*
|
||||
* Having a well defined serialized version of the dataset ( with serial numbers that start from 0 instead of 1 ) we can be sure on what frame each openpose output will correspond
|
||||
*
|
||||
* Running :
|
||||
* openpose.bin -number_people_max 1 --hand --face --write_json videoFiles/ -image_dir videoFiles/
|
||||
*
|
||||
* The directory will be populated with colorFrame_0_xxxxx_keypoints.json files
|
||||
* each of the colorFrame_0_xxxxx_keypoints.json will correspond to a colorFrame_0_xxxxx.jpg
|
||||
*
|
||||
* This can then be converted to a CSV file using :
|
||||
* ./convertOpenPoseJSONToCSV --from videoFiles/
|
||||
*
|
||||
*
|
||||
* If you want to use a custom json labeling scheme and not rely on images as OpenPose input you will need to :
|
||||
*
|
||||
* 1) provide the proper image resolution ( since the JSON files alone do not have this information )
|
||||
* The image resolution is *CRUCIAL* for the software to correctly normalize input 2D points and respect the training aspect ratio
|
||||
* if you don't supply the correct size a Full-HD(1920x1080p) input will be assumed. If this does not correspond to the original video resolution output will be adversly affected
|
||||
* You can do this with the --size WIDTH HEIGHT parameter
|
||||
*
|
||||
* 2) Depending on your datasets and filenames supply the proper number of characters for a valid serial frame number length
|
||||
* i.e. frame_xxxxx_keypoints.json needs --seriallength 5
|
||||
* frame_xxxxxxx_keypoints.json needs --seriallength 7
|
||||
* etc
|
||||
*
|
||||
* 3) Depending on your datasets and filenames supply the correct label for the dataset
|
||||
* i.e. datasetNameA_xxxxx_keypoints.json needs --label datasetNameA
|
||||
* AMoreComplexLabel_IsTHIS_0_xxxxxxx_keypoints.json needs --label AMoreComplexLabel_IsTHIS_0
|
||||
* etc
|
||||
*
|
||||
* 4) Depending on the starting frame and ending frame of your dataset supply the --startAt X , --maxFrames X
|
||||
* i.e dataset_00001_keypoints.json - dataset_00101_keypoints.json should need --startAt 1 --maxFrames 102
|
||||
* i.e dataset_00000_keypoints.json - dataset_0099_keypoints.json should need --startAt 0 --maxFrames 100
|
||||
*
|
||||
* */
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../../MocapNET2/MocapNETLib2/tools.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/commonSkeleton.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/jsonRead.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/csvRead.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/csvWrite.hpp"
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
int findFirstJSONFileInDirectory(const char * path,const char * formatString, const char * label, unsigned int * frameIDOutput)
|
||||
{
|
||||
char filePathOfJSONFile[1025]={0};
|
||||
const int maximumFilesToSearchFor=1000;
|
||||
unsigned int frameID=0;
|
||||
int found=0;
|
||||
while (!found)
|
||||
{
|
||||
snprintf(filePathOfJSONFile,1024,formatString,path,label,frameID);
|
||||
|
||||
if( fileExists(filePathOfJSONFile) )
|
||||
{
|
||||
*frameIDOutput=frameID;
|
||||
return 1;
|
||||
}
|
||||
|
||||
++frameID;
|
||||
if (frameID==maximumFilesToSearchFor)
|
||||
{
|
||||
fprintf(stderr,"Stopping search after %u checks ..\n",maximumFilesToSearchFor);
|
||||
break;
|
||||
//return 0;
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"findFirstJSONFileInDirectory: failed to find any JSON files.. :(\n");
|
||||
fprintf(stderr,"Path : %s \n",path);
|
||||
fprintf(stderr,"Format : %s \n",formatString);
|
||||
fprintf(stderr,"Label : %s \n",label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int respectTrainingAspectRatio = 1;
|
||||
unsigned int width=1920 , height=1080 , frameLimit=100000 , processed = 0 , serialLength = 5 ,forcedSize=0;
|
||||
const char * path=0;
|
||||
const char * label=0;
|
||||
char outputPathFull[2048]={0};
|
||||
const char * outputPath=0;
|
||||
float version=1.4;
|
||||
int noLabel=0;
|
||||
float acceptableThreshold = 0.5;
|
||||
|
||||
for (int i=0; i<argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--maxFrames")==0)
|
||||
{
|
||||
frameLimit=atoi(argv[i+1]);
|
||||
}
|
||||
else if (strcmp(argv[i],"--from")==0)
|
||||
{
|
||||
path = argv[i+1];
|
||||
}
|
||||
else if (strcmp(argv[i],"--threshold")==0)
|
||||
{
|
||||
acceptableThreshold = atof(argv[i+1]);
|
||||
}
|
||||
else if (strcmp(argv[i],"-i")==0)
|
||||
{
|
||||
path = argv[i+1];
|
||||
}
|
||||
else if (strcmp(argv[i],"--label")==0)
|
||||
{
|
||||
label = argv[i+1];
|
||||
}
|
||||
else if (strcmp(argv[i],"--out")==0)
|
||||
{
|
||||
outputPath = argv[i+1];
|
||||
}
|
||||
else if (strcmp(argv[i],"--ignoreTrainingAspectRatio")==0)
|
||||
{
|
||||
fprintf(stderr,RED "Training aspect ratio is going to be ignored during training..!\n" NORMAL);
|
||||
fprintf(stderr,RED "this is not a good idea unless you really know what you are doing\n" NORMAL);
|
||||
respectTrainingAspectRatio = 0;
|
||||
}
|
||||
else if (strcmp(argv[i],"-o")==0)
|
||||
{
|
||||
outputPath = argv[i+1];
|
||||
}
|
||||
else if (strcmp(argv[i],"--to")==0)
|
||||
{
|
||||
outputPath = argv[i+1];
|
||||
}
|
||||
else if (strcmp(argv[i],"-v")==0)
|
||||
{
|
||||
version = atof(argv[i+1]);
|
||||
}
|
||||
else if (strcmp(argv[i],"--seriallength")==0)
|
||||
{
|
||||
serialLength = atoi(argv[i+1]);
|
||||
}
|
||||
else if (strcmp(argv[i],"--size")==0)
|
||||
{
|
||||
width = atoi(argv[i+1]);
|
||||
height = atoi(argv[i+2]);
|
||||
forcedSize=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--nolabel")==0)
|
||||
{
|
||||
//New datasets dont have a label in the filename..!
|
||||
noLabel =1 ;
|
||||
}
|
||||
}
|
||||
|
||||
if (path==0)
|
||||
{
|
||||
path="./";
|
||||
}
|
||||
|
||||
if (label==0)
|
||||
{
|
||||
label="colorFrame_0_";
|
||||
}
|
||||
if (noLabel)
|
||||
{
|
||||
label="";
|
||||
}
|
||||
|
||||
if (outputPath==0)
|
||||
{
|
||||
snprintf(outputPathFull,2048,"%s/2dJoints_v%0.1f.csv",path,version);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strstr(outputPath,".csv")!=0)
|
||||
{
|
||||
fprintf(stderr,"Output path is actually a csv file so treating it as one..\n");
|
||||
snprintf(outputPathFull,2048,"%s",outputPath);
|
||||
} else
|
||||
{
|
||||
snprintf(outputPathFull,2048,"%s/2dJoints_v%0.1f.csv",outputPath,version);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char formatString[256]= {0};
|
||||
char filePathOfJSONFile[2048]= {0};
|
||||
|
||||
snprintf(formatString,256,"%%s/%%s%%0%uu.jpg",serialLength);
|
||||
snprintf(filePathOfJSONFile,2048,formatString,path,label,1/*Frame ID*/);
|
||||
snprintf(formatString,256,"%%s/%%s%%0%uu_keypoints.json",serialLength);
|
||||
|
||||
if (!forcedSize)
|
||||
{
|
||||
if ( getImageWidthHeight(filePathOfJSONFile,&width,&height) )
|
||||
{
|
||||
fprintf(stderr,"Image dimensions changed from default to %ux%u",width,height);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Assuming default image dimensions %ux%u , you can change this using --size x y\n",width,height);
|
||||
}
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,"Forcing size due to --size %u %u commandline parameter\n",width,height);
|
||||
}
|
||||
|
||||
|
||||
float totalTime=0.0;
|
||||
unsigned int totalSamples=0;
|
||||
|
||||
struct skeletonStructure skeleton;
|
||||
memset(&skeleton,0,sizeof(struct skeletonStructure));
|
||||
|
||||
unsigned int frameID=1;
|
||||
|
||||
fprintf(stderr,"Threshold is set to %0.2f\n",acceptableThreshold);
|
||||
fprintf(stderr,"Processing : \n");
|
||||
|
||||
if ( findFirstJSONFileInDirectory(path, formatString,label,&frameID) )
|
||||
{
|
||||
frameLimit+=frameID;
|
||||
fprintf(stderr,"First frame is %u, last will be %u \n",frameID,frameLimit);
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,RED "Failed to find a JSON file..!\n " NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
while (frameID<frameLimit)
|
||||
{
|
||||
snprintf(filePathOfJSONFile,1024,formatString,path,label,frameID);
|
||||
fprintf(stderr,"%s (%ux%u)\n",filePathOfJSONFile,width,height);
|
||||
|
||||
if (parseJsonCOCOSkeleton(filePathOfJSONFile,&skeleton,acceptableThreshold,processed))
|
||||
{
|
||||
if (processed==0)
|
||||
{
|
||||
writeOpenPoseCSVHeaderFromSkeleton(outputPathFull,&skeleton,width,height);
|
||||
}
|
||||
|
||||
if (skeleton.leftHand.isPopulated) { fprintf(stderr,GREEN "Left Hand " NORMAL); }
|
||||
if (skeleton.rightHand.isPopulated) { fprintf(stderr,GREEN "Right Hand " NORMAL); }
|
||||
if (skeleton.body.isPopulated) { fprintf(stderr,GREEN "Body " NORMAL); }
|
||||
if (skeleton.head.isPopulated) { fprintf(stderr,GREEN "Head " NORMAL); }
|
||||
|
||||
writeOpenPoseCSVBodyFromSkeleton(outputPathFull,&skeleton,respectTrainingAspectRatio,width,height);
|
||||
++processed;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Done processing %u frames..\n",frameID);
|
||||
fprintf(stderr,"Output has been stored at %s \n",outputPathFull);
|
||||
break;
|
||||
}
|
||||
|
||||
++frameID;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
project( convertCSV3DToMocapNETInput )
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
include_directories(${TENSORFLOW_INCLUDE_ROOT})
|
||||
|
||||
#-----------------------------------------------
|
||||
# This is the converter utilities..
|
||||
#-----------------------------------------------
|
||||
add_executable(
|
||||
convertCSV3DToMocapNETInput
|
||||
convertCSV3DToMocapNETInput.cpp
|
||||
../../MocapNETLib2/tools.cpp
|
||||
../../MocapNETLib2/IO/jsonRead.cpp
|
||||
../../MocapNETLib2/IO/jsonMocapNETHelpers.cpp
|
||||
../../../../dependencies/InputParser/InputParser_C.cpp
|
||||
${BVH_SOURCE}
|
||||
${OPENGL_SOURCE}
|
||||
../../MocapNETLib2/IO/bvh.cpp
|
||||
../../MocapNETLib2/IO/conversions.cpp
|
||||
../../MocapNETLib2/IO/csvRead.cpp
|
||||
../../MocapNETLib2/IO/csvWrite.cpp
|
||||
)
|
||||
|
||||
#-----------------------------------------------
|
||||
|
||||
target_link_libraries(convertCSV3DToMocapNETInput rt dl m pthread MocapNETLib2)
|
||||
set_target_properties(convertCSV3DToMocapNETInput PROPERTIES DEBUG_POSTFIX "D")
|
||||
set_target_properties(convertCSV3DToMocapNETInput PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
+322
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Export utility from OpenPose BODY 25 JSON format to a more regular CSV file
|
||||
* Sample call : ./convertBody25JSONToCSV --from frames/GOPR3223.MP4-data/ --label colorFrame_0_ -o .
|
||||
* */
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../../MocapNET2/MocapNETLib2/tools.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/commonSkeleton.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/jsonRead.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/csvRead.hpp"
|
||||
#include "../../../MocapNET2/MocapNETLib2/IO/csvWrite.hpp"
|
||||
|
||||
|
||||
#if USE_BVH
|
||||
#include "../../../../dependencies/RGBDAcquisition/tools/AmMatrix/matrix4x4Tools.h"
|
||||
#include "../../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/bvh_loader.h"
|
||||
#include "../../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/calculate/bvh_project.h"
|
||||
#include "../../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/calculate/bvh_transform.h"
|
||||
#include "../../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/src/Library/MotionCaptureLoader/ik/bvh_inverseKinematics.h"
|
||||
#else
|
||||
#warning "BVH code not included.."
|
||||
#endif // USE_BVH
|
||||
|
||||
|
||||
#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 main(int argc, char *argv[])
|
||||
{
|
||||
#if USE_BVH
|
||||
|
||||
float fX = 582.18394; //570.0
|
||||
float fY = 582.52915; //570.0
|
||||
unsigned int width = 1920;
|
||||
unsigned int height = 1080;
|
||||
|
||||
struct simpleRenderer renderer= {0};
|
||||
|
||||
simpleRendererDefaults(
|
||||
&renderer,
|
||||
width,//1920
|
||||
height,//1080
|
||||
fX, //570.0
|
||||
fY //570.0
|
||||
);
|
||||
|
||||
simpleRendererInitialize(&renderer);
|
||||
|
||||
const char * path=0;
|
||||
const char * label=0;
|
||||
char outputPathFull[2048]= {"./handToMnet.csv"};
|
||||
const char * outputPath=outputPathFull;
|
||||
|
||||
float scale2DX=1.0,scale2DY=1.0;
|
||||
float offset2DX=0,offset2DY=0;
|
||||
|
||||
float scale3DX=1.0,scale3DY=1.0,scale3DZ=-1.0;
|
||||
float offset3DX=0.0,offset3DY=0.0,offset3DZ=0.0;
|
||||
|
||||
int flipX=0;
|
||||
int flipY=1;
|
||||
|
||||
unsigned int thereIsALineLimit=0;
|
||||
unsigned int maxLinesToProcess=0;
|
||||
|
||||
// ./convertCSV3DToMocapNETInput --from /home/ammar/Documents/Datasets/STB/test.csv --to /home/ammar/Documents/Datasets/STB/test2D.csv --meters --flipY --offset3D 0 0 -100
|
||||
|
||||
|
||||
int i=0;
|
||||
while (i<argc)
|
||||
{
|
||||
if (strcmp(argv[i],"--from")==0)
|
||||
{
|
||||
path = argv[i+1];
|
||||
i+=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--to")==0)
|
||||
{
|
||||
outputPath = argv[i+1];
|
||||
i+=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--maxFrames")==0)
|
||||
{
|
||||
thereIsALineLimit=1;
|
||||
maxLinesToProcess=atoi(argv[i+1]);
|
||||
i+=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--meters")==0)
|
||||
{
|
||||
scale3DX = 1000.0;
|
||||
scale3DY = 1000.0;
|
||||
scale3DZ = 1000.0;
|
||||
}
|
||||
else if (strcmp(argv[i],"--scale3D")==0)
|
||||
{
|
||||
scale3DX=atof(argv[i+1]);
|
||||
scale3DY=atof(argv[i+2]);
|
||||
scale3DZ=atof(argv[i+3]);
|
||||
i+=3;
|
||||
}
|
||||
else if (strcmp(argv[i],"--offset3D")==0)
|
||||
{
|
||||
offset3DX=atof(argv[i+1]);
|
||||
offset3DY=atof(argv[i+2]);
|
||||
offset3DZ=atof(argv[i+3]);
|
||||
i+=3;
|
||||
}
|
||||
else if (strcmp(argv[i],"--scale2D")==0)
|
||||
{
|
||||
scale2DX=atof(argv[i+1]);
|
||||
scale2DY=atof(argv[i+2]);
|
||||
i+=2;
|
||||
}
|
||||
else if (strcmp(argv[i],"--offset2D")==0)
|
||||
{
|
||||
offset2DX=atof(argv[i+1]);
|
||||
offset2DY=atof(argv[i+2]);
|
||||
i+=2;
|
||||
}
|
||||
else if (strcmp(argv[i],"--flipX")==0)
|
||||
{
|
||||
if (flipX)
|
||||
{
|
||||
flipX=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
flipX=1;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--flipY")==0)
|
||||
{
|
||||
if (flipY)
|
||||
{
|
||||
flipY=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
flipY=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Unknown parameter : %s \n" NORMAL,argv[i]);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
fprintf(stderr,"\n\n\n\nConversion from 3D CSV ground truth file configuration\n");
|
||||
fprintf(stderr,"_____________________________________________________________\n");
|
||||
fprintf(stderr,"3D input will have following modifiers : \n");
|
||||
fprintf(stderr," Scale | %0.2f | %0.2f | %0.2f \n",scale3DX,scale3DY,scale3DZ);
|
||||
fprintf(stderr," Offset | %0.2f | %0.2f | %0.2f \n",offset3DX,offset3DY,offset3DZ);
|
||||
|
||||
fprintf(stderr,"\nVirtual Camera : \n");
|
||||
fprintf(stderr," Width=%0.2f Height=%0.2f\n",renderer.width,renderer.height);
|
||||
fprintf(stderr," fX=%0.2f fY=%0.2f cX=%0.2f cY=%0.2f \n",renderer.fx,renderer.fy,renderer.cx,renderer.cy);
|
||||
|
||||
fprintf(stderr,"\n2D output will have following modifiers : \n");
|
||||
fprintf(stderr," Scale | %0.2f | %0.2f \n",scale2DX,scale2DY);
|
||||
fprintf(stderr," Offset | %0.2f | %0.2f \n",offset2DX,offset2DY);
|
||||
|
||||
fprintf(stderr,"\nFile I/O : \n");
|
||||
fprintf(stderr," 3D CSV ground truth file: `%s`\n",path);
|
||||
fprintf(stderr," 2D CSV output file: `%s`\n",outputPath);
|
||||
fprintf(stderr,"_____________________________________________________________\n");
|
||||
|
||||
|
||||
std::vector<std::vector<float> > result;
|
||||
std::vector<float> points2DOfASpecificFrame;
|
||||
|
||||
struct CSVFileContext csv= {0};
|
||||
struct CSVFloatFileLine csvLine= {0};
|
||||
unsigned int linesProcessed=0;
|
||||
|
||||
|
||||
if ( openCSVFile(&csv,path) )
|
||||
{
|
||||
parseCSVHeader(&csv);
|
||||
|
||||
fprintf(stderr,"%u columns of %u points to be outputted : ",csv.numberOfHeaderFields,(unsigned int) csv.numberOfHeaderFields/3);
|
||||
for (unsigned int pointID=0; pointID<csv.numberOfHeaderFields; pointID++)
|
||||
{
|
||||
if (pointID!=0)
|
||||
{
|
||||
fprintf(stderr,",");
|
||||
}
|
||||
|
||||
fprintf(stderr,"%s",csv.field[pointID].str);
|
||||
}
|
||||
fprintf(stderr,"\n_____________________________________________________________\n");
|
||||
|
||||
while ( (parseNextCSVFloatLine(&csv,&csvLine)) && ( (!thereIsALineLimit) || (linesProcessed+1<maxLinesToProcess) ) )
|
||||
{
|
||||
points2DOfASpecificFrame.clear();
|
||||
|
||||
float pos3D[4]= {0};
|
||||
float position2DX=0.0,position2DY=0.0,position2DW=0.0;
|
||||
float position2DOutputX=0.0,position2DOutputY=0.0;
|
||||
|
||||
float center[4]= {0};
|
||||
float rotation[3]= {0};
|
||||
|
||||
|
||||
for (unsigned int pointID=0; pointID<csv.numberOfHeaderFields/3; pointID++)
|
||||
{
|
||||
//--------------------------------------
|
||||
pos3D[0]=(float) (scale3DX*csvLine.field[pointID * 3 + 0]) + offset3DX;
|
||||
pos3D[1]=(float) (scale3DY*csvLine.field[pointID * 3 + 1]) + offset3DY;
|
||||
pos3D[2]=(float) (scale3DZ*csvLine.field[pointID * 3 + 2]) + offset3DZ;
|
||||
pos3D[3]=1.0;
|
||||
//fprintf(stderr,"Projecting %0.2f,%0.2f,%0.2f : ",pos3D[0],pos3D[1],pos3D[2]);
|
||||
//--------------------------------------
|
||||
if (
|
||||
simpleRendererRender(
|
||||
&renderer,
|
||||
pos3D,
|
||||
center,
|
||||
rotation,
|
||||
ROTATION_ORDER_RPY,
|
||||
&position2DX,
|
||||
&position2DY,
|
||||
&position2DW)
|
||||
)
|
||||
{
|
||||
if (flipX) { position2DX = width - position2DX; }
|
||||
if (flipY) { position2DY = height - position2DY; }
|
||||
|
||||
position2DOutputX=0.0;
|
||||
position2DOutputY=0.0;
|
||||
|
||||
if (position2DW>0.0)
|
||||
{
|
||||
//fprintf(stderr,"output is %0.2f,%0.2f \n",position2DX,position2DY);
|
||||
position2DOutputX = (scale2DX*position2DX) + offset2DX;
|
||||
position2DOutputY = (scale2DY*position2DY) + offset2DY;
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr,"behind camera(%0.2f).. %0.2f,%0.2f \n",position2DW,position2DX,position2DY);
|
||||
}
|
||||
|
||||
//We normalize our 2D output..!
|
||||
position2DOutputX=(float) position2DOutputX/renderer.width;
|
||||
position2DOutputY=(float) position2DOutputY/renderer.height;
|
||||
|
||||
fprintf(stderr,"3D %0.2f,%0.2f,%0.2f => 2D %0.2f,%0.2f \n",pos3D[0],pos3D[1],pos3D[2],position2DOutputX,position2DOutputY);
|
||||
points2DOfASpecificFrame.push_back(position2DOutputX);
|
||||
points2DOfASpecificFrame.push_back(position2DOutputY);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
points2DOfASpecificFrame.push_back(0.0);
|
||||
points2DOfASpecificFrame.push_back(0.0);
|
||||
}
|
||||
} //For every point in this CSV line
|
||||
|
||||
result.push_back(points2DOfASpecificFrame);
|
||||
++linesProcessed;
|
||||
}//While we there are more lines to process
|
||||
|
||||
|
||||
if (result.size()>0)
|
||||
{
|
||||
FILE * fp = fopen(outputPath,"w");
|
||||
if (fp!=0)
|
||||
{
|
||||
|
||||
fprintf(fp,"frameNumber,skeletonID,totalSkeletons");
|
||||
|
||||
for (unsigned int pointID=0; pointID<csv.numberOfHeaderFields/3; pointID++)
|
||||
{
|
||||
char * pointLabel = csv.field[pointID*3].str + 4; //This is the fastest way to get rid of the `3D*_` part of the stream
|
||||
|
||||
//Translate H36M labels to MNET labels..
|
||||
if ( strcmp(pointLabel,"nose")==0 ) { fprintf(fp,",2DX_head,2DY_head,visible_head"); } else
|
||||
if ( strcmp(pointLabel,"rwrist")==0 ) { fprintf(fp,",2DX_rhand,2DY_rhand,visible_rhand"); } else
|
||||
if ( strcmp(pointLabel,"lwrist")==0 ) { fprintf(fp,",2DX_lhand,2DY_lhand,visible_lhand"); } else
|
||||
if ( strcmp(pointLabel,"midhip")==0 ) { fprintf(fp,",2DX_hip,2DY_hip,visible_hip"); } else
|
||||
if ( strcmp(pointLabel,"rheel")==0 ) { fprintf(fp,",2DX_rfoot,2DY_rfoot,visible_rfoot"); } else //rankle/lankle instead..
|
||||
if ( strcmp(pointLabel,"lheel")==0 ) { fprintf(fp,",2DX_lfoot,2DY_lfoot,visible_lfoot"); } else
|
||||
if ( strcmp(pointLabel,"reye")==0 ) { fprintf(fp,",2DX_endsite_eye.r,2DY_endsite_eye.r,visible_endsite_eye.r"); } else
|
||||
if ( strcmp(pointLabel,"leye")==0 ) { fprintf(fp,",2DX_endsite_eye.l,2DY_endsite_eye.l,visible_endsite_eye.l"); } else
|
||||
if ( strcmp(pointLabel,"rbigtoe")==0 ) { fprintf(fp,",2DX_endsite_toe1-2.r,2DY_endsite_toe1-2.r,visible_endsite_toe1-2.r"); } else
|
||||
if ( strcmp(pointLabel,"lbigtoe")==0 ) { fprintf(fp,",2DX_endsite_toe1-2.l,2DY_endsite_toe1-2.l,visible_endsite_toe1-2.l"); } else
|
||||
if ( strcmp(pointLabel,"rsmalltoe")==0 ) { fprintf(fp,",2DX_endsite_toe5-3.r,2DY_endsite_toe5-3.r,visible_endsite_toe5-3.r"); } else
|
||||
if ( strcmp(pointLabel,"lsmalltoe")==0 ) { fprintf(fp,",2DX_endsite_toe5-3.l,2DY_endsite_toe5-3.l,visible_endsite_toe5-3.l"); } else
|
||||
{ fprintf(fp,",2DX_%s,2DY_%s,visible_%s",pointLabel,pointLabel,pointLabel); }
|
||||
}
|
||||
fprintf(fp,"\n");
|
||||
|
||||
for (unsigned int frameID=0; frameID<result.size(); frameID++)
|
||||
{
|
||||
fprintf(fp,"%u,0,0",frameID);
|
||||
for (unsigned int pointID=0; pointID<result[frameID].size(); pointID++)
|
||||
{
|
||||
if ( pointID%2==0) { fprintf(fp,",%f",result[frameID][pointID]); } else
|
||||
{ fprintf(fp,",%f,1",result[frameID][pointID]); }
|
||||
}
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
closeCSVFile(&csv);
|
||||
} //CSV file can be successfully opened
|
||||
#else
|
||||
fprintf(stderr,"This utility is only available if you compile the BVH code in..\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import numpy as np
|
||||
import gc
|
||||
import os
|
||||
import sys
|
||||
import csv
|
||||
import time
|
||||
import array
|
||||
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.animation as animation
|
||||
from mpl_toolkits.mplot3d import axes3d, Axes3D
|
||||
|
||||
width=1920.0
|
||||
height=1080.0
|
||||
|
||||
|
||||
class bcolors:
|
||||
HEADER = '\033[95m'
|
||||
OKBLUE = '\033[94m'
|
||||
OKGREEN = '\033[92m'
|
||||
WARNING = '\033[93m'
|
||||
FAIL = '\033[91m'
|
||||
ENDC = '\033[0m'
|
||||
BOLD = '\033[1m'
|
||||
UNDERLINE = '\033[4m'
|
||||
|
||||
def pointListReturnXYListForScatterPlot(A):
|
||||
numberOfPoints=A.shape[0]
|
||||
xs=list()
|
||||
ys=list()
|
||||
frameNumber=A[0]
|
||||
skeletonID=A[1]
|
||||
totalSkeletons=A[2]
|
||||
for i in range(3,int(numberOfPoints/3)):
|
||||
x=width*float(A[i*3+0])
|
||||
y=height*float(A[i*3+1])
|
||||
visibility=int(A[i*3+2])
|
||||
if (visibility==1):
|
||||
xs.append(x)
|
||||
ys.append(y)
|
||||
print('Point(',x,',',y,')')
|
||||
return xs,ys
|
||||
|
||||
def checkIfFileExists(filename):
|
||||
return os.path.isfile(filename)
|
||||
|
||||
def convert_bytes(num):
|
||||
"""
|
||||
this function will convert bytes to MB.... GB... etc
|
||||
"""
|
||||
step_unit = 1000.0 #1024 bad the size
|
||||
|
||||
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
|
||||
if num < step_unit:
|
||||
return "%3.1f %s" % (num, x)
|
||||
num /= step_unit
|
||||
|
||||
def getNumberOfLines(filename):
|
||||
print("Counting number of lines in file ",filename)
|
||||
with open(filename) as f:
|
||||
return sum(1 for line in f)
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
def readCSVFile(filename,memPercentage,csvDelimiter,useHalfFloats,groupOutput):
|
||||
print("CSV file :",filename,"..\n")
|
||||
|
||||
if (not checkIfFileExists(filename)):
|
||||
print( bcolors.WARNING + "Input file "+filename+" does not exist, cannot read ground truth.." + bcolors.ENDC)
|
||||
print("Current Directory was "+os.getcwd())
|
||||
sys.exit(0)
|
||||
start = time.time()
|
||||
|
||||
dtypeSelected=np.dtype(np.float32)
|
||||
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
|
||||
if (useHalfFloats):
|
||||
dtypeSelected=np.dtype(np.float16)
|
||||
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
|
||||
|
||||
progress=0.0
|
||||
sampleNumber=0
|
||||
receivedHeader=0
|
||||
inputNumberOfColumns=0
|
||||
|
||||
inputLabels=list()
|
||||
|
||||
#-------------------------------------------------------------------------------------------------
|
||||
numberOfSamplesInput=getNumberOfLines(filename)-2
|
||||
print(" Input file has ",numberOfSamplesInput," training samples\n")
|
||||
#-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
numberOfSamples = numberOfSamplesInput
|
||||
numberOfSamplesLimit=int(numberOfSamples*memPercentage)
|
||||
#-------------------------------------------------------------------------------------------------
|
||||
if (memPercentage==0.0):
|
||||
print("readGroundTruthFile was asked to occupy 0 memory so this probably means we just want one record")
|
||||
numberOfSamplesLimit=2
|
||||
if (memPercentage>1.0):
|
||||
print("Memory Limit will be interpreted as a raw value..")
|
||||
numberOfSamplesLimit=int(memPercentage)
|
||||
#-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
thisInput = array.array('f')
|
||||
#---------------------------------
|
||||
|
||||
fi = open(filename, "r")
|
||||
readerIn = csv.reader( fi , delimiter=csvDelimiter, skipinitialspace=True)
|
||||
for rowIn in readerIn:
|
||||
#------------------------------------------------------
|
||||
if (not receivedHeader): #use header to get labels
|
||||
#------------------------------------------------------
|
||||
inputNumberOfColumns=len(rowIn)
|
||||
|
||||
#Make sure CSV files that end with delimiter are correctly handled..
|
||||
if (inputNumberOfColumns>0):
|
||||
if (rowIn[inputNumberOfColumns-1]==''):
|
||||
inputNumberOfColumns=inputNumberOfColumns-1
|
||||
#-----------------------------------------------------
|
||||
inputLabels = list(rowIn[i] for i in range(0,inputNumberOfColumns) )
|
||||
print("Number of Input elements : ",len(inputLabels))
|
||||
#------------------------------------------------------
|
||||
|
||||
if (memPercentage==0):
|
||||
print("Will only return labels\n")
|
||||
return {'labels':inputLabels};
|
||||
|
||||
|
||||
#i=0
|
||||
#print("class Input(Enum):")
|
||||
#for label in inputLabels:
|
||||
# print(" ",label," = ",i," #",int(i/3))
|
||||
# print(" ",label,"=",int(i/3))
|
||||
# i=i+1
|
||||
|
||||
#---------------------------------
|
||||
# Allocate Lists
|
||||
#---------------------------------
|
||||
for i in range(inputNumberOfColumns):
|
||||
thisInput.append(0.0)
|
||||
#---------------------------------
|
||||
|
||||
|
||||
#---------------------------------
|
||||
# Allocate Numpy Arrays
|
||||
#---------------------------------
|
||||
inputSize=0
|
||||
startCompressed=0
|
||||
|
||||
inputSize=inputSize+inputNumberOfColumns
|
||||
startCompressed=inputNumberOfColumns
|
||||
|
||||
npInputBytesize=0+numberOfSamplesLimit * inputSize * dtypeSelectedByteSize
|
||||
print(" Input file on disk has a shape of [",numberOfSamples,",",inputSize,"]")
|
||||
print(" Input we will read has a shape of [",numberOfSamplesLimit,",",inputSize,"]")
|
||||
print(" Input will occupy ",convert_bytes(npInputBytesize)," of RAM\n")
|
||||
npInput = np.full([numberOfSamplesLimit,inputSize],fill_value=0,dtype=dtypeSelected,order='C')
|
||||
#----------------------------------------------------------------------------------------------------------
|
||||
receivedHeader=1
|
||||
#sys.exit(0)
|
||||
else:
|
||||
#-------------------------------------------
|
||||
# First convert our string INPUT to floats
|
||||
#-------------------------------------------
|
||||
for i in range(inputNumberOfColumns):
|
||||
thisInput[i]=float(rowIn[i])
|
||||
#-------------------------------------------
|
||||
for num in range(0,inputNumberOfColumns):
|
||||
npInput[sampleNumber,num]=float(thisInput[num]);
|
||||
#-------------------------------------------
|
||||
sampleNumber=sampleNumber+1
|
||||
|
||||
if (numberOfSamples>0):
|
||||
progress=sampleNumber/numberOfSamplesLimit
|
||||
|
||||
if (sampleNumber%1000==0) :
|
||||
progressString = "%0.2f"%float(100*progress)
|
||||
print("\rReading from disk (",sampleNumber,") - ",progressString," % \r", end="", flush=True)
|
||||
|
||||
if (numberOfSamplesLimit<=sampleNumber):
|
||||
print("\rStopping reading file to obey memory limit given by parameter --mem ",memPercentage,"\n")
|
||||
break
|
||||
#-------------------------------------------
|
||||
fi.close()
|
||||
del readerIn
|
||||
gc.collect()
|
||||
|
||||
|
||||
print("\n read, Samples: ",sampleNumber,", was expecting ",numberOfSamples," samples\n")
|
||||
print(npInput.shape)
|
||||
|
||||
totalNumberOfBytes=npInput.nbytes;
|
||||
totalNumberOfGigaBytes=totalNumberOfBytes/1073741824;
|
||||
print("Size Occupied by data = ",totalNumberOfGigaBytes," GB \n")
|
||||
|
||||
end = time.time()
|
||||
print("Time elapsed : ",(end-start)/60," mins")
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
if (groupOutput==0):
|
||||
#New better dictionary
|
||||
output = dict()
|
||||
for i in range(0,len(inputLabels)):
|
||||
lowerCaseName = inputLabels[i].lower()
|
||||
#print("Joint ",lowerCaseName)
|
||||
output[lowerCaseName]=list()
|
||||
for frameID in range(0,len(npInput)):
|
||||
output[lowerCaseName].append(npInput[frameID][i])
|
||||
return output
|
||||
else:
|
||||
#This is the old dictionary way (better for tensorflow training)
|
||||
return {'label':inputLabels, 'body':npInput };
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
drawPlot=1
|
||||
|
||||
ground=readCSVFile("test2D.csv",1.0,',',0,1)
|
||||
|
||||
|
||||
if (drawPlot):
|
||||
print("Using matplotlib:",matplotlib.__version__)
|
||||
# === Plot and animate ===
|
||||
fig = plt.figure()
|
||||
fig.set_size_inches(19.2, 10.8, forward=True)
|
||||
|
||||
ax = fig.add_subplot(1, 2, 1)
|
||||
ax2 = fig.add_subplot(1, 2, 2)
|
||||
#ax3 = fig.add_subplot(2, 2, 3)
|
||||
#ax4 = fig.add_subplot(2, 2, 4)
|
||||
fig.subplots_adjust(left=0.05, bottom=0.05, right=0.95, top=0.95)
|
||||
|
||||
ax.set_xlabel('X Axis')
|
||||
ax.set_ylabel('Y Axis')
|
||||
#ax.set_zlabel('Z Axis')
|
||||
#ax.view_init(90, 90)
|
||||
|
||||
|
||||
print("Ground truth file has %u elements ",len(ground['body']))
|
||||
|
||||
|
||||
for i in range(0,len(ground['body'])):
|
||||
if (drawPlot):
|
||||
plt.cla()
|
||||
ax.cla()
|
||||
ax2.cla()
|
||||
|
||||
xs, ys = pointListReturnXYListForScatterPlot(ground['body'][i])
|
||||
|
||||
ax.scatter(xs, ys)
|
||||
img = plt.imread("images/im%u.png" % i)
|
||||
ax2.imshow(img)
|
||||
|
||||
#-------------------------
|
||||
ax.set_xlim(auto=False,left=0,right=width)
|
||||
ax.set_ylim(auto=False,bottom=height,top=0)
|
||||
#ax.set_zlim(auto=False,bottom=2000,top=6000)
|
||||
ax.set_xlabel('X Axis')
|
||||
ax.set_ylabel('Y Axis')
|
||||
#ax.set_zlabel('Z Axis')
|
||||
#-------------------------
|
||||
plt.show(block=False)
|
||||
#plt.savefig('p%05u.png'%i)
|
||||
#fig.canvas.draw()
|
||||
plt.pause(0.102)
|
||||
@@ -0,0 +1,316 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import numpy as np
|
||||
import gc
|
||||
import os
|
||||
import sys
|
||||
import csv
|
||||
import time
|
||||
import array
|
||||
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.animation as animation
|
||||
from mpl_toolkits.mplot3d import axes3d, Axes3D
|
||||
|
||||
class bcolors:
|
||||
HEADER = '\033[95m'
|
||||
OKBLUE = '\033[94m'
|
||||
OKGREEN = '\033[92m'
|
||||
WARNING = '\033[93m'
|
||||
FAIL = '\033[91m'
|
||||
ENDC = '\033[0m'
|
||||
BOLD = '\033[1m'
|
||||
UNDERLINE = '\033[4m'
|
||||
|
||||
def pointListReturnXYZListForScatterPlot(A):
|
||||
numberOfPoints=A.shape[0]
|
||||
xs=list()
|
||||
ys=list()
|
||||
zs=list()
|
||||
for i in range(0,int(numberOfPoints/3)):
|
||||
xs.append(float(-1000*10*A[i*3+0]))
|
||||
ys.append(float(1000*10*A[i*3+1]))
|
||||
zs.append(float(1000*10*A[i*3+2]))
|
||||
return xs,ys,zs
|
||||
|
||||
def checkIfFileExists(filename):
|
||||
return os.path.isfile(filename)
|
||||
|
||||
def convert_bytes(num):
|
||||
"""
|
||||
this function will convert bytes to MB.... GB... etc
|
||||
"""
|
||||
step_unit = 1000.0 #1024 bad the size
|
||||
|
||||
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
|
||||
if num < step_unit:
|
||||
return "%3.1f %s" % (num, x)
|
||||
num /= step_unit
|
||||
|
||||
def getNumberOfLines(filename):
|
||||
print("Counting number of lines in file ",filename)
|
||||
with open(filename) as f:
|
||||
return sum(1 for line in f)
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
def readCSVFile(filename,memPercentage,csvDelimiter,useHalfFloats,groupOutput):
|
||||
print("CSV file :",filename,"..\n")
|
||||
|
||||
if (not checkIfFileExists(filename)):
|
||||
print( bcolors.WARNING + "Input file "+filename+" does not exist, cannot read ground truth.." + bcolors.ENDC)
|
||||
print("Current Directory was "+os.getcwd())
|
||||
sys.exit(0)
|
||||
start = time.time()
|
||||
|
||||
dtypeSelected=np.dtype(np.float32)
|
||||
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
|
||||
if (useHalfFloats):
|
||||
dtypeSelected=np.dtype(np.float16)
|
||||
dtypeSelectedByteSize=int(dtypeSelected.itemsize)
|
||||
|
||||
progress=0.0
|
||||
sampleNumber=0
|
||||
receivedHeader=0
|
||||
inputNumberOfColumns=0
|
||||
|
||||
inputLabels=list()
|
||||
|
||||
#-------------------------------------------------------------------------------------------------
|
||||
numberOfSamplesInput=getNumberOfLines(filename)-2
|
||||
print(" Input file has ",numberOfSamplesInput," training samples\n")
|
||||
#-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
numberOfSamples = numberOfSamplesInput
|
||||
numberOfSamplesLimit=int(numberOfSamples*memPercentage)
|
||||
#-------------------------------------------------------------------------------------------------
|
||||
if (memPercentage==0.0):
|
||||
print("readGroundTruthFile was asked to occupy 0 memory so this probably means we just want one record")
|
||||
numberOfSamplesLimit=2
|
||||
if (memPercentage>1.0):
|
||||
print("Memory Limit will be interpreted as a raw value..")
|
||||
numberOfSamplesLimit=int(memPercentage)
|
||||
#-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
thisInput = array.array('f')
|
||||
#---------------------------------
|
||||
|
||||
fi = open(filename, "r")
|
||||
readerIn = csv.reader( fi , delimiter=csvDelimiter, skipinitialspace=True)
|
||||
for rowIn in readerIn:
|
||||
#------------------------------------------------------
|
||||
if (not receivedHeader): #use header to get labels
|
||||
#------------------------------------------------------
|
||||
inputNumberOfColumns=len(rowIn)
|
||||
|
||||
#Make sure CSV files that end with delimiter are correctly handled..
|
||||
if (inputNumberOfColumns>0):
|
||||
if (rowIn[inputNumberOfColumns-1]==''):
|
||||
inputNumberOfColumns=inputNumberOfColumns-1
|
||||
#-----------------------------------------------------
|
||||
inputLabels = list(rowIn[i] for i in range(0,inputNumberOfColumns) )
|
||||
print("Number of Input elements : ",len(inputLabels))
|
||||
#------------------------------------------------------
|
||||
|
||||
if (memPercentage==0):
|
||||
print("Will only return labels\n")
|
||||
return {'labels':inputLabels};
|
||||
|
||||
|
||||
#i=0
|
||||
#print("class Input(Enum):")
|
||||
#for label in inputLabels:
|
||||
# print(" ",label," = ",i," #",int(i/3))
|
||||
# print(" ",label,"=",int(i/3))
|
||||
# i=i+1
|
||||
|
||||
#---------------------------------
|
||||
# Allocate Lists
|
||||
#---------------------------------
|
||||
for i in range(inputNumberOfColumns):
|
||||
thisInput.append(0.0)
|
||||
#---------------------------------
|
||||
|
||||
|
||||
#---------------------------------
|
||||
# Allocate Numpy Arrays
|
||||
#---------------------------------
|
||||
inputSize=0
|
||||
startCompressed=0
|
||||
|
||||
inputSize=inputSize+inputNumberOfColumns
|
||||
startCompressed=inputNumberOfColumns
|
||||
|
||||
npInputBytesize=0+numberOfSamplesLimit * inputSize * dtypeSelectedByteSize
|
||||
print(" Input file on disk has a shape of [",numberOfSamples,",",inputSize,"]")
|
||||
print(" Input we will read has a shape of [",numberOfSamplesLimit,",",inputSize,"]")
|
||||
print(" Input will occupy ",convert_bytes(npInputBytesize)," of RAM\n")
|
||||
npInput = np.full([numberOfSamplesLimit,inputSize],fill_value=0,dtype=dtypeSelected,order='C')
|
||||
#----------------------------------------------------------------------------------------------------------
|
||||
receivedHeader=1
|
||||
#sys.exit(0)
|
||||
else:
|
||||
#-------------------------------------------
|
||||
# First convert our string INPUT to floats
|
||||
#-------------------------------------------
|
||||
for i in range(inputNumberOfColumns):
|
||||
thisInput[i]=float(rowIn[i])
|
||||
#-------------------------------------------
|
||||
for num in range(0,inputNumberOfColumns):
|
||||
npInput[sampleNumber,num]=float(thisInput[num]);
|
||||
#-------------------------------------------
|
||||
sampleNumber=sampleNumber+1
|
||||
|
||||
if (numberOfSamples>0):
|
||||
progress=sampleNumber/numberOfSamplesLimit
|
||||
|
||||
if (sampleNumber%1000==0) :
|
||||
progressString = "%0.2f"%float(100*progress)
|
||||
print("\rReading from disk (",sampleNumber,") - ",progressString," % \r", end="", flush=True)
|
||||
|
||||
if (numberOfSamplesLimit<=sampleNumber):
|
||||
print("\rStopping reading file to obey memory limit given by parameter --mem ",memPercentage,"\n")
|
||||
break
|
||||
#-------------------------------------------
|
||||
fi.close()
|
||||
del readerIn
|
||||
gc.collect()
|
||||
|
||||
|
||||
print("\n read, Samples: ",sampleNumber,", was expecting ",numberOfSamples," samples\n")
|
||||
print(npInput.shape)
|
||||
|
||||
totalNumberOfBytes=npInput.nbytes;
|
||||
totalNumberOfGigaBytes=totalNumberOfBytes/1073741824;
|
||||
print("Size Occupied by data = ",totalNumberOfGigaBytes," GB \n")
|
||||
|
||||
end = time.time()
|
||||
print("Time elapsed : ",(end-start)/60," mins")
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
if (groupOutput==0):
|
||||
#New better dictionary
|
||||
output = dict()
|
||||
for i in range(0,len(inputLabels)):
|
||||
lowerCaseName = inputLabels[i].lower()
|
||||
#print("Joint ",lowerCaseName)
|
||||
output[lowerCaseName]=list()
|
||||
for frameID in range(0,len(npInput)):
|
||||
output[lowerCaseName].append(npInput[frameID][i])
|
||||
return output
|
||||
else:
|
||||
#This is the old dictionary way (better for tensorflow training)
|
||||
return {'label':inputLabels, 'body':npInput };
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
#---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
drawPlot=1
|
||||
|
||||
ground=readCSVFile("ground3D.csv",1.0,',',0,1)
|
||||
|
||||
|
||||
if (drawPlot):
|
||||
print("Using matplotlib:",matplotlib.__version__)
|
||||
# === Plot and animate ===
|
||||
fig = plt.figure()
|
||||
fig.set_size_inches(19.2, 10.8, forward=True)
|
||||
|
||||
ax = fig.add_subplot(1, 2, 1, projection='3d')
|
||||
ax2 = fig.add_subplot(1, 2, 2)
|
||||
#ax3 = fig.add_subplot(2, 2, 3)
|
||||
#ax4 = fig.add_subplot(2, 2, 4)
|
||||
fig.subplots_adjust(left=0.05, bottom=0.05, right=0.95, top=0.95)
|
||||
|
||||
ax.set_xlabel('X Axis')
|
||||
ax.set_ylabel('Y Axis')
|
||||
ax.set_zlabel('Z Axis')
|
||||
ax.view_init(90, 90)
|
||||
|
||||
|
||||
print("Ground truth file has %u elements ",len(ground['body']))
|
||||
|
||||
|
||||
for i in range(0,len(ground['body'])):
|
||||
if (drawPlot):
|
||||
plt.cla()
|
||||
ax.cla()
|
||||
ax2.cla()
|
||||
#ax3.cla()
|
||||
#ax4.cla()
|
||||
|
||||
|
||||
categories = np.array([0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20
|
||||
])
|
||||
|
||||
color0=(0.0, 1.0, 1.0, 1.0) #Palm
|
||||
color1=(0.6, 0.0, 0.0, 1.0) #Thumb
|
||||
color2=(0.8, 0.0, 0.0, 1.0) #Finger 1.2
|
||||
color3=(1.0, 0.0, 0.0, 1.0) #Finger 1.3
|
||||
color4=(0.0, 1.0, 1.0, 1.0) #BaseOfFourFingers
|
||||
color5=(0.0, 1.0, 0.0, 1.0) #Finger 2.3
|
||||
color6=(0.0, 0.8, 0.0, 1.0) #Finger 2.2
|
||||
color7=(0.0, 0.6, 0.0, 1.0) #Finger 2.1
|
||||
color8=(0.0, 0.4, 0.0, 1.0) #Metacarpal 1
|
||||
color9=(0.0, 0.0, 1.0, 1.0) #Finger 3.3
|
||||
color10=(0.0, 0.0, 0.8, 1.0) #Finger 3.2
|
||||
color11=(0.0, 0.0, 0.6, 1.0) #Finger 3.1
|
||||
color12=(0.0, 0.0, 0.4, 1.0) #Metacarpal 2
|
||||
color13=(0.0, 1.0, 1.0, 1.0) #Finger 4.3
|
||||
color14=(0.0, 0.8, 0.8, 1.0) #Finger 4.2
|
||||
color15=(0.0, 0.6, 0.6, 1.0) #Finger 4.1
|
||||
color16=(0.0, 0.4, 0.4, 1.0) #Metacarpal 3
|
||||
color17=(1.0, 1.0, 0.0, 1.0) #Finger 5.3
|
||||
color18=(0.8, 0.8, 0.0, 1.0) #Finger 5.2
|
||||
color19=(0.6, 0.6, 0.0, 1.0) #Finger 5.1
|
||||
color20=(0.4, 0.4, 0.0, 1.0) #Metacarpal 4
|
||||
|
||||
colormap = np.array([color0,color1,color2,color3,color4,color5,color6,color7,color8,color9,color10,color11,color12,color13,color14,color15,color16,color17,color18,color19,color20])
|
||||
|
||||
xs, ys, zs = pointListReturnXYZListForScatterPlot(ground['body'][i])
|
||||
|
||||
ax.scatter(xs, ys, zs, c=colormap[categories])
|
||||
img = plt.imread("images/im%u.png" % i)
|
||||
ax2.imshow(img)
|
||||
|
||||
#-------------------------
|
||||
ax.set_xlim(auto=False,left=-600,right=300)
|
||||
ax.set_ylim(auto=False,bottom=-1600,top=200)
|
||||
ax.set_zlim(auto=False,bottom=2000,top=6000)
|
||||
ax.set_xlabel('X Axis')
|
||||
ax.set_ylabel('Y Axis')
|
||||
ax.set_zlabel('Z Axis')
|
||||
#-------------------------
|
||||
plt.show(block=False)
|
||||
#plt.savefig('p%05u.png'%i)
|
||||
#fig.canvas.draw()
|
||||
plt.pause(0.001)
|
||||
@@ -0,0 +1,18 @@
|
||||
project( HandOnlyTest )
|
||||
cmake_minimum_required( VERSION 2.8.7 )
|
||||
#cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
find_package(OpenCV REQUIRED)
|
||||
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
|
||||
|
||||
add_executable(HandOnlyTest handTest.cpp)
|
||||
target_link_libraries(HandOnlyTest rt dl m ${OpenCV_LIBRARIES} Tensorflow TensorflowFramework MocapNETLib2 )
|
||||
set_target_properties(HandOnlyTest PROPERTIES DEBUG_POSTFIX "D")
|
||||
|
||||
|
||||
set_target_properties(HandOnlyTest PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
project( MocapNET2LiveWebcamDemo )
|
||||
cmake_minimum_required( VERSION 2.8.13 )
|
||||
#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})
|
||||
|
||||
|
||||
add_executable(MocapNET2LiveWebcamDemo livedemo.cpp )
|
||||
|
||||
target_link_libraries(MocapNET2LiveWebcamDemo rt dl m ${OpenCV_LIBRARIES} ${OPENGL_LIBS} JointEstimator2D Tensorflow TensorflowFramework MocapNETLib2 ${NETWORK_CLIENT_LIBRARIES} ${PNG_Libs} ${JPG_Libs} )
|
||||
set_target_properties(MocapNET2LiveWebcamDemo PROPERTIES DEBUG_POSTFIX "D")
|
||||
|
||||
|
||||
set_target_properties(MocapNET2LiveWebcamDemo PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,516 @@
|
||||
#include "opencv2/opencv.hpp"
|
||||
/** @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 "../../JointEstimator2D/cameraControl.hpp"
|
||||
#include "../../JointEstimator2D/jointEstimator2D.hpp"
|
||||
#include "../../JointEstimator2D/visualization.hpp"
|
||||
//-----------------------------------------------------------------
|
||||
#include "../../MocapNET2/MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/applicationLogic/parseCommandlineOptions.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/IO/commonSkeleton.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/IO/conversions.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/IO/bvh.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/IO/csvRead.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/IO/csvWrite.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/IO/skeletonAbstraction.hpp"
|
||||
//-----------------------------------------------------------------
|
||||
#include "../../MocapNET2/MocapNETLib2/visualization/visualization.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/visualization/map.hpp"
|
||||
//-----------------------------------------------------------------
|
||||
#include "../../MocapNET2/MocapNETLib2/tools.hpp"
|
||||
using namespace cv;
|
||||
|
||||
|
||||
#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 main(int argc, char *argv[])
|
||||
{
|
||||
struct MocapNET2Options options= {0};
|
||||
struct MocapNET2 mnet= {0};
|
||||
mnet.options = & options;
|
||||
|
||||
struct JointEstimator2D jointEstimator;
|
||||
|
||||
std::vector<float> inputValues;
|
||||
std::vector<std::vector<float> > exactMocapNET2DOutput;
|
||||
std::vector<std::vector<float> > output3DPositions;
|
||||
std::vector<float> points3DFlatOutput;
|
||||
|
||||
struct skeletonSerialized resultAsSkeletonSerialized= {0};
|
||||
|
||||
float frameRateSummary = 0.0;
|
||||
unsigned int frameSamples=0;
|
||||
|
||||
defaultMocapNET2Options(&options);
|
||||
|
||||
/*
|
||||
* Force effortless IK configuration on Webcam Demo
|
||||
*/
|
||||
//Be unconstrained by default
|
||||
options.constrainPositionRotation=0;
|
||||
//Use IK ========
|
||||
options.useInverseKinematics=1;
|
||||
options.learningRate=0.01;
|
||||
options.iterations=5;
|
||||
options.epochs=30.0;
|
||||
options.spring=1.0;
|
||||
//==============
|
||||
|
||||
//640x480 should be a high framerate compatible resolution
|
||||
//for most webcams, you can change this using --size X Y commandline parameter
|
||||
options.width = 640;
|
||||
options.height = 480;
|
||||
|
||||
|
||||
loadOptionsFromCommandlineOptions(&options,argc,argv);
|
||||
|
||||
std::cerr<<"Trying to open source ("<<options.webcamSource<<") \n";
|
||||
VideoCapture cap(options.webcamSource); // open the default camera
|
||||
|
||||
int itIsTheFirstFrame=1;
|
||||
Mat singleImageFrame;
|
||||
Mat frame;
|
||||
Mat frameCentered;
|
||||
|
||||
if (
|
||||
(strstr(options.webcamSource,".jpg")!=0) ||
|
||||
(strstr(options.webcamSource,".png")!=0)
|
||||
)
|
||||
{
|
||||
std::cerr<<"Source seems to be a single image ("<<options.webcamSource<<") \n";
|
||||
options.frameLimit = 20; //let it warmup for a few frames..
|
||||
options.inputIsSingleImage = 1;
|
||||
options.doOutputFiltering = 0; //There is no motion to filter so skip this
|
||||
singleImageFrame=imread(options.webcamSource);
|
||||
singleImageFrame.copyTo(frame);
|
||||
} else
|
||||
if (strstr(options.webcamSource,"/dev/video")!=0)
|
||||
{
|
||||
std::cerr<<"Source seems to be a webcam ("<<options.webcamSource<<" @ "<<options.width<<","<<options.height<<") \n";
|
||||
options.inputIsSingleImage = 0;
|
||||
cap.set(cv::CAP_PROP_FRAME_WIDTH,options.width);
|
||||
cap.set(cv::CAP_PROP_FRAME_HEIGHT,options.height);
|
||||
}
|
||||
|
||||
//This needs to be grabbed to initialize window sizes either on video source, or on webcam source
|
||||
//--------------------------------------------------------------------
|
||||
if (!options.inputIsSingleImage)
|
||||
{ cap >> frame; }
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
//We will accept the input resolution and force it
|
||||
//on visualization..
|
||||
options.width = frame.size().width;
|
||||
options.height = frame.size().height;
|
||||
options.visWidth = frame.size().width;
|
||||
options.visHeight = frame.size().height;
|
||||
//-----------------------------------------------------
|
||||
|
||||
|
||||
//We might want to load a special bvh file based on our options..!
|
||||
loadOptionsAfterBVHLoadFromCommandlineOptions(&options,argc,argv);
|
||||
|
||||
//If the initialization didnt happen inside the previous call lets do it now
|
||||
if (!options.hasInit)
|
||||
{
|
||||
if (initializeBVHConverter(0,options.visWidth,options.visHeight,0))
|
||||
{
|
||||
fprintf(stderr,"BVH code initalization successfull..\n");
|
||||
options.hasInit=1;
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
//Switch to realtime priority before opening tensorflow stuff..
|
||||
requestRealtimePriority();
|
||||
|
||||
if (loadJointEstimator2D(
|
||||
&jointEstimator,
|
||||
options.
|
||||
jointEstimatorUsed,
|
||||
1,
|
||||
options.useCPUOnlyFor2DEstimator
|
||||
))
|
||||
{
|
||||
if ( loadMocapNET2(&mnet,"Live Demo") )
|
||||
{
|
||||
//------------------------------
|
||||
mnet.learningRate=options.learningRate;
|
||||
mnet.iterations=options.iterations;
|
||||
mnet.epochs=options.epochs;
|
||||
mnet.spring=options.spring;
|
||||
//------------------------------
|
||||
|
||||
cv::Mat viewMat = Mat(Size(jointEstimator.inputWidth2DJointDetector,jointEstimator.inputHeight2DJointDetector),CV_8UC3, Scalar(0,0,0));
|
||||
|
||||
struct Skeletons2DDetected skeleton2DEstimations= {0};
|
||||
|
||||
if (options.visualize)
|
||||
{
|
||||
//cv::namedWindow("Video Input Feed",1);
|
||||
//cv::moveWindow("Video Input Feed",0,368);
|
||||
cv::namedWindow("3D Points Output",1);
|
||||
cv::moveWindow("3D Points Output",0,0);
|
||||
cv::namedWindow("Skeletons",1);
|
||||
cv::moveWindow("Skeletons",1920-jointEstimator.inputWidth2DJointDetector-50,100);
|
||||
}
|
||||
|
||||
unsigned int frameID=0;
|
||||
unsigned int skippedFramesInARow=0;
|
||||
|
||||
|
||||
std::vector<float> result;
|
||||
std::vector<float> previousResult;
|
||||
|
||||
float totalTime=0.0;
|
||||
unsigned int totalSamples=0;
|
||||
|
||||
std::vector<std::vector<float> > bvhFrames;
|
||||
struct skeletonSerialized skeleton= {0};
|
||||
|
||||
while ( (options.frameLimit==0) || (frameID<options.frameLimit) )
|
||||
{
|
||||
options.loopStartTime = GetTickCountMicrosecondsMN();
|
||||
|
||||
if (options.inputIsSingleImage) { singleImageFrame.copyTo(frame); } else
|
||||
if (itIsTheFirstFrame) { itIsTheFirstFrame=0; } else
|
||||
{ cap >> frame; }
|
||||
|
||||
//If we are running in a low-end computer and need to keep in sync with a live video feed we can frame-skip
|
||||
if (options.frameSkip)
|
||||
{
|
||||
for (int i=0; i<options.frameSkip; i++)
|
||||
{
|
||||
cap >> frame;
|
||||
}
|
||||
}
|
||||
|
||||
frame.copyTo(frameCentered);
|
||||
if ( (frameCentered.size().width>0) && (frameCentered.size().height>0) )
|
||||
{
|
||||
if (
|
||||
!cropAndResizeCVMatToMatchSkeleton(
|
||||
&jointEstimator,
|
||||
frameCentered,
|
||||
&skeleton2DEstimations
|
||||
)
|
||||
)
|
||||
{
|
||||
fprintf(stderr,"Failed to crop input video\n");
|
||||
}
|
||||
//imshow("Video Input Feed", frameCentered);
|
||||
|
||||
frameCentered.copyTo(viewMat);
|
||||
// viewMat.setTo(Scalar(0,0,0));
|
||||
|
||||
//Tensorflow works with Floating point input so we need to convert our buffer..
|
||||
frameCentered.convertTo(frameCentered,CV_32FC3);
|
||||
|
||||
//At this point we are ready to execute the neural network
|
||||
long startTime2D = GetTickCountMicrosecondsMN();
|
||||
|
||||
//We count the framerate of our acquisition
|
||||
options.fpsAcquisition = convertStartEndTimeFromMicrosecondsToFPS(options.loopStartTime,startTime2D);
|
||||
|
||||
|
||||
std::vector<std::vector<float> > heatmaps = getHeatmaps(
|
||||
&jointEstimator,
|
||||
frameCentered.data,
|
||||
jointEstimator.inputWidth2DJointDetector,
|
||||
jointEstimator.inputHeight2DJointDetector
|
||||
);
|
||||
if (heatmaps.size()>0)
|
||||
{
|
||||
//This will spam with small heatmap windows
|
||||
//visualizeHeatmaps(&jointEstimator,heatmaps,frameID);
|
||||
|
||||
estimate2DSkeletonsFromHeatmaps(&jointEstimator,&skeleton2DEstimations,heatmaps);
|
||||
|
||||
long endTime2D = GetTickCountMicrosecondsMN();
|
||||
|
||||
options.fps2DEstimator = convertStartEndTimeFromMicrosecondsToFPS(startTime2D,endTime2D);
|
||||
|
||||
if (options.visualize)
|
||||
{
|
||||
dj_drawExtractedSkeletons(
|
||||
viewMat,
|
||||
&skeleton2DEstimations,
|
||||
jointEstimator.inputWidth2DJointDetector,
|
||||
jointEstimator.inputHeight2DJointDetector
|
||||
);
|
||||
}
|
||||
|
||||
float percentageOf2DPointsMissing = percentOf2DPointsMissing(&skeleton2DEstimations);
|
||||
if ( percentageOf2DPointsMissing < 50.0 ) //only work when less than 50% of information missing..
|
||||
{
|
||||
skippedFramesInARow=0;
|
||||
//We want to go from the original normalized values of skeleton2DEstimations to the original
|
||||
//Resolution we grabbed our initial frame @ before cropping..
|
||||
restore2DJointsToInputFrameCoordinates(&jointEstimator,&skeleton2DEstimations);
|
||||
|
||||
//Now that our points have their initial size let's perform a conversion to the internal
|
||||
//serialized skeleton data structure that will prepare them for use in MocapNET
|
||||
convertSkeletons2DDetectedToSkeletonsSerialized(
|
||||
&skeleton,
|
||||
&skeleton2DEstimations,
|
||||
frameID,
|
||||
jointEstimator.crop.frameWidth,
|
||||
jointEstimator.crop.frameHeight
|
||||
);
|
||||
|
||||
takeCareOfScalingInputAndAddingNoiseAccordingToOptions(&options,&skeleton);
|
||||
|
||||
unsigned int feetAreMissing=areFeetMissing(&skeleton);
|
||||
|
||||
|
||||
long startTime = GetTickCountMicrosecondsMN();
|
||||
//--------------------------------------------------------
|
||||
previousResult = result;
|
||||
result = runMocapNET2(
|
||||
&mnet,
|
||||
&skeleton,
|
||||
( (options.doLowerBody) && (!feetAreMissing) ),
|
||||
options.doHands,
|
||||
options.doFace,
|
||||
options.doGestureDetection,
|
||||
options.useInverseKinematics,
|
||||
options.doOutputFiltering
|
||||
);
|
||||
bvhFrames.push_back(result);
|
||||
//--------------------------------------------------------
|
||||
long endTime = GetTickCountMicrosecondsMN();
|
||||
options.fpsMocapNET = convertStartEndTimeFromMicrosecondsToFPS(startTime,endTime);
|
||||
frameRateSummary += options.fpsMocapNET;
|
||||
++frameSamples;
|
||||
//--------------------------------------------------------
|
||||
|
||||
|
||||
options.numberOfMissingJoints = upperbodyCountMissingNSDMElements(mnet.upperBody.NSDM,0 /*Dont spam */);
|
||||
//Don't spam with missing joints..
|
||||
//fprintf(stderr,"Number of missing joints for UpperBody %u\n",options.numberOfMissingJoints);
|
||||
|
||||
//Convert BVH frame to 2D points to show on screen
|
||||
exactMocapNET2DOutput = convertBVHFrameTo2DPoints(result);//,MocapNETTrainingWidth,MocapNETTrainingHeight);
|
||||
|
||||
if (options.saveCSV3DFile)
|
||||
{
|
||||
//Convert BVH frame to 3D points to output on a file
|
||||
points3DFlatOutput=convertBVHFrameToFlat3DPoints(result);//,MocapNETTrainingWidth,MocapNETTrainingHeight);
|
||||
output3DPositions.push_back(points3DFlatOutput); //3d Input
|
||||
}
|
||||
|
||||
resultAsSkeletonSerialized.skeletonHeaderElements = skeleton.skeletonHeaderElements;
|
||||
resultAsSkeletonSerialized.skeletonBodyElements = skeleton.skeletonBodyElements;
|
||||
if (
|
||||
convertMocapNET2OutputToSkeletonSerialized(
|
||||
&mnet,
|
||||
&resultAsSkeletonSerialized,
|
||||
exactMocapNET2DOutput,
|
||||
frameID,
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
)
|
||||
)
|
||||
{
|
||||
//TODO : Compare resultAsSkeletonSerialized and skeleton
|
||||
doReprojectionCheck(&skeleton,&resultAsSkeletonSerialized);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (skippedFramesInARow%30==0)
|
||||
{ fprintf(stderr,"."); }
|
||||
++skippedFramesInARow;
|
||||
}
|
||||
|
||||
if (options.visualize)
|
||||
{
|
||||
visualizationCommander(
|
||||
&mnet,
|
||||
&options,
|
||||
&skeleton,
|
||||
&frame,
|
||||
result,
|
||||
exactMocapNET2DOutput,
|
||||
frameID,
|
||||
1// We will do the waitKey call ourselves
|
||||
);
|
||||
|
||||
if ( (viewMat.size().width >0) && (viewMat.size().height>0) )
|
||||
{ imshow("Skeletons", viewMat); } else
|
||||
{ std::cerr<<"Invalid skeleton visualization frame.. \n"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr<<"Broken frame.. \n";
|
||||
++options.brokenFrames;
|
||||
if (options.brokenFrames>10)
|
||||
{
|
||||
std::cerr<<"Too many broken frames.. \n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
options.loopEndTime = GetTickCountMicrosecondsMN();
|
||||
|
||||
options.totalLoopFPS = convertStartEndTimeFromMicrosecondsToFPS(options.loopStartTime,options.loopEndTime);
|
||||
|
||||
|
||||
//------------------------------------------------------
|
||||
// These final calls add delays to frame processing so
|
||||
// they are not counted in loop time
|
||||
//------------------------------------------------------
|
||||
|
||||
|
||||
//Frames should increment even when visualization is off..
|
||||
++frameID;
|
||||
|
||||
|
||||
if (options.visualize)
|
||||
{
|
||||
char key = 0;
|
||||
if (options.delay!=0)
|
||||
{
|
||||
key = waitKey(options.delay);
|
||||
} else
|
||||
{
|
||||
key = waitKey(1);
|
||||
}
|
||||
|
||||
if (key==27)
|
||||
{
|
||||
fprintf(stderr,GREEN "Received Escape key from UI, terminating the application.." NORMAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.delay!=0)
|
||||
{
|
||||
nsleep(options.delay*1000);
|
||||
}
|
||||
//------------------------------------------------------
|
||||
} // End of grabber loop
|
||||
|
||||
|
||||
if (options.bvhCenter)
|
||||
{
|
||||
for (unsigned int i=0; i<bvhFrames.size(); i++)
|
||||
{
|
||||
bvhFrames[i][0]=0;
|
||||
bvhFrames[i][1]=0;
|
||||
bvhFrames[i][2]=0;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.dontBend)
|
||||
{
|
||||
for (unsigned int i=0; i<bvhFrames.size(); i++)
|
||||
{
|
||||
if (bvhFrames[i][3]>10) { bvhFrames[i][3]=10; } else
|
||||
if (bvhFrames[i][3]<-10) { bvhFrames[i][3]=-10; }
|
||||
}
|
||||
}
|
||||
|
||||
//fix https://github.com/FORTH-ModelBasedTracker/MocapNET/issues/35
|
||||
fixBVHHip(bvhFrames);
|
||||
|
||||
if ( writeBVHFile(options.outputPath,0,options.prependTPose,bvhFrames) )
|
||||
{
|
||||
fprintf(stderr,GREEN "Successfully wrote %lu frames to bvh file.. \n" NORMAL,bvhFrames.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Failed to write %lu frames to bvh file.. \n" NORMAL,bvhFrames.size());
|
||||
}
|
||||
|
||||
if (options.saveCSV3DFile)
|
||||
{
|
||||
fprintf(stderr,"Will now write 3D output to out3DP.csv.. \n");
|
||||
//----------------------------------------------------------------------------------------------------------------------------------
|
||||
if ( writeCSVHeaderFromLabelsAndVectorOfVectors("out3DP.csv",MocapNET3DPositionalOutputArrayNames,MOCAPNET_3DPOINT_NUMBER,output3DPositions) )
|
||||
{
|
||||
fprintf(stderr,GREEN "Successfully wrote %lu frames to csv file.. \n" NORMAL,output3DPositions.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Failed to write %lu frames to bvh file.. \n" NORMAL,output3DPositions.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( (options.save3DVisualization) || (options.save2DVisualization) )
|
||||
{
|
||||
int highResEncoding=1;
|
||||
char formatString[256];
|
||||
|
||||
if (highResEncoding)
|
||||
{
|
||||
snprintf(formatString,256,"ffmpeg -framerate %f -i vis%%05d.jpg -s 1200x720 -y -r %f -pix_fmt yuv420p -threads 8 livelastRun3DHiRes.mp4 && rm ./*.jpg",options.inputFramerate,options.inputFramerate);
|
||||
} else
|
||||
{
|
||||
snprintf(formatString,256,"ffmpeg -framerate %f -i vis%%05d.jpg -y -r %f -threads 8 -crf 9 -pix_fmt yuv420p lastRun3D.webm && rm ./*.jpg",options.inputFramerate,options.inputFramerate);
|
||||
}
|
||||
int i=system(formatString);
|
||||
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
fprintf(stderr,"Successfully wrote video file.. \n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Failed to write a video file.. \n");
|
||||
}
|
||||
}
|
||||
|
||||
unloadMocapNET2(&mnet);
|
||||
|
||||
|
||||
|
||||
} //3D pose estimator ok
|
||||
} //2D joint estimator ok
|
||||
|
||||
//Offer a summary of system and the achieved framerate..!
|
||||
if (frameSamples!=0)
|
||||
{
|
||||
fprintf(stderr,"\n\nMocapNET v%s execution summary :\n",MocapNETVersion);
|
||||
fprintf(stderr,"__________________________________________\n");
|
||||
//neuralNetworkPrintVersion();
|
||||
printBVHCodeVersion();
|
||||
fprintf(stderr,"CPU : %s \n",options.CPUName);
|
||||
fprintf(stderr,"GPU : %s \n",options.GPUName);
|
||||
fprintf(stderr,"Average framerate for %u samples was %0.2f fps \n",frameSamples,((float) frameRateSummary/frameSamples) );
|
||||
|
||||
//Offer some info on options of the run executed..
|
||||
//-------------------------------------------------
|
||||
if (options.doMultiThreadedIK)
|
||||
{ fprintf(stderr,"Multi-threading was on\n"); }
|
||||
//-------------------------------------------------
|
||||
if (codeOptimizationsForIKEnabled())
|
||||
{ fprintf(stderr,"Code optimizations where on\n"); }
|
||||
//-------------------------------------------------
|
||||
if (options.jointEstimatorUsed==JOINT_2D_ESTIMATOR_FORTH)
|
||||
{ fprintf(stderr,"You can achieve better accuracy by using the homebrewed OpenPose 2D joint estimator using --openpose\n"); }
|
||||
//-------------------------------------------------
|
||||
if (options.jointEstimatorUsed==JOINT_2D_ESTIMATOR_OPENPOSE)
|
||||
{ fprintf(stderr,"You can achieve faster framerates with the bundled FORTH 2D joint estimator using --forth\n"); }
|
||||
//-------------------------------------------------
|
||||
}
|
||||
|
||||
// the camera will be deinitialized automatically in VideoCapture destructor
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
project( MocapNET2CSV )
|
||||
cmake_minimum_required( VERSION 2.8.13 )
|
||||
#cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
find_package(OpenCV REQUIRED)
|
||||
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
|
||||
|
||||
add_executable(MocapNET2CSV mocapnet2CSV.cpp )
|
||||
target_link_libraries(MocapNET2CSV rt dl m ${OpenCV_LIBRARIES} Tensorflow TensorflowFramework MocapNETLib2 )
|
||||
set_target_properties(MocapNET2CSV PROPERTIES DEBUG_POSTFIX "D")
|
||||
|
||||
|
||||
set_target_properties(MocapNET2CSV PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Utility to extract BVH files straight from OpenPose JSON output
|
||||
* Sample usage ./MocapNETCSV --from test.csv --visualize
|
||||
*/
|
||||
|
||||
#include "../MocapNETLib2/mocapnet2.hpp"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../MocapNETLib2/applicationLogic/parseCommandlineOptions.hpp"
|
||||
|
||||
#include "../MocapNETLib2/tools.hpp"
|
||||
#include "../MocapNETLib2/visualization/map.hpp"
|
||||
#include "../MocapNETLib2/visualization/visualization.hpp"
|
||||
#include "../MocapNETLib2/visualization/camera_ready.hpp"
|
||||
//------------------------------------------
|
||||
#include "../MocapNETLib2/IO/bvh.hpp"
|
||||
#include "../MocapNETLib2/IO/csvRead.hpp"
|
||||
#include "../MocapNETLib2/IO/csvWrite.hpp"
|
||||
#include "../MocapNETLib2/IO/jsonRead.hpp"
|
||||
#include "../MocapNETLib2/IO/jsonMocapNETHelpers.hpp"
|
||||
#include "../MocapNETLib2/IO/conversions.hpp"
|
||||
#include "../MocapNETLib2/IO/skeletonAbstraction.hpp"
|
||||
//---------------------------------------------------
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct MocapNET2Options options= {0};
|
||||
struct MocapNET2 mnet= {0};
|
||||
mnet.options = & options;
|
||||
|
||||
struct skeletonSerialized resultAsSkeletonSerialized= {0};
|
||||
|
||||
defaultMocapNET2Options(&options);
|
||||
options.GPUName[0]=0; //The CSV demo does not use the GPU so don't display it..
|
||||
|
||||
|
||||
/*
|
||||
* Force effortless IK configuration on CSV demo
|
||||
*/
|
||||
//Be unconstrained by default
|
||||
options.constrainPositionRotation=0;
|
||||
//Use IK ========
|
||||
options.useInverseKinematics=1;
|
||||
options.learningRate=0.01;
|
||||
options.iterations=5;//5;
|
||||
options.epochs=30.0;
|
||||
options.spring=0.0; //Deprecated ?
|
||||
//==============
|
||||
|
||||
//640x480 should be a high framerate compatible resolution
|
||||
//for most webcams, you can change this using --size X Y commandline parameter
|
||||
options.width = 1920;
|
||||
options.height = 1080;
|
||||
|
||||
loadOptionsFromCommandlineOptions(&options,argc,argv);
|
||||
|
||||
if (options.path==0)
|
||||
{
|
||||
fprintf(stderr,RED "No CSV dataset given\n " NORMAL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if (options.label==0)
|
||||
{
|
||||
options. label="colorFrame_0_";
|
||||
}
|
||||
|
||||
|
||||
struct CSVFileContext csv= {0};
|
||||
if (!options.isCSVFile)
|
||||
{
|
||||
fprintf(stderr,RED "The path %s doesn't look like a CSV file.. \n" NORMAL,options.path);
|
||||
return 0;
|
||||
}
|
||||
else if (options.isCSVFile)
|
||||
{
|
||||
if (!openCSVFile(&csv,options.path))
|
||||
{
|
||||
fprintf(stderr,RED "Unable to open CSV file %s \n" NORMAL,options.path);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,GREEN "CSV file %s is now open\n" NORMAL,options.path);
|
||||
options.frameLimit=getBodyLinesOfCSVFIle(&csv,options.path);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
int havePath=0;
|
||||
int positionOfSlash=0;
|
||||
for (int i=strlen(options.path); i>=0; i--)
|
||||
{
|
||||
if (options.path[i]=='/')
|
||||
{
|
||||
positionOfSlash=i;
|
||||
havePath=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (havePath)
|
||||
{
|
||||
options.datasetPath=(char*) malloc(sizeof(char) * (positionOfSlash+2) );
|
||||
if (options.datasetPath!=0)
|
||||
{
|
||||
for (int i=0; i<=positionOfSlash; i++)
|
||||
{
|
||||
options.datasetPath[i]=options.path[i];
|
||||
}
|
||||
options.datasetPath[positionOfSlash+1]=0; //Null termination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
loadCalibration(&options,options.datasetPath,"color.calib");
|
||||
|
||||
|
||||
if(options.visualize)
|
||||
{
|
||||
spawnVisualizationWindow("3D Points Output",options.visWidth,options.visHeight);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ( loadMocapNET2(&mnet,"CSV Demo") )
|
||||
{
|
||||
//------------------------------
|
||||
mnet.learningRate=options.learningRate;
|
||||
mnet.iterations=options.iterations;
|
||||
mnet.epochs=options.epochs;
|
||||
mnet.spring=options.spring;
|
||||
//------------------------------
|
||||
|
||||
|
||||
char filePathOfImageFile[1024]= {0};
|
||||
if (options.datasetPath)
|
||||
{
|
||||
char formatString[1024]= {0};
|
||||
snprintf(formatString,1024,"%%s/%%s%%0%uu.jpg",options.serialLength);
|
||||
snprintf(filePathOfImageFile,1024,formatString,options.datasetPath,options.label,1/*Frame ID*/);
|
||||
// snprintf(filePathOfImageFile,1024,"%s/colorFrame_0_00001.jpg",datasetPath);
|
||||
|
||||
if ( getImageWidthHeight(filePathOfImageFile,&options.width,&options.height) )
|
||||
{
|
||||
fprintf(stderr,"Image dimensions changed from default to %ux%u\n",options.width,options.height);
|
||||
//Force visualization size to the same as image dimensions autodetected..
|
||||
options.visWidth = options.width;
|
||||
options.visHeight = options.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Assuming default image dimensions %ux%u , you can change this using --size x y\n",options.width,options.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//We might want to load a special bvh file based on our options..!
|
||||
loadOptionsAfterBVHLoadFromCommandlineOptions(&options,argc,argv);
|
||||
|
||||
//If the initialization didnt happen inside the previous call lets do it now
|
||||
if (!options.hasInit)
|
||||
{
|
||||
if (initializeBVHConverter(0,options.visWidth,options.visHeight,0))
|
||||
{
|
||||
fprintf(stderr,"BVH code initalization successfull..\n");
|
||||
options.hasInit=1;
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
std::vector<float> result;
|
||||
std::vector<float> previousResult;
|
||||
std::vector<std::vector<float> > output3DPositions;
|
||||
std::vector<float> points3DFlatOutput;
|
||||
|
||||
float totalTime=0.0;
|
||||
unsigned int totalSamples=0;
|
||||
|
||||
std::vector<std::vector<float> > bvhFrames;
|
||||
struct skeletonSerialized skeleton= {0};
|
||||
|
||||
char formatString[1024]= {0};
|
||||
snprintf(formatString,1024,"%%s/%%s%%0%uu_keypoints.json",options.serialLength);
|
||||
|
||||
unsigned int frameID=0;
|
||||
while ( (options.frameLimit==0) || (frameID<options.frameLimit) )
|
||||
{
|
||||
if ( parseNextCSVCOCOSkeleton(&csv,&skeleton) )
|
||||
{
|
||||
takeCareOfScalingInputAndAddingNoiseAccordingToOptions(&options,&skeleton);
|
||||
|
||||
unsigned int feetAreMissing=areFeetMissing(&skeleton);
|
||||
|
||||
long startTime = GetTickCountMicrosecondsMN();
|
||||
//--------------------------------------------------------
|
||||
previousResult = result;
|
||||
result = runMocapNET2(
|
||||
&mnet,
|
||||
&skeleton,
|
||||
( (options.doLowerBody) && (!feetAreMissing) ),
|
||||
options.doHands,
|
||||
options.doFace,
|
||||
options.doGestureDetection,
|
||||
options.useInverseKinematics,
|
||||
options.doOutputFiltering);
|
||||
bvhFrames.push_back(result);
|
||||
//--------------------------------------------------------
|
||||
long endTime = GetTickCountMicrosecondsMN();
|
||||
|
||||
//Convert BVH frame to 2D points to show on screen
|
||||
std::vector<std::vector<float> > exactMocapNET2DOutput = convertBVHFrameTo2DPoints(result);//,MocapNETTrainingWidth,MocapNETTrainingHeight);
|
||||
|
||||
|
||||
if (options.saveCSV3DFile)
|
||||
{
|
||||
//Convert BVH frame to 3D points to output on a file
|
||||
points3DFlatOutput=convertBVHFrameToFlat3DPoints(result);//,MocapNETTrainingWidth,MocapNETTrainingHeight);
|
||||
output3DPositions.push_back(points3DFlatOutput); //3d Input
|
||||
}
|
||||
|
||||
resultAsSkeletonSerialized.skeletonHeaderElements = skeleton.skeletonHeaderElements;
|
||||
resultAsSkeletonSerialized.skeletonBodyElements = skeleton.skeletonBodyElements;
|
||||
//exactMocapNET2DOutput = convertBVHFrameTo2DPoints(result,MocapNETTrainingWidth,MocapNETTrainingHeight);
|
||||
if (
|
||||
convertMocapNET2OutputToSkeletonSerialized(
|
||||
&mnet,
|
||||
&resultAsSkeletonSerialized,
|
||||
exactMocapNET2DOutput,
|
||||
frameID,
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
)
|
||||
)
|
||||
{
|
||||
//TODO : Compare resultAsSkeletonSerialized and skeleton
|
||||
doReprojectionCheck(&skeleton,&resultAsSkeletonSerialized);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float sampleTime = (float) (endTime-startTime)/1000;
|
||||
if (sampleTime==0.0)
|
||||
{
|
||||
sampleTime=1.0; //Take care of division by null..
|
||||
}
|
||||
|
||||
options.totalLoopFPS = (float) 1000/sampleTime;
|
||||
fprintf(stderr,"Sample %u - %0.4fms - %0.4f fps\n",frameID,sampleTime,options.totalLoopFPS);
|
||||
|
||||
|
||||
if (options.visualize)
|
||||
{
|
||||
visualizationCommander(
|
||||
&mnet,
|
||||
&options,
|
||||
&skeleton,
|
||||
0,
|
||||
result,
|
||||
exactMocapNET2DOutput,
|
||||
frameID,
|
||||
0 //Visualization code must handle messages..
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
totalTime+=sampleTime;
|
||||
++totalSamples;
|
||||
|
||||
if (options.delay!=0)
|
||||
{
|
||||
fprintf(stderr,"Sleeping for %u milliseconds\n",options.delay);
|
||||
nsleep(options.delay*1000);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Done.. \n");
|
||||
break;
|
||||
}
|
||||
|
||||
++frameID;
|
||||
}
|
||||
|
||||
fprintf(stderr,"Finished with %u/%u frames\n",frameID,options.frameLimit);
|
||||
|
||||
if (totalSamples>0)
|
||||
{
|
||||
char * bvhHeaderToWrite=0;
|
||||
|
||||
if (options.bvhCenter)
|
||||
{
|
||||
for (unsigned int i=0; i<bvhFrames.size(); i++)
|
||||
{
|
||||
bvhFrames[i][0]=0;
|
||||
bvhFrames[i][1]=0;
|
||||
bvhFrames[i][2]=0;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.dontBend)
|
||||
{
|
||||
for (unsigned int i=0; i<bvhFrames.size(); i++)
|
||||
{
|
||||
if (bvhFrames[i][3]>10) { bvhFrames[i][3]=10; } else
|
||||
if (bvhFrames[i][3]<-10) { bvhFrames[i][3]=-10; }
|
||||
}
|
||||
}
|
||||
|
||||
//fix https://github.com/FORTH-ModelBasedTracker/MocapNET/issues/35
|
||||
fixBVHHip(bvhFrames);
|
||||
|
||||
if ( writeBVHFile(options.outputPath,bvhHeaderToWrite,options.prependTPose,bvhFrames) )
|
||||
{
|
||||
fprintf(stderr,"Successfully wrote %lu frames to bvh file %s.. \n",bvhFrames.size(),options.outputPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Failed to write %lu frames to bvh file %s .. \n",bvhFrames.size(),options.outputPath);
|
||||
}
|
||||
|
||||
if (options.saveCSV3DFile)
|
||||
{
|
||||
fprintf(stderr,"Will now write 3D output to out3DP.csv.. \n");
|
||||
//----------------------------------------------------------------------------------------------------------------------------------
|
||||
if ( writeCSVHeaderFromLabelsAndVectorOfVectors("out3DP.csv",MocapNET3DPositionalOutputArrayNames,MOCAPNET_3DPOINT_NUMBER,output3DPositions) )
|
||||
{
|
||||
fprintf(stderr,GREEN "Successfully wrote %lu frames to csv file.. \n" NORMAL,output3DPositions.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Failed to write %lu frames to bvh file.. \n" NORMAL,output3DPositions.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float averageTime=(float) totalTime/totalSamples;
|
||||
fprintf(stderr,"\n\nMocapNET v%s execution summary :\n",MocapNETVersion);
|
||||
fprintf(stderr,"__________________________________________\n");
|
||||
//neuralNetworkPrintVersion();
|
||||
printBVHCodeVersion();
|
||||
fprintf(stderr,"CPU : %s \n",options.CPUName);
|
||||
fprintf(stderr,"GPU : %s \n",options.GPUName);
|
||||
fprintf(stderr,"Total %0.2f ms for %u samples - Average %0.2f ms - %0.2f fps\n",totalTime,totalSamples,averageTime,(float) 1000/averageTime);
|
||||
//-----------------------------------------------
|
||||
if (options.doMultiThreadedIK)
|
||||
{ fprintf(stderr,"Multi-threading was on\n"); }
|
||||
if (codeOptimizationsForIKEnabled())
|
||||
{ fprintf(stderr,"Code optimizations where on\n"); }
|
||||
}
|
||||
|
||||
if (options.isCSVFile)
|
||||
{
|
||||
closeCSVFile(&csv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (options.saveVisualization)
|
||||
{
|
||||
int i;
|
||||
//Low-Res video encoding
|
||||
//int i=system("ffmpeg -framerate 25 -i vis%05d.jpg -y -r 30 -threads 8 -crf 9 -pix_fmt yuv420p lastRun3D.webm");
|
||||
//High-Res video encoding
|
||||
snprintf(formatString,1024,"ffmpeg -framerate %f -i vis%%05d.jpg -s 1200x720 -y -r %f -pix_fmt yuv420p -threads 8 %s_lastRun3DHiRes.mp4 && rm ./vis*.jpg",options.inputFramerate,options.inputFramerate,options.path); //
|
||||
i=system(formatString);
|
||||
if (i==0)
|
||||
{
|
||||
fprintf(stderr,"Successfully wrote video file to %s_lastRun3DHiRes.mp4 .. \n",options.path);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Failed to write a video file.. \n");
|
||||
}
|
||||
}
|
||||
|
||||
unloadMocapNET2(&mnet);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET2 failed to load properly and will now exit..\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
project( MocapNETLib2 )
|
||||
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(MocapNETLib2 SHARED
|
||||
${BVH_SOURCE}
|
||||
${OPENGL_SOURCE}
|
||||
../MocapNETLib2/config.h
|
||||
../MocapNETLib2/core/core.cpp
|
||||
../MocapNETLib2/core/core.hpp
|
||||
../MocapNETLib2/core/singleThreaded.cpp
|
||||
../MocapNETLib2/core/singleThreaded.hpp
|
||||
../MocapNETLib2/core/multiThreaded.cpp
|
||||
../MocapNETLib2/core/multiThreaded.hpp
|
||||
../MocapNETLib2/mocapnet2.cpp
|
||||
../MocapNETLib2/tools.cpp
|
||||
../MocapNETLib2/remoteExecution.cpp
|
||||
../MocapNETLib2/applicationLogic/parseCommandlineOptions.cpp
|
||||
../MocapNETLib2/applicationLogic/poseRecognition.cpp
|
||||
../MocapNETLib2/applicationLogic/gestureRecognition.cpp
|
||||
../MocapNETLib2/applicationLogic/artifactRecognition.cpp
|
||||
../MocapNETLib2/qualityControl/qualityControl.cpp
|
||||
../MocapNETLib2/postProcessing/outputFiltering.hpp
|
||||
../MocapNETLib2/NSDM/generated_body.hpp
|
||||
../MocapNETLib2/NSDM/generated_upperbody.hpp
|
||||
../MocapNETLib2/NSDM/generated_lowerbody.hpp
|
||||
../MocapNETLib2/IO/bvh.cpp
|
||||
../MocapNETLib2/IO/commonSkeleton.hpp
|
||||
../MocapNETLib2/IO/skeletonAbstraction.cpp
|
||||
../MocapNETLib2/IO/skeletonSerializedToBVHTransform.hpp
|
||||
../MocapNETLib2/IO/csvRead.cpp
|
||||
../MocapNETLib2/IO/csvWrite.cpp
|
||||
../MocapNETLib2/IO/jsonRead.cpp
|
||||
../MocapNETLib2/IO/jsonMocapNETHelpers.cpp
|
||||
../MocapNETLib2/IO/conversions.cpp
|
||||
../MocapNETLib2/visualization/rgb.cpp
|
||||
../MocapNETLib2/visualization/allInOne.cpp
|
||||
../MocapNETLib2/visualization/widgets.cpp
|
||||
../MocapNETLib2/visualization/visualization.cpp
|
||||
../MocapNETLib2/visualization/drawSkeleton.cpp
|
||||
../MocapNETLib2/visualization/opengl.cpp
|
||||
../MocapNETLib2/visualization/camera_ready.cpp
|
||||
../MocapNETLib2/visualization/map.cpp
|
||||
../MocapNETLib2/visualization/template.cpp
|
||||
../MocapNETLib2/solutionParts/body.cpp
|
||||
../MocapNETLib2/solutionParts/upperBody.cpp
|
||||
../MocapNETLib2/solutionParts/lowerBody.cpp
|
||||
${CMAKE_SOURCE_DIR}/dependencies/InputParser/InputParser_C.cpp
|
||||
#Tensorflow stuff..
|
||||
${TENSORFLOW_SOURCE_FILES}
|
||||
)
|
||||
|
||||
|
||||
target_link_libraries(MocapNETLib2 rt dl m pthread ${OpenCV_LIBRARIES} ${OPENGL_LIBS} Tensorflow TensorflowFramework ${NETWORK_CLIENT_LIBRARIES} ${PNG_Libs} ${JPG_Libs} )
|
||||
set_target_properties(MocapNETLib2 PROPERTIES DEBUG_POSTFIX "D")
|
||||
|
||||
|
||||
set_target_properties(MocapNETLib2 PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,164 @@
|
||||
abdomen
|
||||
chest
|
||||
neck
|
||||
neck1
|
||||
head
|
||||
__jaw
|
||||
jaw
|
||||
special04
|
||||
oris02
|
||||
oris01
|
||||
oris06.l
|
||||
oris07.l
|
||||
oris06.r
|
||||
oris07.r
|
||||
tongue00
|
||||
tongue01
|
||||
tongue02
|
||||
tongue03
|
||||
__tongue04
|
||||
tongue04
|
||||
tongue07.l
|
||||
tongue07.r
|
||||
tongue06.l
|
||||
tongue06.r
|
||||
tongue05.l
|
||||
tongue05.r
|
||||
__levator02.l
|
||||
levator02.l
|
||||
levator03.l
|
||||
levator04.l
|
||||
levator05.l
|
||||
__levator02.r
|
||||
levator02.r
|
||||
levator03.r
|
||||
levator04.r
|
||||
levator05.r
|
||||
__special01
|
||||
special01
|
||||
oris04.l
|
||||
oris03.l
|
||||
oris04.r
|
||||
oris03.r
|
||||
oris06
|
||||
oris05
|
||||
__special03
|
||||
special03
|
||||
__levator06.l
|
||||
levator06.l
|
||||
__levator06.r
|
||||
levator06.r
|
||||
special06.l
|
||||
special05.l
|
||||
eye.l
|
||||
orbicularis03.l
|
||||
orbicularis04.l
|
||||
special06.r
|
||||
special05.r
|
||||
eye.r
|
||||
orbicularis03.r
|
||||
orbicularis04.r
|
||||
__temporalis01.l
|
||||
temporalis01.l
|
||||
oculi02.l
|
||||
oculi01.l
|
||||
__temporalis01.r
|
||||
temporalis01.r
|
||||
oculi02.r
|
||||
oculi01.r
|
||||
__temporalis02.l
|
||||
temporalis02.l
|
||||
risorius02.l
|
||||
risorius03.l
|
||||
__temporalis02.r
|
||||
temporalis02.r
|
||||
risorius02.r
|
||||
risorius03.r
|
||||
rCollar
|
||||
rShldr
|
||||
rForeArm
|
||||
rHand
|
||||
metacarpal1.r
|
||||
finger2-1.r
|
||||
finger2-2.r
|
||||
finger2-3.r
|
||||
metacarpal2.r
|
||||
finger3-1.r
|
||||
finger3-2.r
|
||||
finger3-3.r
|
||||
__metacarpal3.r
|
||||
metacarpal3.r
|
||||
finger4-1.r
|
||||
finger4-2.r
|
||||
finger4-3.r
|
||||
__metacarpal4.r
|
||||
metacarpal4.r
|
||||
finger5-1.r
|
||||
finger5-2.r
|
||||
finger5-3.r
|
||||
__rthumb
|
||||
rthumb
|
||||
finger1-2.r
|
||||
finger1-3.r
|
||||
lCollar
|
||||
lShldr
|
||||
lForeArm
|
||||
lHand
|
||||
metacarpal1.l
|
||||
finger2-1.l
|
||||
finger2-2.l
|
||||
finger2-3.l
|
||||
metacarpal2.l
|
||||
finger3-1.l
|
||||
finger3-2.l
|
||||
finger3-3.l
|
||||
__metacarpal3.l
|
||||
metacarpal3.l
|
||||
finger4-1.l
|
||||
finger4-2.l
|
||||
finger4-3.l
|
||||
__metacarpal4.l
|
||||
metacarpal4.l
|
||||
finger5-1.l
|
||||
finger5-2.l
|
||||
finger5-3.l
|
||||
__lthumb
|
||||
lthumb
|
||||
finger1-2.l
|
||||
finger1-3.l
|
||||
rButtock
|
||||
rThigh
|
||||
rShin
|
||||
rFoot
|
||||
toe1-1.R
|
||||
toe1-2.R
|
||||
toe2-1.R
|
||||
toe2-2.R
|
||||
toe2-3.R
|
||||
toe3-1.R
|
||||
toe3-2.R
|
||||
toe3-3.R
|
||||
toe4-1.R
|
||||
toe4-2.R
|
||||
toe4-3.R
|
||||
toe5-1.R
|
||||
toe5-2.R
|
||||
toe5-3.R
|
||||
lButtock
|
||||
lThigh
|
||||
lShin
|
||||
lFoot
|
||||
toe1-1.L
|
||||
toe1-2.L
|
||||
toe2-1.L
|
||||
toe2-2.L
|
||||
toe2-3.L
|
||||
toe3-1.L
|
||||
toe3-2.L
|
||||
toe3-3.L
|
||||
toe4-1.L
|
||||
toe4-2.L
|
||||
toe4-3.L
|
||||
toe5-1.L
|
||||
toe5-2.L
|
||||
toe5-3.L
|
||||
@@ -0,0 +1,714 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* @brief A C struct to hold a 2D coordinate
|
||||
*/
|
||||
struct point2D
|
||||
{
|
||||
float x,y;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A C struct to hold a 3D coordinate
|
||||
*/
|
||||
struct point3D
|
||||
{
|
||||
float x,y,z;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A structure to hold a bounding box
|
||||
*/
|
||||
struct boundingBox
|
||||
{
|
||||
char populated;
|
||||
float minimumX;
|
||||
float maximumX;
|
||||
float minimumY;
|
||||
float maximumY;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is an array of names for all the old COCO body parts.
|
||||
*/
|
||||
static const char * COCOOldBodyNames[] =
|
||||
{
|
||||
"Nose", //0
|
||||
"Neck", //1
|
||||
"RShoulder", //2
|
||||
"RElbow", //3
|
||||
"RWrist", //4
|
||||
"LShoulder", //5
|
||||
"LElbow", //6
|
||||
"LWrist", //7
|
||||
"RHip", //8
|
||||
"RKnee", //9
|
||||
"RAnkle", //10
|
||||
"LHip", //11
|
||||
"LKnee", //12
|
||||
"LAnkle", //13
|
||||
"REye", //14
|
||||
"LEye", //15
|
||||
"REar", //16
|
||||
"LEar", //17
|
||||
"Bkg", //18
|
||||
//=================
|
||||
"End of Joint Names"
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief An enumerator of coco skeleton joints
|
||||
*/
|
||||
//https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/media/keypoints_pose_18.png
|
||||
enum COCOOldSkeletonJoints
|
||||
{
|
||||
COCO_Nose=0,
|
||||
COCO_Neck,
|
||||
COCO_RShoulder,
|
||||
COCO_RElbow,
|
||||
COCO_RWrist,
|
||||
COCO_LShoulder,
|
||||
COCO_LElbow,
|
||||
COCO_LWrist,
|
||||
COCO_RHip,
|
||||
COCO_RKnee,
|
||||
COCO_RAnkle,
|
||||
COCO_LHip,
|
||||
COCO_LKnee,
|
||||
COCO_LAnkle,
|
||||
COCO_REye,
|
||||
COCO_LEye,
|
||||
COCO_REar,
|
||||
COCO_LEar,
|
||||
COCO_Bkg,
|
||||
//---------------------
|
||||
COCO_PARTS
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief An array of indexes to the parents of coco skeleton joints
|
||||
*/
|
||||
static const int COCOSkeletonJointsParentRelationMap[] =
|
||||
{
|
||||
// Parent Joint
|
||||
COCO_Nose, //COCO_Nose,
|
||||
COCO_Nose, //COCO_Neck,
|
||||
COCO_Neck, //COCO_RShoulder,
|
||||
COCO_RShoulder, //COCO_RElbow,
|
||||
COCO_RElbow, //COCO_RWrist,
|
||||
COCO_Neck, //COCO_LShoulder,
|
||||
COCO_LShoulder, //COCO_LElbow,
|
||||
COCO_LElbow, //COCO_LWrist,
|
||||
COCO_Neck, //COCO_RHip,
|
||||
COCO_RHip, //COCO_RKnee,
|
||||
COCO_RKnee, //COCO_RAnkle,
|
||||
COCO_Neck, //COCO_LHip,
|
||||
COCO_LHip, //COCO_LKnee,
|
||||
COCO_LKnee, //COCO_LAnkle,
|
||||
COCO_Nose, //COCO_REye,
|
||||
COCO_Nose, //COCO_LEye,
|
||||
COCO_REye, //COCO_REar,
|
||||
COCO_LEye, //COCO_LEar,
|
||||
COCO_Bkg //COCO_Bkg
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is an array of names for all the new BODY25 body parts.
|
||||
* This is a "friendly" array, meaning it is meant to be easy to understand and does not need to exactly correspond to the BVH file..
|
||||
*/
|
||||
static const char * Body25BodyFriendlyNames[] =
|
||||
{
|
||||
"Nose", //0
|
||||
"Neck", //1
|
||||
"RShoulder", //2
|
||||
"RElbow", //3
|
||||
"RWrist", //4
|
||||
"LShoulder", //5
|
||||
"LElbow", //6
|
||||
"LWrist", //7
|
||||
"MidHip", //8
|
||||
"RHip", //9
|
||||
"RKnee", //10
|
||||
"RAnkle", //11
|
||||
"LHip", //12
|
||||
"LKnee", //13
|
||||
"LAnkle", //14
|
||||
"REye", //15
|
||||
"LEye", //16
|
||||
"REar", //17
|
||||
"LEar", //18
|
||||
"LBigToe", //19
|
||||
"LSmallToe", //20
|
||||
"LHeel", //21
|
||||
"RBigToe", //22
|
||||
"RSmallToe", //23
|
||||
"RHeel", //24
|
||||
"Bkg", //25
|
||||
//=================
|
||||
"End of Joint Names"
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This is an array of names for all the new BODY25 body parts.
|
||||
* This tries to mirror body_configuration.json and everything used is lowercase exactly for this reason..
|
||||
* it also has to be the same with the bvh file headerWithHeadAndOneMotion.bvh
|
||||
*/
|
||||
static const char * Body25BodyNames[] =
|
||||
{
|
||||
"head", //0
|
||||
"neck", //1
|
||||
"rshoulder", //2
|
||||
"relbow", //3
|
||||
"rhand", //4
|
||||
"lshoulder", //5
|
||||
"lelbow", //6
|
||||
"lhand", //7
|
||||
"hip", //8
|
||||
"rhip", //9
|
||||
"rknee", //10
|
||||
"rfoot", //11
|
||||
"lhip", //12
|
||||
"lknee", //13
|
||||
"lfoot", //14
|
||||
"endsite_eye.r", //15
|
||||
"endsite_eye.l", //16
|
||||
"rear", //17 ========= No correspondance
|
||||
"lear", //18 ========= No correspondance
|
||||
"endsite_toe1-2.l",//19
|
||||
"endsite_toe5-3.l",//20
|
||||
"lheel", //21 ========= No correspondance
|
||||
"endsite_toe1-2.r",//22
|
||||
"endsite_toe5-3.r",//23
|
||||
"rheel", //24 ========= No correspondance
|
||||
"bkg", //25 ========= No correspondance
|
||||
//==================
|
||||
"End of Joint Names"
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An enumerator of BODY 25 skeleton joints
|
||||
*/
|
||||
enum Body25SkeletonJoints
|
||||
{
|
||||
BODY25_Nose=0,
|
||||
BODY25_Neck,
|
||||
BODY25_RShoulder,
|
||||
BODY25_RElbow,
|
||||
BODY25_RWrist,
|
||||
BODY25_LShoulder,
|
||||
BODY25_LElbow,
|
||||
BODY25_LWrist,
|
||||
BODY25_MidHip,
|
||||
BODY25_RHip,
|
||||
BODY25_RKnee,
|
||||
BODY25_RAnkle,
|
||||
BODY25_LHip,
|
||||
BODY25_LKnee,
|
||||
BODY25_LAnkle,
|
||||
BODY25_REye,
|
||||
BODY25_LEye,
|
||||
BODY25_REar,
|
||||
BODY25_LEar,
|
||||
BODY25_LBigToe,
|
||||
BODY25_LSmallToe,
|
||||
BODY25_LHeel,
|
||||
BODY25_RBigToe,
|
||||
BODY25_RSmallToe,
|
||||
BODY25_RHeel,
|
||||
BODY25_Bkg,
|
||||
//---------------------
|
||||
BODY25_PARTS
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief An array of indexes to the parents of BODY25 skeleton joints
|
||||
*/
|
||||
static const int Body25SkeletonJointsParentRelationMap[] =
|
||||
{
|
||||
// Parent Joint
|
||||
BODY25_Nose, //BODY25_Nose,
|
||||
BODY25_Nose, //BODY25_Neck,
|
||||
BODY25_Neck, //BODY25_RShoulder,
|
||||
BODY25_RShoulder, //BODY25_RElbow,
|
||||
BODY25_RElbow, //BODY25_RWrist,
|
||||
BODY25_Neck, //BODY25_LShoulder,
|
||||
BODY25_LShoulder, //BODY25_LElbow,
|
||||
BODY25_LElbow, //BODY25_LWrist,
|
||||
BODY25_Neck, //BODY25_MidHip
|
||||
BODY25_MidHip, //BODY25_RHip,
|
||||
BODY25_RHip, //BODY25_RKnee,
|
||||
BODY25_RKnee, //BODY25_RAnkle,
|
||||
BODY25_MidHip, //BODY25_LHip,
|
||||
BODY25_LHip, //BODY25_LKnee,
|
||||
BODY25_LKnee, //BODY25_LAnkle,
|
||||
BODY25_Nose, //BODY25_REye,
|
||||
BODY25_Nose, //BODY25_LEye,
|
||||
BODY25_REye, //BODY25_REar,
|
||||
BODY25_LEye, //BODY25_LEar,
|
||||
BODY25_LHeel, //BODY25_LBigToe,
|
||||
BODY25_LBigToe, //BODY25_LSmallToe,
|
||||
BODY25_LAnkle, //BODY25_LHeel,
|
||||
BODY25_RHeel, //BODY25_RBigToe,
|
||||
BODY25_RBigToe, //BODY25_RSmallToe,
|
||||
BODY25_RAnkle, // BODY25_RHeel,
|
||||
BODY25_Bkg //BODY25_Bkg
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief An enumerator of COCO Hand joints
|
||||
*/
|
||||
//https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/media/keypoints_hand.png
|
||||
enum COCOHandJoints
|
||||
{
|
||||
COCO_Hand_Wrist=0,//0
|
||||
COCO_Hand_Thumb_1,//1
|
||||
COCO_Hand_Thumb_2, //2
|
||||
COCO_Hand_Thumb_3, //3
|
||||
COCO_Hand_Thumb_4,//4
|
||||
COCO_Hand_Index_1,//5
|
||||
COCO_Hand_Index_2,//6
|
||||
COCO_Hand_Index_3,//7
|
||||
COCO_Hand_Index_4,//8
|
||||
COCO_Hand_Middle_1,//9
|
||||
COCO_Hand_Middle_2,//10
|
||||
COCO_Hand_Middle_3,//11
|
||||
COCO_Hand_Middle_4,//12
|
||||
COCO_Hand_Ring_1,//13
|
||||
COCO_Hand_Ring_2,//14
|
||||
COCO_Hand_Ring_3,//15
|
||||
COCO_Hand_Ring_4,//16
|
||||
COCO_Hand_Pinky_1,//17
|
||||
COCO_Hand_Pinky_2,//18
|
||||
COCO_Hand_Pinky_3,//19
|
||||
COCO_Hand_Pinky_4,//20
|
||||
//---------------------
|
||||
COCO_HAND_PARTS
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is an array of names for the left hand.
|
||||
* This is a "friendly" array, meaning it is meant to be easy to understand and does not need to exactly correspond to the BVH file..
|
||||
*/
|
||||
static const char * COCOLeftHandFriendlyNames[] =
|
||||
{
|
||||
"Left_Hand_Wrist",//0
|
||||
"Left_Hand_Thumb_1",//1
|
||||
"Left_Hand_Thumb_2", //2
|
||||
"Left_Hand_Thumb_3", //3
|
||||
"Left_Hand_Thumb_4",//4
|
||||
"Left_Hand_Index_1",//5
|
||||
"Left_Hand_Index_2",//6
|
||||
"Left_Hand_Index_3",//7
|
||||
"Left_Hand_Index_4",//8
|
||||
"Left_Hand_Middle_1",//9
|
||||
"Left_Hand_Middle_2",//10
|
||||
"Left_Hand_Middle_3",//11
|
||||
"Left_Hand_Middle_4",//12
|
||||
"Left_Hand_Ring_1",//13
|
||||
"Left_Hand_Ring_2",//14
|
||||
"Left_Hand_Ring_3",//15
|
||||
"Left_Hand_Ring_4",//16
|
||||
"Left_Hand_Pinky_1",//17
|
||||
"Left_Hand_Pinky_2",//18
|
||||
"Left_Hand_Pinky_3",//19
|
||||
"Left_Hand_Pinky_4",//20
|
||||
//--------------------
|
||||
"End of Left Hand Names"
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This is an array of names for the left hand.
|
||||
* This tries to mirror lhand_configuration.json and everything used is lowercase exactly for this reason..
|
||||
* it also has to be the same with the bvh file headerWithHeadAndOneMotion.bvh
|
||||
*/
|
||||
static const char * COCOLeftHandNames[] =
|
||||
{
|
||||
"lhand",//0
|
||||
"lthumb",//1
|
||||
"finger1-2.l", //2
|
||||
"finger1-3.l", //3
|
||||
"endsite_finger1-3.l",//4
|
||||
"finger2-1.l",//5
|
||||
"finger2-2.l",//6
|
||||
"finger2-3.l",//7
|
||||
"endsite_finger2-3.l",//8
|
||||
"finger3-1.l",//9
|
||||
"finger3-2.l",//10
|
||||
"finger3-3.l",//11
|
||||
"endsite_finger3-3.l",//12
|
||||
"finger4-1.l",//13
|
||||
"finger4-2.l",//14
|
||||
"finger4-3.l",//15
|
||||
"endsite_finger4-3.l",//16
|
||||
"finger5-1.l",//17
|
||||
"finger5-2.l",//18
|
||||
"finger5-3.l",//19
|
||||
"endsite_finger5-3.l",//20
|
||||
//--------------------
|
||||
"End of Left Hand Names"
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is an array of names for the right hand.
|
||||
* This is a "friendly" array, meaning it is meant to be easy to understand and does not need to exactly correspond to the BVH file..
|
||||
*/
|
||||
|
||||
static const char * COCORightHandFriendlyNames[] =
|
||||
{
|
||||
"Right_Hand_Wrist",//0
|
||||
"Right_Hand_Thumb_1",//1
|
||||
"Right_Hand_Thumb_2", //2
|
||||
"Right_Hand_Thumb_3", //3
|
||||
"Right_Hand_Thumb_4",//4
|
||||
"Right_Hand_Index_1",//5
|
||||
"Right_Hand_Index_2",//6
|
||||
"Right_Hand_Index_3",//7
|
||||
"Right_Hand_Index_4",//8
|
||||
"Right_Hand_Middle_1",//9
|
||||
"Right_Hand_Middle_2",//10
|
||||
"Right_Hand_Middle_3",//11
|
||||
"Right_Hand_Middle_4",//12
|
||||
"Right_Hand_Ring_1",//13
|
||||
"Right_Hand_Ring_2",//14
|
||||
"Right_Hand_Ring_3",//15
|
||||
"Right_Hand_Ring_4",//16
|
||||
"Right_Hand_Pinky_1",//17
|
||||
"Right_Hand_Pinky_2",//18
|
||||
"Right_Hand_Pinky_3",//19
|
||||
"Right_Hand_Pinky_4",//20
|
||||
//--------------------
|
||||
"End of Right Hand Names"
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is an array of names for the right hand.
|
||||
* This tries to mirror rhand_configuration.json and everything used is lowercase exactly for this reason..
|
||||
* it also has to be the same with the bvh file headerWithHeadAndOneMotion.bvh
|
||||
*/
|
||||
static const char * COCORightHandNames[] =
|
||||
{
|
||||
"rhand",//0
|
||||
"rthumb",//1
|
||||
"finger1-2.r", //2
|
||||
"finger1-3.r", //3
|
||||
"endsite_finger1-3.r",//4
|
||||
"finger2-1.r",//5
|
||||
"finger2-2.r",//6
|
||||
"finger2-3.r",//7
|
||||
"endsite_finger2-3.r",//8
|
||||
"finger3-1.r",//9
|
||||
"finger3-2.r",//10
|
||||
"finger3-3.r",//11
|
||||
"endsite_finger3-3.r",//12
|
||||
"finger4-1.r",//13
|
||||
"finger4-2.r",//14
|
||||
"finger4-3.r",//15
|
||||
"endsite_finger4-3.r",//16
|
||||
"finger5-1.r",//17
|
||||
"finger5-2.r",//18
|
||||
"finger5-3.r",//19
|
||||
"endsite_finger5-3.r",//20
|
||||
//--------------------
|
||||
"End of Right Hand Names"
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief An enumerator of COCO Hand joints
|
||||
*/
|
||||
//https://raw.githubusercontent.com/CMU-Perceptual-Computing-Lab/openpose/master/doc/media/keypoints_face.png
|
||||
enum OP_HeadJoints
|
||||
{
|
||||
OP_Head_RChin_0=0, //0
|
||||
OP_Head_RChin_1, //1
|
||||
OP_Head_RChin_2, //2
|
||||
OP_Head_RChin_3, //3
|
||||
OP_Head_RChin_4, //4
|
||||
OP_Head_RChin_5, //5
|
||||
OP_Head_RChin_6, //6
|
||||
OP_Head_RChin_7, //7
|
||||
OP_Head_Chin, //8
|
||||
OP_Head_LChin_7 , //9
|
||||
OP_Head_LChin_6, //10
|
||||
OP_Head_LChin_5, //11
|
||||
OP_Head_LChin_4, //12
|
||||
OP_Head_LChin_3, //13
|
||||
OP_Head_LChin_2, //14
|
||||
OP_Head_LChin_1, //15
|
||||
OP_Head_LChin_0, //16
|
||||
OP_Head_REyebrow_0, //17
|
||||
OP_Head_REyebrow_1, //18
|
||||
OP_Head_REyebrow_2, //19
|
||||
OP_Head_REyebrow_3, //20
|
||||
OP_Head_REyebrow_4, //21
|
||||
OP_Head_LEyebrow_4, //22
|
||||
OP_Head_LEyebrow_3, //23
|
||||
OP_Head_LEyebrow_2, //24
|
||||
OP_Head_LEyebrow_1, //25
|
||||
OP_Head_LEyebrow_0, //26
|
||||
OP_Head_NoseBone_0,//27
|
||||
OP_Head_NoseBone_1,//28
|
||||
OP_Head_NoseBone_2,//29
|
||||
OP_Head_NoseBone_3,//30
|
||||
OP_Head_Nostrills_0,//31
|
||||
OP_Head_Nostrills_1,//32
|
||||
OP_Head_Nostrills_2,//33
|
||||
OP_Head_Nostrills_3,//34
|
||||
OP_Head_Nostrills_4,//35
|
||||
OP_Head_REye_0,//36
|
||||
OP_Head_REye_1,//37
|
||||
OP_Head_REye_2,//38
|
||||
OP_Head_REye_3,//39
|
||||
OP_Head_REye_4,//40
|
||||
OP_Head_REye_5,//41
|
||||
OP_Head_LEye_0,//42
|
||||
OP_Head_LEye_1,//43
|
||||
OP_Head_LEye_2,//44
|
||||
OP_Head_LEye_3,//45
|
||||
OP_Head_LEye_4,//46
|
||||
OP_Head_LEye_5,//47
|
||||
OP_Head_OutMouth_0,//48
|
||||
OP_Head_OutMouth_1,//49
|
||||
OP_Head_OutMouth_2,//50
|
||||
OP_Head_OutMouth_3,//51
|
||||
OP_Head_OutMouth_4,//52
|
||||
OP_Head_OutMouth_5,//53
|
||||
OP_Head_OutMouth_6,//54
|
||||
OP_Head_OutMouth_7,//55
|
||||
OP_Head_OutMouth_8,//56
|
||||
OP_Head_OutMouth_9,//57
|
||||
OP_Head_OutMouth_10,//58
|
||||
OP_Head_OutMouth_11,//59
|
||||
OP_Head_InMouth_0,//60
|
||||
OP_Head_InMouth_1,//61
|
||||
OP_Head_InMouth_2,//62
|
||||
OP_Head_InMouth_3,//63
|
||||
OP_Head_InMouth_4,//64
|
||||
OP_Head_InMouth_5,//65
|
||||
OP_Head_InMouth_6,//66
|
||||
OP_Head_InMouth_7,//67
|
||||
OP_Head_REye,//68
|
||||
OP_Head_LEye,//69
|
||||
//---------------------
|
||||
OP_HEAD_PARTS
|
||||
};
|
||||
|
||||
|
||||
static const char * HeadNames[] =
|
||||
{
|
||||
"Head_RChin_0", //0
|
||||
"Head_RChin_1", //1
|
||||
"Head_RChin_2", //2
|
||||
"Head_RChin_3", //3
|
||||
"Head_RChin_4", //4
|
||||
"Head_RChin_5", //5
|
||||
"Head_RChin_6", //6
|
||||
"Head_RChin_7", //7
|
||||
"Head_Chin", //8
|
||||
"Head_LChin_7", //9
|
||||
"Head_LChin_6", //10
|
||||
"Head_LChin_5", //11
|
||||
"Head_LChin_4", //12
|
||||
"Head_LChin_3", //13
|
||||
"Head_LChin_2", //14
|
||||
"Head_LChin_1", //15
|
||||
"Head_LChin_0", //16
|
||||
"Head_REyebrow_0",//17
|
||||
"Head_REyebrow_1",//18
|
||||
"Head_REyebrow_2",//19
|
||||
"Head_REyebrow_3",//20
|
||||
"Head_REyebrow_4",//21
|
||||
"Head_LEyebrow_4",//22
|
||||
"Head_LEyebrow_3",//23
|
||||
"Head_LEyebrow_2",//24
|
||||
"Head_LEyebrow_1",//25
|
||||
"Head_LEyebrow_0",//26
|
||||
"Head_NoseBone_0",//27
|
||||
"Head_NoseBone_1",//28
|
||||
"Head_NoseBone_2",//29
|
||||
"Head_NoseBone_3",//30
|
||||
"Head_Nostrills_0",//31
|
||||
"Head_Nostrills_1",//32
|
||||
"Head_Nostrills_2",//33
|
||||
"Head_Nostrills_3",//34
|
||||
"Head_Nostrills_4",//35
|
||||
"Head_REye_0",//36
|
||||
"Head_REye_1",//37
|
||||
"Head_REye_2",//38
|
||||
"Head_REye_3",//39
|
||||
"Head_REye_4",//40
|
||||
"Head_REye_5",//41
|
||||
"Head_LEye_0",//42
|
||||
"Head_LEye_1",//43
|
||||
"Head_LEye_2",//44
|
||||
"Head_LEye_3",//45
|
||||
"Head_LEye_4",//46
|
||||
"Head_LEye_5",//47
|
||||
"Head_OutMouth_0",//48
|
||||
"Head_OutMouth_1",//49
|
||||
"Head_OutMouth_2",//50
|
||||
"Head_OutMouth_3",//51
|
||||
"Head_OutMouth_4",//52
|
||||
"Head_OutMouth_5",//53
|
||||
"Head_OutMouth_6",//54
|
||||
"Head_OutMouth_7",//55
|
||||
"Head_OutMouth_8",//56
|
||||
"Head_OutMouth_9",//57
|
||||
"Head_OutMouth_10",//58
|
||||
"Head_OutMouth_11",//59
|
||||
"Head_InMouth_0",//60
|
||||
"Head_InMouth_1",//61
|
||||
"Head_InMouth_2",//62
|
||||
"Head_InMouth_3",//63
|
||||
"Head_InMouth_4",//64
|
||||
"Head_InMouth_5",//65
|
||||
"Head_InMouth_6",//66
|
||||
"Head_InMouth_7",//67
|
||||
"Head_REye",//68
|
||||
"Head_LEye"//69
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A C struct to hold a hand. It contains its 2D points, its 3D points and some flags that signal
|
||||
*/
|
||||
struct handCOCO
|
||||
{
|
||||
int isPopulated;
|
||||
int isLeft;
|
||||
int isRight;
|
||||
|
||||
struct point2D joint2D[COCO_HAND_PARTS];
|
||||
float jointAccuracy[COCO_HAND_PARTS];
|
||||
unsigned int active[COCO_HAND_PARTS];
|
||||
struct point3D joint[COCO_HAND_PARTS];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A C struct to hold a hand. It contains its 2D points, its 3D points and some flags that signal
|
||||
*/
|
||||
struct headOP
|
||||
{
|
||||
int isPopulated;
|
||||
struct point2D joint2D[OP_HEAD_PARTS];
|
||||
float jointAccuracy[OP_HEAD_PARTS];
|
||||
unsigned int active[OP_HEAD_PARTS];
|
||||
struct point3D joint[OP_HEAD_PARTS];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A C struct to hold a body. It contains its 2D points, its 3D points and some flags that signal
|
||||
*/
|
||||
struct body25OP
|
||||
{
|
||||
int isPopulated;
|
||||
struct point2D joint2D[BODY25_PARTS];
|
||||
struct point2D bbox2D[2];
|
||||
|
||||
float jointAccuracy[BODY25_PARTS];
|
||||
unsigned int active[BODY25_PARTS];
|
||||
struct point3D joint[BODY25_PARTS];
|
||||
struct point3D bbox[8];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief A C struct to hold a skeleton. It contains its 2D points, its 3D points and some flags that signal
|
||||
*/
|
||||
struct skeletonStructure
|
||||
{
|
||||
unsigned int observationNumber , observationTotal;
|
||||
unsigned int userID;
|
||||
unsigned int totalUsersPresent;
|
||||
//------------------------
|
||||
struct body25OP body;
|
||||
struct handCOCO leftHand;
|
||||
struct handCOCO rightHand;
|
||||
struct headOP head;
|
||||
//------------------------
|
||||
struct boundingBox bbox2D;
|
||||
};
|
||||
|
||||
|
||||
struct headerField
|
||||
{
|
||||
unsigned int strLength;
|
||||
char * str;
|
||||
};
|
||||
|
||||
|
||||
struct bodyField
|
||||
{
|
||||
float value;
|
||||
};
|
||||
|
||||
|
||||
struct skeletonSerialized
|
||||
{
|
||||
unsigned int skeletonHeaderElements;
|
||||
struct headerField skeletonHeader[512];
|
||||
|
||||
unsigned int skeletonBodyElements;
|
||||
struct bodyField skeletonBody[512];
|
||||
|
||||
float width;
|
||||
float height;
|
||||
};
|
||||
|
||||
|
||||
static void printSkeletonSerialized(const char * msg, struct skeletonSerialized * sk )
|
||||
{
|
||||
if (msg!=0)
|
||||
{
|
||||
fprintf(stderr,"printSkeletonSerialized (%s)\n",msg);
|
||||
}
|
||||
|
||||
if (sk==0)
|
||||
{
|
||||
fprintf(stderr,"struct skeletonSerialized that was given as input is not allocated\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sk->skeletonHeaderElements != sk->skeletonBodyElements)
|
||||
{
|
||||
fprintf(stderr,"struct skeletonSerialized is corrupted since it has a different number of head and body records..\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr,"Serialization has %u elements\n",sk->skeletonHeaderElements);
|
||||
for (unsigned int skID = 0; skID<sk->skeletonHeaderElements; skID++)
|
||||
{
|
||||
if (sk->skeletonHeader[skID].str==0)
|
||||
{
|
||||
fprintf(stderr," Serial #%u has an empty label => % 0.2f \n" ,skID , sk->skeletonBody[skID].value);
|
||||
} else
|
||||
{
|
||||
fprintf(stderr," %s => % 0.2f \n" ,sk->skeletonHeader[skID].str , sk->skeletonBody[skID].value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,827 @@
|
||||
#include "conversions.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include "../tools.hpp"
|
||||
#include "bvh.hpp"
|
||||
|
||||
#include "csvRead.hpp"
|
||||
#include "../../../../dependencies/RGBDAcquisition/tools/AmMatrix/matrix4x4Tools.h"
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
int appendVectorToFile(const char * filename, std::vector<float> vec)
|
||||
{
|
||||
FILE * fp = fopen(filename,"a");
|
||||
if (fp!=0)
|
||||
{
|
||||
for (unsigned int i=0; i<vec.size(); i++)
|
||||
{
|
||||
if (i!=0) { fprintf(fp,","); }
|
||||
fprintf(fp,"%f",vec[i]);
|
||||
}
|
||||
fprintf(fp,"\n");
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int initializeAssociationsForSubsetOfSkeleton(unsigned int * targetIndexIsInitializedFlag,unsigned int * targetIndexes,unsigned int targetLength,const char * * targetLabels,struct skeletonSerialized * input)
|
||||
{
|
||||
//int i=0,z=0;
|
||||
|
||||
for (unsigned int i=0; i<targetLength; i++)
|
||||
{
|
||||
targetIndexes[i]=666;
|
||||
}
|
||||
|
||||
|
||||
char targetLabelLowercase[513]={0};
|
||||
for (unsigned int i=0; i<targetLength; i++)
|
||||
{
|
||||
convertStringToLowercase(targetLabelLowercase,512,targetLabels[i]);
|
||||
|
||||
for (unsigned int z=0; z<input->skeletonHeaderElements; z++)
|
||||
{
|
||||
if (input->skeletonHeader[z].str!=0)
|
||||
{
|
||||
if (strcmp(input->skeletonHeader[z].str,targetLabelLowercase)==0)
|
||||
{
|
||||
if (targetIndexes[i]==666)
|
||||
{
|
||||
targetIndexes[i]=z;
|
||||
fprintf(stderr,GREEN "%s==%s\n" NORMAL,input->skeletonHeader[z].str,targetLabelLowercase);
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,YELLOW "%s==%s multiple times, only keeping first association..\n" NORMAL,input->skeletonHeader[z].str,targetLabelLowercase);
|
||||
}
|
||||
} //We have a matching string..
|
||||
} //There is a string to compare
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int unassociatedJoints=0;
|
||||
for (unsigned int i=0; i<targetLength; i++)
|
||||
{
|
||||
if ( targetIndexes[i]==666 ) {
|
||||
++unassociatedJoints;
|
||||
fprintf(stderr,RED "Joint %s(%u) is not associated\n" NORMAL,targetLabels[i],i);
|
||||
} else
|
||||
{ fprintf(stderr,GREEN "Joint %s(%u) associated\n" NORMAL,targetLabels[i],i); }
|
||||
}
|
||||
|
||||
*targetIndexIsInitializedFlag=(unassociatedJoints==0);
|
||||
|
||||
return (unassociatedJoints==0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::vector<float> deriveMocapNET2InputUsingAssociations(struct MocapNET2 * mnet,struct skeletonSerialized * input,unsigned int * targetIndexIsInitializedFlag,unsigned int * targetIndexes,unsigned int targetLength,const char * * targetLabels,int verbose)
|
||||
{
|
||||
std::vector<float> result;
|
||||
|
||||
if (mnet->indexesPopulated)
|
||||
{
|
||||
|
||||
if (! *targetIndexIsInitializedFlag)
|
||||
{
|
||||
fprintf(stderr,RED "deriveMocapNET2InputUsingAssociations called without initialization\n" NORMAL);
|
||||
|
||||
initializeAssociationsForSubsetOfSkeleton(
|
||||
targetIndexIsInitializedFlag,
|
||||
targetIndexes,
|
||||
targetLength,
|
||||
targetLabels,
|
||||
input
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
for (int i=0; i<targetLength; i++)
|
||||
{
|
||||
if (verbose) { fprintf(stderr,"%s = %0.2f -> %s \n" , input->skeletonHeader[targetIndexes[i]].str , input->skeletonBody[targetIndexes[i]].value ,targetLabels[i]); }
|
||||
result.push_back(input->skeletonBody[targetIndexes[i]].value);
|
||||
}
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,RED "initializeAssociationsForSubsetOfSkeleton has to be run at initialization before deriveMocapNET2InputUsingAssociations\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int convertSkeletons2DDetectedToSkeletonsSerialized(
|
||||
struct skeletonSerialized * output,
|
||||
struct Skeletons2DDetected * input,
|
||||
unsigned int frameNumber,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
)
|
||||
{
|
||||
int check;
|
||||
if (output->skeletonHeaderElements==0)
|
||||
{
|
||||
//Brand new header that needs to be populated..!
|
||||
int elementsPopulated=3;
|
||||
output->skeletonHeader[0].strLength = 12;
|
||||
output->skeletonHeader[0].str=(char *) malloc(sizeof(char) * output->skeletonHeader[0].strLength);
|
||||
snprintf(output->skeletonHeader[0].str,output->skeletonHeader[0].strLength,"frameNumber");
|
||||
|
||||
output->skeletonHeader[1].strLength = 11;
|
||||
output->skeletonHeader[1].str=(char *) malloc(sizeof(char) * output->skeletonHeader[1].strLength);
|
||||
snprintf(output->skeletonHeader[1].str,output->skeletonHeader[1].strLength,"skeletonID");
|
||||
|
||||
output->skeletonHeader[2].strLength = 15;
|
||||
output->skeletonHeader[2].str=(char *) malloc(sizeof(char) * output->skeletonHeader[2].strLength);
|
||||
snprintf(output->skeletonHeader[2].str,output->skeletonHeader[2].strLength,"totalSkeletons");
|
||||
|
||||
char lowercaseName[512]={0};
|
||||
|
||||
for (int i=0; i<BODY25_PARTS; i++)
|
||||
{
|
||||
convertStringToLowercase(lowercaseName,512,Body25BodyNames[i]);
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"2dx_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"2dy_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+9;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"visible_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
for (int i=0; i<COCO_HAND_PARTS; i++)
|
||||
{
|
||||
convertStringToLowercase(lowercaseName,512,COCOLeftHandNames[i]);
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"2dx_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"2dy_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+9;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"visible_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
for (int i=0; i<COCO_HAND_PARTS; i++)
|
||||
{
|
||||
convertStringToLowercase(lowercaseName,512,COCORightHandNames[i]);
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"2dx_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"2dy_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+9;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"visible_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
for (int i=0; i<OP_HEAD_PARTS; i++)
|
||||
{
|
||||
convertStringToLowercase(lowercaseName,512,HeadNames[i]);
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"2dx_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+5;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"2dy_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
output->skeletonHeader[elementsPopulated].strLength= strlen(lowercaseName)+9;
|
||||
output->skeletonHeader[elementsPopulated].str = ( char* ) malloc( sizeof(char) * output->skeletonHeader[elementsPopulated].strLength);
|
||||
if (output->skeletonHeader[elementsPopulated].str!=0)
|
||||
{
|
||||
check = snprintf(
|
||||
output->skeletonHeader[elementsPopulated].str ,
|
||||
output->skeletonHeader[elementsPopulated].strLength,
|
||||
"visible_%s",
|
||||
lowercaseName
|
||||
);
|
||||
if (check<0) { return 0; }
|
||||
} else { return 0; }
|
||||
++elementsPopulated;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
output->skeletonHeaderElements = elementsPopulated;
|
||||
}
|
||||
// Reduce spam
|
||||
// else
|
||||
//{
|
||||
// fprintf(stderr,"SkeletonSerialized appears to be already populated, skipping re allocating everything..\n");
|
||||
//}
|
||||
|
||||
|
||||
//=================================================================================
|
||||
//=================================================================================
|
||||
//=================================================================================
|
||||
//=================================================================================
|
||||
//=================================================================================
|
||||
// Now to convert the values..
|
||||
//=================================================================================
|
||||
//=================================================================================
|
||||
//=================================================================================
|
||||
//=================================================================================
|
||||
//=================================================================================
|
||||
|
||||
output->skeletonBodyElements = output->skeletonHeaderElements;
|
||||
|
||||
//Points will be normalized using normalize2DPointWhileAlsoMatchingTrainingAspectRatio
|
||||
output->width = 1.0;
|
||||
output->height = 1.0;
|
||||
|
||||
for (unsigned int skID=0; skID<input->numberOfSkeletonsDetected; skID++)
|
||||
{
|
||||
int bodyElementsPopulated=3;
|
||||
output->skeletonBody[0].value = frameNumber;
|
||||
output->skeletonBody[1].value = skID;
|
||||
output->skeletonBody[2].value = input->numberOfSkeletonsDetected;
|
||||
|
||||
for (int i=0; i<BODY25_PARTS; i++)
|
||||
{
|
||||
//Normalize targets --------------------------------------------------------------
|
||||
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
&input->skeletons[skID].body.joint2D[i].x,
|
||||
&input->skeletons[skID].body.joint2D[i].y,
|
||||
width,
|
||||
height,
|
||||
1,//Respect training aspect ratio
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
);
|
||||
//--------------------------------------------------------------------------------
|
||||
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].body.joint2D[i].x;
|
||||
++bodyElementsPopulated;
|
||||
|
||||
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].body.joint2D[i].y;
|
||||
++bodyElementsPopulated;
|
||||
|
||||
output->skeletonBody[bodyElementsPopulated].value = ( (input->skeletons[skID].body.joint2D[i].x!=0) && (input->skeletons[skID].body.joint2D[i].y!=0) ) ;
|
||||
/*
|
||||
if (!output->skeletonBody[bodyElementsPopulated].value)
|
||||
{
|
||||
fprintf(stderr,"%s not populated.. \n" ,Body25BodyNames[i]);
|
||||
}*/
|
||||
++bodyElementsPopulated;
|
||||
//--------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<COCO_HAND_PARTS; i++)
|
||||
{
|
||||
//Normalize targets --------------------------------------------------------------
|
||||
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
&input->skeletons[skID].leftHand.joint2D[i].x,
|
||||
&input->skeletons[skID].leftHand.joint2D[i].y,
|
||||
width,
|
||||
height,
|
||||
1,//Respect training aspect ratio
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
);
|
||||
//--------------------------------------------------------------------------------
|
||||
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].leftHand.joint2D[i].x;
|
||||
++bodyElementsPopulated;
|
||||
|
||||
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].leftHand.joint2D[i].y;
|
||||
++bodyElementsPopulated;
|
||||
|
||||
output->skeletonBody[bodyElementsPopulated].value =( (input->skeletons[skID].leftHand.joint2D[i].x!=0) && (input->skeletons[skID].leftHand.joint2D[i].y!=0) ) ;
|
||||
++bodyElementsPopulated;
|
||||
//--------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<COCO_HAND_PARTS; i++)
|
||||
{
|
||||
//Normalize targets --------------------------------------------------------------
|
||||
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
&input->skeletons[skID].rightHand.joint2D[i].x,
|
||||
&input->skeletons[skID].rightHand.joint2D[i].y,
|
||||
width,
|
||||
height,
|
||||
1,//Respect training aspect ratio
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
);
|
||||
//--------------------------------------------------------------------------------
|
||||
output->skeletonBody[bodyElementsPopulated].value = input->skeletons[skID].rightHand.joint2D[i].x;
|
||||
++bodyElementsPopulated;
|
||||
|
||||
output->skeletonBody[bodyElementsPopulated].value = input->skeletons[skID].rightHand.joint2D[i].y;
|
||||
++bodyElementsPopulated;
|
||||
|
||||
output->skeletonBody[bodyElementsPopulated].value = ( (input->skeletons[skID].rightHand.joint2D[i].x!=0) && (input->skeletons[skID].rightHand.joint2D[i].y!=0) );
|
||||
++bodyElementsPopulated;
|
||||
//--------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
for (int i=0; i<OP_HEAD_PARTS; i++)
|
||||
{
|
||||
//Normalize targets --------------------------------------------------------------
|
||||
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
&input->skeletons[skID].head.joint2D[i].x,
|
||||
&input->skeletons[skID].head.joint2D[i].y,
|
||||
width,
|
||||
height,
|
||||
1,//Respect training aspect ratio
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
);
|
||||
//--------------------------------------------------------------------------------
|
||||
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].head.joint2D[i].x;
|
||||
++bodyElementsPopulated;
|
||||
|
||||
output->skeletonBody[bodyElementsPopulated].value = (float) input->skeletons[skID].head.joint2D[i].y;
|
||||
++bodyElementsPopulated;
|
||||
|
||||
output->skeletonBody[bodyElementsPopulated].value = ( (input->skeletons[skID].head.joint2D[i].x!=0) && (input->skeletons[skID].head.joint2D[i].y!=0) );
|
||||
++bodyElementsPopulated;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int convertMocapNET2OutputToSkeletonSerialized(
|
||||
struct MocapNET2 * mnet,
|
||||
struct skeletonSerialized * output,
|
||||
std::vector<std::vector<float> > mocapNET2DPointsResult,
|
||||
unsigned int frameNumber,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
)
|
||||
{
|
||||
if (mocapNET2DPointsResult.size()==0)
|
||||
{
|
||||
fprintf(stderr,"convertMocapNET2OutputToSkeletonSerialized cannot work without 3D point results\n");
|
||||
return 0;
|
||||
}
|
||||
struct Skeletons2DDetected input={0};
|
||||
|
||||
input.numberOfSkeletonsDetected=1;
|
||||
input.skeletons[0].body.joint2D[BODY25_Nose].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS05][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_Nose].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS05][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_Neck].x = mocapNET2DPointsResult[MOCAPNET_JOINT_NECK][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_Neck].y = mocapNET2DPointsResult[MOCAPNET_JOINT_NECK][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_RShoulder].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RSHOULDER][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_RShoulder].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RSHOULDER][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_RElbow].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RELBOW][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_RElbow].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RELBOW][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_RWrist].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RHAND][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_RWrist].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RHAND][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_LShoulder].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LSHOULDER][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LShoulder].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LSHOULDER][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_LElbow].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LELBOW][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LElbow].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LELBOW][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_LWrist].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LHAND][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LWrist].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LHAND][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_MidHip].x = mocapNET2DPointsResult[MOCAPNET_JOINT_HIP][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_MidHip].y = mocapNET2DPointsResult[MOCAPNET_JOINT_HIP][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_RHip].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RHIP][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_RHip].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RHIP][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_RKnee].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RKNEE][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_RKnee].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RKNEE][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_RAnkle].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RFOOT][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_RAnkle].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RFOOT][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_LHip].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LHIP][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LHip].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LHIP][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_LKnee].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LKNEE][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LKnee].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LKNEE][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_LAnkle].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LFOOT][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LAnkle].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LFOOT][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_REye].x = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_R][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_REye].y = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_R][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_LEye].x = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_L][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LEye].y = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_L][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_REar].x = mocapNET2DPointsResult[MOCAPNET_JOINT_TEMPORALIS02_R][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_REar].y = mocapNET2DPointsResult[MOCAPNET_JOINT_TEMPORALIS02_R][1];
|
||||
input.skeletons[0].body.joint2D[BODY25_LEar].x = mocapNET2DPointsResult[MOCAPNET_JOINT_TEMPORALIS02_L][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LEar].y = mocapNET2DPointsResult[MOCAPNET_JOINT_TEMPORALIS02_L][1];
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_LBigToe].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE1_2_L][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LBigToe].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE1_2_L][1];
|
||||
input.skeletons[0].body.joint2D[BODY25_LSmallToe].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE5_3_L][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LSmallToe].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE5_3_L][1];
|
||||
input.skeletons[0].body.joint2D[BODY25_LHeel].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LFOOT][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_LHeel].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LFOOT][1];
|
||||
|
||||
|
||||
input.skeletons[0].body.joint2D[BODY25_RBigToe].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE1_2_R][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_RBigToe].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE1_2_R][1];
|
||||
input.skeletons[0].body.joint2D[BODY25_RSmallToe].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE5_3_R][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_RSmallToe].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_TOE5_3_R][1];
|
||||
input.skeletons[0].body.joint2D[BODY25_RHeel].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RFOOT][0];
|
||||
input.skeletons[0].body.joint2D[BODY25_RHeel].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RFOOT][1];
|
||||
//Dont forget to update convertBodySkeletonSerializedToBVHTransform
|
||||
|
||||
|
||||
//Populate right hand
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Wrist].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RHAND][0]; //MOCAPNET_OUTPUT_JOINT_RHAND
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Wrist].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RHAND][1]; //MOCAPNET_OUTPUT_JOINT_RHAND
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_RTHUMB][0]; //MOCAPNET_OUTPUT_JOINT_RTHUMB
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_RTHUMB][1]; //MOCAPNET_OUTPUT_JOINT_RTHUMB
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_2_R][0]; //MOCAPNET_OUTPUT_JOINT_RTHUMB
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_2_R][1]; //MOCAPNET_OUTPUT_JOINT_RTHUMB
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER1_2_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER1_2_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER1_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER1_3_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Thumb_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER1_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER1_3_R
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_1_R][0]; //MOCAPNET_OUTPUT_JOINT_METACARPAL1_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_1_R][1]; //MOCAPNET_OUTPUT_JOINT_METACARPAL1_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_2_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER2_1_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_2_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER2_1_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER2_2_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER2_2_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER2_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER2_3_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Index_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER2_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER2_3_R
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_1_R][0];//MOCAPNET_OUTPUT_JOINT_METACARPAL2_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_1_R][1];
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_2_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER3_1_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_2_R][1];
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER3_2_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_3_R][1];
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER3_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER3_3_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Middle_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER3_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER3_3_R
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_1_R][0]; //MOCAPNET_OUTPUT_JOINT_METACARPAL3_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_1_R][1];
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_2_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER4_1_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_2_R][1];
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER4_2_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_3_R][1];
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER4_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER4_3_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Ring_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER4_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER4_3_R
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_1_R][0]; //MOCAPNET_OUTPUT_JOINT_METACARPAL4_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_1_R][1];
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_2_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER5_1_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_2_R][1];
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER5_2_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_3_R][1];
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER5_3_R][0]; //MOCAPNET_OUTPUT_JOINT_FINGER5_3_R
|
||||
input.skeletons[0].rightHand.joint2D[COCO_Hand_Pinky_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER5_3_R][1]; //MOCAPNET_OUTPUT_JOINT_FINGER5_3_R
|
||||
//---------------------------------------------------------------------------------
|
||||
//Dont forget convertRHandSkeletonSerializedToBVHTransform needs to also be updated
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Populate left hand
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Wrist].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LHAND][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Wrist].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LHAND][1];
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_LTHUMB][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_LTHUMB][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_2_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_2_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER1_3_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER1_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Thumb_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER1_3_L][1];
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_1_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_1_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_2_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_2_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER2_3_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER2_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Index_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER2_3_L][1]; //Maybe the end site is prefereable?
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_1_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_1_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_2_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_2_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER3_3_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER3_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Middle_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER3_3_L][1]; //Maybe the end site is prefereable?
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_1_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_1_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_2_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_2_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER4_3_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER4_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Ring_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER4_3_L][1]; //Maybe the end site is prefereable?
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_1_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_1_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_2_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_2_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_FINGER5_3_L][1];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_4].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER5_3_L][0];
|
||||
input.skeletons[0].leftHand.joint2D[COCO_Hand_Pinky_4].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ENDSITE_FINGER5_3_L][1]; //Maybe the end site is prefereable?
|
||||
//---------------------------------------------------------------------------------
|
||||
//Dont forget convertLHandSkeletonSerializedToBVHTransform needs to also be updated
|
||||
|
||||
|
||||
|
||||
|
||||
//Populate face
|
||||
input.skeletons[0].head.joint2D[OP_Head_REye_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS03_R][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_REye_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS03_R][1];
|
||||
input.skeletons[0].head.joint2D[OP_Head_REye].x = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_R][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_REye].y = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_R][1];
|
||||
input.skeletons[0].head.joint2D[OP_Head_REye_5].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS04_R][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_REye_5].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS04_R][1];
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].head.joint2D[OP_Head_LEye_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS03_L][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_LEye_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS03_L][1];
|
||||
input.skeletons[0].head.joint2D[OP_Head_LEye].x = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_L][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_LEye].y = mocapNET2DPointsResult[MOCAPNET_JOINT_EYE_L][1];
|
||||
input.skeletons[0].head.joint2D[OP_Head_LEye_5].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS04_L][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_LEye_5].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORBICULARIS04_L][1];
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].head.joint2D[OP_Head_Chin].x = mocapNET2DPointsResult[MOCAPNET_JOINT_SPECIAL04][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_Chin].y = mocapNET2DPointsResult[MOCAPNET_JOINT_SPECIAL04][1];
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_1].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS03_R][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_1].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS03_R][1];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_2].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS05][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_2].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS05][1];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_3].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS03_L][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_3].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS03_L][1];
|
||||
//---------------------------------------------------------------------------------
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_7].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS07_R][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_7].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS07_R][1];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_6].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS01][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_6].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS01][1];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_5].x = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS07_L][0];
|
||||
input.skeletons[0].head.joint2D[OP_Head_InMouth_5].y = mocapNET2DPointsResult[MOCAPNET_JOINT_ORIS07_L][1];
|
||||
//---------------------------------------------------------------------------------
|
||||
// Dont forget to update convertFaceSkeletonSerializedToBVHTransform
|
||||
|
||||
/*
|
||||
for (int jID=0; jID<getBVHNumberOfJoints(); jID++)
|
||||
{
|
||||
const char * jointName = getBVHJointName(jID);
|
||||
fprintf(stderr,"%u = %s \n",jID,jointName);
|
||||
|
||||
}*/
|
||||
|
||||
return convertSkeletons2DDetectedToSkeletonsSerialized(
|
||||
output,
|
||||
&input,
|
||||
frameNumber,
|
||||
width,
|
||||
height
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int affineSkeletonRotation(struct skeletonSerialized * input,float degrees)
|
||||
{
|
||||
if (degrees==0.0) { return 1; }
|
||||
//---------------------------------------------------------------------------
|
||||
float rad = degrees_to_radF(degrees);
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
unsigned int hipJoint = 1 + BODY25_MidHip; //+1 because the first three parameters are for skeleton ids etc.
|
||||
float hipX = input->skeletonBody[hipJoint*3+0].value;
|
||||
float hipY = input->skeletonBody[hipJoint*3+1].value;
|
||||
char hipVisibility = (input->skeletonBody[hipJoint*3+2].value > 0.0);
|
||||
|
||||
if (hipVisibility)
|
||||
{
|
||||
if (input!=0)
|
||||
{
|
||||
for (unsigned int jID = 0; jID< input->skeletonBodyElements/3; jID++)
|
||||
{
|
||||
float x=input->skeletonBody[jID*3+0].value;
|
||||
float y=input->skeletonBody[jID*3+1].value;
|
||||
char visibility=(char) (input->skeletonBody[jID*3+2].value > 0.0);
|
||||
|
||||
if (visibility)
|
||||
{
|
||||
//Subtract HIP from every joint and perform a 2D rotation using the rad variable
|
||||
float unrotatedX = x-hipX;
|
||||
//Subtract HIP from every joint and perform a 2D rotation using the rad variable
|
||||
float unrotatedY = y-hipY;
|
||||
|
||||
input->skeletonBody[jID*3+0].value = hipX + (unrotatedX * cosf(rad)) - (unrotatedY * sinf(rad));
|
||||
input->skeletonBody[jID*3+1].value = hipY + (unrotatedX * sinf(rad)) + (unrotatedY * cosf(rad));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
float rotationRequiredToMakeSkeletonCloserToTrainingDataset(struct skeletonSerialized * input)
|
||||
{
|
||||
//--------------------------------------------------------------------
|
||||
unsigned int hipJoint = 1 + BODY25_MidHip; //+1 because the first three parameters are for skeleton ids etc.
|
||||
float hipX = input->skeletonBody[hipJoint*3+0].value;
|
||||
float hipY = input->skeletonBody[hipJoint*3+1].value;
|
||||
char hipVisibility = (input->skeletonBody[hipJoint*3+2].value > 0.0);
|
||||
//--------------------------------------------------------------------
|
||||
unsigned int neckJoint = 1 + BODY25_Neck; //+1 because the first three parameters are for skeleton ids etc.
|
||||
float neckX = input->skeletonBody[neckJoint*3+0].value;
|
||||
float neckY = input->skeletonBody[neckJoint*3+1].value;
|
||||
char neckVisibility = (input->skeletonBody[neckJoint*3+2].value > 0.0);
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
if ( (hipVisibility) && (neckVisibility) )
|
||||
{
|
||||
float alignmentAngle=getAngleToAlignToZero_tools(hipX,hipY,neckX,neckY);
|
||||
return alignmentAngle;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
int makeSkeletonUpright(struct skeletonSerialized * input)
|
||||
{
|
||||
float angleCorrectionNeededInDegrees = 180 + goFromRadToDegrees * rotationRequiredToMakeSkeletonCloserToTrainingDataset(input);
|
||||
|
||||
if (angleCorrectionNeededInDegrees!=180.0)
|
||||
{
|
||||
return affineSkeletonRotation(input,angleCorrectionNeededInDegrees);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
/** @file conversions.hpp
|
||||
* @brief Unfortunately due to the complexity of the problem and the different libraries used there cannot be a single skeleton representation.
|
||||
* This module handles conversions between std::vector<float> which is used by Tensorflow/NeuralNetwork layer , skeletonSerialized which is used by MocapNET and Skeletons2DDetected which is used by the 2D estimator
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include "../mocapnet2.hpp"
|
||||
#include "../../../JointEstimator2D/jointEstimator2D.hpp"
|
||||
|
||||
|
||||
int appendVectorToFile(const char * filename, std::vector<float> vec);
|
||||
|
||||
int initializeAssociationsForSubsetOfSkeleton(
|
||||
unsigned int * targetIndexIsInitializedFlag,
|
||||
unsigned int * targetIndexes,
|
||||
unsigned int targetLength,
|
||||
const char * * targetLabels,
|
||||
struct skeletonSerialized * input
|
||||
);
|
||||
|
||||
|
||||
|
||||
std::vector<float> deriveMocapNET2InputUsingAssociations(
|
||||
struct MocapNET2 * mnet,
|
||||
struct skeletonSerialized * input,
|
||||
unsigned int * targetIndexIsInitializedFlag,
|
||||
unsigned int * targetIndexes,
|
||||
unsigned int targetLength,
|
||||
const char * * targetLabels,
|
||||
int verbose
|
||||
);
|
||||
|
||||
|
||||
|
||||
int convertSkeletons2DDetectedToSkeletonsSerialized(
|
||||
struct skeletonSerialized * output,
|
||||
struct Skeletons2DDetected * input,
|
||||
unsigned int frameNumber,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
);
|
||||
|
||||
|
||||
int convertMocapNET2OutputToSkeletonSerialized(
|
||||
struct MocapNET2 * mnet ,
|
||||
struct skeletonSerialized * output ,
|
||||
std::vector<std::vector<float> > mocapNET2DPointsResult,
|
||||
unsigned int frameNumber,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
);
|
||||
|
||||
|
||||
|
||||
int affineSkeletonRotation(struct skeletonSerialized * input,float degrees);
|
||||
|
||||
float rotationRequiredToMakeSkeletonCloserToTrainingDataset(struct skeletonSerialized * input);
|
||||
|
||||
int makeSkeletonUpright(struct skeletonSerialized * input);
|
||||
@@ -0,0 +1,653 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "csvRead.hpp"
|
||||
#include "../../MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../../MocapNETLib2/IO/jsonMocapNETHelpers.hpp"
|
||||
|
||||
#include "../../../../dependencies/InputParser/InputParser_C.h"
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
|
||||
unsigned int getBodyLinesOfCSVFIle(struct CSVFileContext * csv,const char * filename)
|
||||
{
|
||||
FILE * fp = fopen(filename,"r");
|
||||
{
|
||||
// Extract characters from file and store in character c
|
||||
unsigned int count=0;
|
||||
char c;
|
||||
for (c = getc(fp); c != EOF; c = getc(fp))
|
||||
if (c == '\n') // Increment count if this character is newline
|
||||
{
|
||||
count = count + 1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
//The first line of a CSV is its header so we don't count this ..
|
||||
if (count>0)
|
||||
{
|
||||
--count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int openCSVFile(struct CSVFileContext * csv,const char * filename)
|
||||
{
|
||||
csv->fp = fopen(filename,"r");
|
||||
if (csv->fp!=0)
|
||||
{
|
||||
csv->lineNumber=0;
|
||||
csv->numberOfHeaderFields=0;
|
||||
fprintf(stderr,GREEN "Successfully opened CSV file %s\n" NORMAL,filename);
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr,RED "Failed to open CSV file %s\n" NORMAL,filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int closeCSVFile(struct CSVFileContext * csv)
|
||||
{
|
||||
if (csv==0)
|
||||
{
|
||||
fprintf(stderr,RED "Dont need to close empty CSV struct..\n" NORMAL);
|
||||
return 1;
|
||||
}
|
||||
if (csv->fp==0)
|
||||
{
|
||||
fprintf(stderr,RED "Dont need to close CSV header that has already been closed..\n" NORMAL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (csv->fp!=0)
|
||||
{
|
||||
//TODO FREE STUFF HERE..
|
||||
int i=0;
|
||||
for (i=0; i<csv->numberOfHeaderFields; i++)
|
||||
{
|
||||
if (csv->field[i].str!=0)
|
||||
{
|
||||
free(csv->field[i].str);
|
||||
csv->field[i].str=0;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(csv->fp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int parseCSVHeader(struct CSVFileContext * csv)
|
||||
{
|
||||
if (csv==0)
|
||||
{
|
||||
fprintf(stderr,RED "Cannot parse empty CSV header..\n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
if (csv->fp==0)
|
||||
{
|
||||
fprintf(stderr,RED "Cannot parse CSV header that hasn't been opened using openCSVFile..\n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr,"Parsing CSV header..\n");
|
||||
char whereToStoreItems[513]= {0};
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
if (csv->lineNumber==0)
|
||||
{
|
||||
read = getline(&line, &len, csv->fp);
|
||||
if (line!=0)
|
||||
{
|
||||
struct InputParserC * ipc = InputParser_Create(8096,4);
|
||||
InputParser_SetDelimeter(ipc,0,',');
|
||||
InputParser_SetDelimeter(ipc,1,0);
|
||||
InputParser_SetDelimeter(ipc,2,10);
|
||||
InputParser_SetDelimeter(ipc,3,13);
|
||||
|
||||
int numberOfArguments = InputParser_SeperateWords(ipc,line,1);
|
||||
|
||||
if (numberOfArguments<MAX_CSV_HEADER_FIELDS)
|
||||
{
|
||||
int i=0;
|
||||
for (i=0; i<numberOfArguments; i++)
|
||||
{
|
||||
//InputParser_GetWord InputParser_GetLowercaseWord
|
||||
InputParser_GetLowercaseWord(ipc,i,whereToStoreItems,512);
|
||||
//fprintf(stderr,"CSV Header element %u => %s\n",i,whereToStoreItems);
|
||||
csv->field[i].strLength = strlen(whereToStoreItems);
|
||||
csv->field[i].str = (char*) malloc(sizeof(char) * (csv->field[i].strLength+2));
|
||||
memcpy(csv->field[i].str,whereToStoreItems,csv->field[i].strLength);
|
||||
csv->field[i].str[csv->field[i].strLength]=0;
|
||||
++csv->numberOfHeaderFields;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Too many CSV header arguments (encountered %u, max %u)..\n",numberOfArguments,MAX_CSV_HEADER_FIELDS);
|
||||
InputParser_Destroy(ipc);
|
||||
if (line!=0)
|
||||
{
|
||||
free(line);
|
||||
line=0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
InputParser_Destroy(ipc);
|
||||
csv->lineNumber = csv->lineNumber +1;
|
||||
if (line!=0)
|
||||
{
|
||||
free(line);
|
||||
line=0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (line!=0)
|
||||
{
|
||||
free(line);
|
||||
line=0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int parseNextCSVFloatLine(struct CSVFileContext * csv,struct CSVFloatFileLine * csvLine)
|
||||
{
|
||||
if (csv==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (csvLine==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
if (csv->lineNumber==0)
|
||||
{
|
||||
if (!parseCSVHeader(csv))
|
||||
{
|
||||
fprintf(stderr,RED "Could not read CSV header on first loop\n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((read = getline(&line, &len, csv->fp)) != -1)
|
||||
{
|
||||
struct InputParserC * ipc = InputParser_Create(8096,4);
|
||||
InputParser_SetDelimeter(ipc,0,',');
|
||||
InputParser_SetDelimeter(ipc,1,0);
|
||||
InputParser_SetDelimeter(ipc,2,10);
|
||||
InputParser_SetDelimeter(ipc,3,13);
|
||||
|
||||
csvLine->lineNumber=csv->lineNumber;
|
||||
csvLine->numberOfFields = InputParser_SeperateWords(ipc,line,1);
|
||||
|
||||
//fprintf(stderr,"Line %u (%s) has %u arguments \n",csvLine->lineNumber,line,csvLine->numberOfFields );
|
||||
|
||||
if ( csvLine->numberOfFields != csv->numberOfHeaderFields )
|
||||
{
|
||||
fprintf(stderr,RED "Number of header fields %u does not correspond with number of body elements %u \n" NORMAL,csv->numberOfHeaderFields,csvLine->numberOfFields);
|
||||
}
|
||||
|
||||
for (int i=0; i<csvLine->numberOfFields; i++)
|
||||
{
|
||||
csvLine->field[i] = InputParser_GetWordFloat(ipc,i);
|
||||
//fprintf(stderr,"%s(%u)=%0.2f ",csv->field[i].str,i,csvLine->field[i]);
|
||||
}
|
||||
|
||||
|
||||
InputParser_Destroy(ipc);
|
||||
|
||||
csv->lineNumber = csv->lineNumber+1;
|
||||
if (line!=0)
|
||||
{
|
||||
free(line);
|
||||
line=0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (line!=0)
|
||||
{
|
||||
free(line);
|
||||
line=0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int parseNextCSVCOCOSkeleton(struct CSVFileContext * csv, struct skeletonSerialized * skel)
|
||||
{
|
||||
if (csv==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (skel==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
if (csv->lineNumber==0)
|
||||
{
|
||||
if (!parseCSVHeader(csv))
|
||||
{
|
||||
fprintf(stderr,RED "Could not read CSV header on first loop\n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Header of skeleton parsed successfully..\n");
|
||||
for (unsigned int i=0; i<csv->numberOfHeaderFields; i++)
|
||||
{
|
||||
fprintf(stderr,"CSV file header element %u => %s \n",i,csv->field[i].str);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if ((read = getline(&line, &len, csv->fp)) != -1)
|
||||
{
|
||||
//CSV files are always stored normalized..
|
||||
skel->width = 1.0;
|
||||
skel->height = 1.0;
|
||||
|
||||
|
||||
struct InputParserC * ipc = InputParser_Create(8096,4);
|
||||
InputParser_SetDelimeter(ipc,0,',');
|
||||
InputParser_SetDelimeter(ipc,1,0);
|
||||
InputParser_SetDelimeter(ipc,2,10);
|
||||
InputParser_SetDelimeter(ipc,3,13);
|
||||
|
||||
skel->skeletonBodyElements = InputParser_SeperateWords(ipc,line,1);
|
||||
|
||||
//fprintf(stderr,"Line %u (%s) has %u arguments \n",csv->lineNumber,line,skel->skeletonBodyElements);
|
||||
|
||||
int typeOfData=0,jointID=0;
|
||||
float value=0.0;
|
||||
|
||||
if ( skel->skeletonBodyElements != csv->numberOfHeaderFields )
|
||||
{
|
||||
fprintf(stderr,"Number of header fields %u does not correspond with number of body elements %u \n",csv->numberOfHeaderFields,skel->skeletonBodyElements);
|
||||
}
|
||||
|
||||
//Copy references to header ..
|
||||
skel->skeletonHeaderElements=csv->numberOfHeaderFields;
|
||||
for (int i=0; i<csv->numberOfHeaderFields; i++)
|
||||
{
|
||||
skel->skeletonHeader[i].strLength = csv->field[i].strLength;
|
||||
skel->skeletonHeader[i].str = csv->field[i].str;
|
||||
}
|
||||
|
||||
for (int i=0; i<skel->skeletonBodyElements; i++)
|
||||
{
|
||||
//fprintf(stderr,"CSV Header element %u => %s\n",i,whereToStoreItems);
|
||||
skel->skeletonBody[i].value = InputParser_GetWordFloat(ipc,i);
|
||||
//fprintf(stderr,"%s(%u)=%0.2f ",csv->field[i].str,i,skel->skeletonBody[i].value);
|
||||
}
|
||||
|
||||
|
||||
InputParser_Destroy(ipc);
|
||||
csv->lineNumber = csv->lineNumber+1;
|
||||
if (line!=0)
|
||||
{
|
||||
free(line);
|
||||
line=0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (line!=0)
|
||||
{
|
||||
free(line);
|
||||
line=0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uniformlyScaleSerializedSkeleton(struct skeletonSerialized * skel,float factor)
|
||||
{
|
||||
if (skel==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i=0; i<skel->skeletonBodyElements; i++)
|
||||
{
|
||||
skel->skeletonBody[i].value *= factor;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int scaleSerializedSkeletonX(struct skeletonSerialized * skel,float factorX)
|
||||
{
|
||||
if (skel==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (skel->skeletonHeaderElements!=skel->skeletonBodyElements)
|
||||
{
|
||||
fprintf(stderr,"scaleSerializedSkeletonX: Inconsistent headers length\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scaledJoints=0;
|
||||
for (int i=0; i<skel->skeletonHeaderElements; i++)
|
||||
{
|
||||
if
|
||||
(
|
||||
( skel->skeletonHeader[i].strLength >4 ) &&
|
||||
( skel->skeletonHeader[i].str!=0 )
|
||||
)
|
||||
{
|
||||
if (
|
||||
(skel->skeletonHeader[i].str[0]=='2') &&
|
||||
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
|
||||
( (skel->skeletonHeader[i].str[2]=='X') || (skel->skeletonHeader[i].str[2]=='x') ) &&
|
||||
(skel->skeletonHeader[i].str[3]=='_')
|
||||
)
|
||||
{
|
||||
skel->skeletonBody[i].value *= factorX;
|
||||
++scaledJoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scaledJoints;
|
||||
}
|
||||
|
||||
|
||||
int scaleSerializedSkeletonY(struct skeletonSerialized * skel,float factorY)
|
||||
{
|
||||
if (skel==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (skel->skeletonHeaderElements!=skel->skeletonBodyElements)
|
||||
{
|
||||
fprintf(stderr,"scaleSerializedSkeletonY: Inconsistent headers length\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scaledJoints=0;
|
||||
for (int i=0; i<skel->skeletonHeaderElements; i++)
|
||||
{
|
||||
if
|
||||
(
|
||||
( skel->skeletonHeader[i].strLength >4 ) &&
|
||||
( skel->skeletonHeader[i].str!=0 )
|
||||
)
|
||||
{
|
||||
if (
|
||||
(skel->skeletonHeader[i].str[0]=='2') &&
|
||||
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
|
||||
( (skel->skeletonHeader[i].str[2]=='Y') || (skel->skeletonHeader[i].str[2]=='y') ) &&
|
||||
(skel->skeletonHeader[i].str[3]=='_')
|
||||
)
|
||||
{
|
||||
skel->skeletonBody[i].value *= factorY;
|
||||
++scaledJoints;
|
||||
}
|
||||
///else { fprintf(stderr,"`%s` does not match\n",skel->skeletonHeader[i].str); }
|
||||
}
|
||||
}
|
||||
|
||||
return scaledJoints;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int scaleSerializedSkeletonFromCenter(struct skeletonSerialized * skel,float factorX,float factorY)
|
||||
{
|
||||
if (skel==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Assuming we have a 2D point cloud with points 0..1,0..1
|
||||
// This is how we model the framebuffer
|
||||
// 0,0 __________________________________________________________________________________ 1,0
|
||||
// | /\ |
|
||||
// | | 0.5 |
|
||||
// | | |
|
||||
// | 0.5 | 0.5 |
|
||||
// | <----------------------------- * -----------------------------> |
|
||||
// | | |
|
||||
// | | |
|
||||
// | | 0.5 |
|
||||
// | \/ |
|
||||
// 0,1------------------------------------------------------------------------------------ 1,1
|
||||
// The * is the center of the image..
|
||||
// We want to scale X,Y points based on factorX and factorY
|
||||
//However the magnitued of the scaling will be linear to the distance from the
|
||||
//Center of the image , Points 0.5 units away from the center will be scaled fully with the factor
|
||||
//Points close to the center will be not scaled at all..
|
||||
if (skel->skeletonHeaderElements!=skel->skeletonBodyElements)
|
||||
{
|
||||
fprintf(stderr,"scaleSerializedSkeletonY: Inconsistent headers length\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
float value,magnitude,maximumFactor,thisFactorY,relativeY,thisFactorX,relativeX;
|
||||
|
||||
int scaledJoints=0;
|
||||
for (int i=0; i<skel->skeletonHeaderElements; i++)
|
||||
{
|
||||
if
|
||||
(
|
||||
( skel->skeletonHeader[i].strLength >4 ) &&
|
||||
( skel->skeletonHeader[i].str!=0 )
|
||||
)
|
||||
{
|
||||
if (
|
||||
(skel->skeletonHeader[i].str[0]=='2') &&
|
||||
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
|
||||
( (skel->skeletonHeader[i].str[2]=='X') || (skel->skeletonHeader[i].str[2]=='x') ) &&
|
||||
(skel->skeletonHeader[i].str[3]=='_')
|
||||
)
|
||||
{
|
||||
if (factorX!=1.0)
|
||||
{
|
||||
value = skel->skeletonBody[i].value;
|
||||
maximumFactor = factorX-1.0;
|
||||
magnitude = (float) fabs(value-0.5)/0.5;
|
||||
thisFactorX = (magnitude * maximumFactor) + 1.0;
|
||||
relativeX = value - 0.5;
|
||||
relativeX *= thisFactorX;
|
||||
skel->skeletonBody[i].value = relativeX + 0.5 ;
|
||||
++scaledJoints;
|
||||
}
|
||||
}
|
||||
else if (
|
||||
(skel->skeletonHeader[i].str[0]=='2') &&
|
||||
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
|
||||
( (skel->skeletonHeader[i].str[2]=='Y') || (skel->skeletonHeader[i].str[2]=='y') ) &&
|
||||
(skel->skeletonHeader[i].str[3]=='_')
|
||||
)
|
||||
{
|
||||
if (factorY!=1.0)
|
||||
{
|
||||
value = skel->skeletonBody[i].value;
|
||||
maximumFactor = factorY-1.0;
|
||||
magnitude = (float) fabs(value-0.5)/0.5;
|
||||
thisFactorY = ( magnitude * maximumFactor ) + 1.0;
|
||||
relativeY = value - 0.5;
|
||||
relativeY *= thisFactorY;
|
||||
skel->skeletonBody[i].value = relativeY + 0.5 ;
|
||||
++scaledJoints;
|
||||
}
|
||||
}
|
||||
} //Valid header
|
||||
} // For each joint
|
||||
|
||||
return scaledJoints;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
# if __GNUC_PREREQ(5,5)
|
||||
// If gcc_version >= RANDOM support
|
||||
#include <random> //For generating random samples based on a normal distribution
|
||||
//This function makes the life of the 3D pose estimator more difficult by adding a configurable level of gaussian noise on the 2D pixels estimated
|
||||
int perturbSerializedSkeletonUsingGaussianNoise(struct skeletonSerialized * skel,float gaussianNoiseInNormalizedPixelsX,float gaussianNoiseInNormalizedPixelsY)
|
||||
{
|
||||
if (skel->skeletonHeaderElements!=skel->skeletonBodyElements)
|
||||
{
|
||||
fprintf(stderr,"perturbSerializedSkeletonUsingGaussianNoise: Inconsistent headers length\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::default_random_engine generator;
|
||||
std::normal_distribution<float> distributionX(0.0,gaussianNoiseInNormalizedPixelsX);
|
||||
std::normal_distribution<float> distributionY(0.0,gaussianNoiseInNormalizedPixelsY);
|
||||
|
||||
|
||||
float value,magnitude,maximumFactor,thisFactorY,relativeY,thisFactorX,relativeX;
|
||||
|
||||
int perturbedCoordinates=0;
|
||||
for (int i=0; i<skel->skeletonHeaderElements; i++)
|
||||
{
|
||||
if
|
||||
(
|
||||
( skel->skeletonHeader[i].strLength >4 ) &&
|
||||
( skel->skeletonHeader[i].str!=0 )
|
||||
)
|
||||
{
|
||||
if (
|
||||
(skel->skeletonHeader[i].str[0]=='2') &&
|
||||
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
|
||||
( (skel->skeletonHeader[i].str[2]=='X') || (skel->skeletonHeader[i].str[2]=='x') ) &&
|
||||
(skel->skeletonHeader[i].str[3]=='_')
|
||||
)
|
||||
{
|
||||
if (gaussianNoiseInNormalizedPixelsX>0.0)
|
||||
{
|
||||
float perturbation = distributionX(generator);
|
||||
skel->skeletonBody[i].value += perturbation;
|
||||
|
||||
++perturbedCoordinates;
|
||||
}
|
||||
}
|
||||
else if (
|
||||
(skel->skeletonHeader[i].str[0]=='2') &&
|
||||
( (skel->skeletonHeader[i].str[1]=='D') || (skel->skeletonHeader[i].str[1]=='d') ) &&
|
||||
( (skel->skeletonHeader[i].str[2]=='Y') || (skel->skeletonHeader[i].str[2]=='y') ) &&
|
||||
(skel->skeletonHeader[i].str[3]=='_')
|
||||
)
|
||||
{
|
||||
if (gaussianNoiseInNormalizedPixelsY>0.0)
|
||||
{
|
||||
float perturbation = distributionY(generator);
|
||||
skel->skeletonBody[i].value += perturbation;
|
||||
|
||||
++perturbedCoordinates;
|
||||
}
|
||||
}
|
||||
} //Valid header
|
||||
} // For each joint
|
||||
|
||||
return perturbedCoordinates;
|
||||
}
|
||||
# else
|
||||
#warning "Your compiler is too old and is missing normal random distributions"
|
||||
int perturbSerializedSkeletonUsingGaussianNoise(struct skeletonSerialized * skel,float gaussianNoiseInNormalizedPixelsX,float gaussianNoiseInNormalizedPixelsY)
|
||||
{
|
||||
fprintf(stderr,RED "\n\n\n\nYour compiler is too old and is missing normal random distributions\n\n\n\n" NORMAL );
|
||||
return 0;
|
||||
}
|
||||
// Else
|
||||
# endif
|
||||
#else
|
||||
int perturbSerializedSkeletonUsingGaussianNoise(struct skeletonSerialized * skel,float gaussianNoiseInNormalizedPixelsX,float gaussianNoiseInNormalizedPixelsY)
|
||||
{
|
||||
fprintf(stderr,RED "\n\n\n\nYour compiler is not GCC old and is missing(?) normal random distributions\n\n\n\n" NORMAL );
|
||||
return 0;
|
||||
}
|
||||
// If not gcc
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
float rand_FloatRange(float a, float b)
|
||||
{
|
||||
return ((b - a) * ((float)rand() / RAND_MAX)) + a;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
std::vector<std::vector<float> > get2DPointsFromSkeleton(struct skeletonSerialized * skel)
|
||||
{
|
||||
fprintf(stderr,"get2DPointsFromSkeleton: ");
|
||||
std::vector<std::vector<float> > finalVector;
|
||||
if (skel==0)
|
||||
{
|
||||
fprintf(stderr,"get2DPointsFromSkeleton: No input\n");
|
||||
return finalVector;
|
||||
}
|
||||
if (skel->skeletonBodyElements!=skel->skeletonHeaderElements)
|
||||
{
|
||||
fprintf(stderr,"get2DPointsFromSkeleton: Mismatch of elements of body/header\n");
|
||||
return finalVector;
|
||||
}
|
||||
|
||||
std::vector<float> points2D;
|
||||
for (int i=0; i<skel->skeletonBodyElements; i++)
|
||||
{
|
||||
if ( strstr(skel->skeletonHeader[i].str,"2DX_")!=0)
|
||||
{
|
||||
points2D.push_back(skel->skeletonBody[i].value);
|
||||
}
|
||||
else if ( strstr(skel->skeletonHeader[i].str,"2DY_")!=0)
|
||||
{
|
||||
points2D.push_back(skel->skeletonBody[i].value);
|
||||
}
|
||||
else if ( strstr(skel->skeletonHeader[i].str,"visible_")!=0)
|
||||
{
|
||||
finalVector.push_back(points2D);
|
||||
points2D.clear();
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr,"survived..\n");
|
||||
return finalVector;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
/** @file csvRead.hpp
|
||||
* @brief To simplify dataset parsing the very simple CSV ( comma seperated value ) format is used by MocapNET2
|
||||
* This module facilitates opening,parsing and performing some trivial processing of CSV input files..
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include "commonSkeleton.hpp"
|
||||
#define MAX_CSV_HEADER_FIELDS 1024
|
||||
|
||||
|
||||
/**
|
||||
* @brief Each CSV file needs a context to be parsed, this contains the file discriptor the current line number, the number of fields in the header as well as header fields
|
||||
*/
|
||||
struct CSVFileContext
|
||||
{
|
||||
FILE * fp;
|
||||
unsigned int lineNumber;
|
||||
unsigned int numberOfHeaderFields;
|
||||
struct headerField field[MAX_CSV_HEADER_FIELDS];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief We may choose to parse a CSV file that only consists of floats, for this specific type there is an optimized CSV context
|
||||
*/
|
||||
struct CSVFloatFileLine
|
||||
{
|
||||
unsigned int lineNumber;
|
||||
unsigned int numberOfFields;
|
||||
float field[MAX_CSV_HEADER_FIELDS];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write a skeleton to a CSV. This is the first call that prepares the header
|
||||
* @param CSV context
|
||||
* @param filename of CSV file
|
||||
* @retval 0=Failure/No lines, Otherwise the number of body lines is returned
|
||||
*/
|
||||
unsigned int getBodyLinesOfCSVFIle(struct CSVFileContext * csv,const char * filename);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is the initial call to open a CSV file, you need to have a preallocated CSVFileContext strcture as well as a filename. Also don't forget to call closeCSVFile after you are done parsing it
|
||||
* @param CSV context
|
||||
* @param filename of CSV file
|
||||
* @retval 0=Failure/1=Success
|
||||
*/
|
||||
int openCSVFile(struct CSVFileContext * csv,const char * filename);
|
||||
|
||||
/**
|
||||
* @brief This call should be executed once after opening a CSV file to parse it's header
|
||||
* @param CSV context
|
||||
* @retval 0=Failure/1=Success
|
||||
*/
|
||||
int parseCSVHeader(struct CSVFileContext * csv);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is the final call to close a CSV file and release its file descriptor after you are done parsing it
|
||||
* @param CSV context
|
||||
* @retval 0=Failure/1=Success
|
||||
*/
|
||||
int closeCSVFile(struct CSVFileContext * csv);
|
||||
|
||||
|
||||
int parseNextCSVFloatLine(struct CSVFileContext * csv,struct CSVFloatFileLine * csvLine);
|
||||
|
||||
|
||||
int parseNextCSVCOCOSkeleton(struct CSVFileContext * csv, struct skeletonSerialized * skel);
|
||||
|
||||
|
||||
|
||||
int uniformlyScaleSerializedSkeleton(struct skeletonSerialized * skel,float factor);
|
||||
|
||||
|
||||
int scaleSerializedSkeletonX(struct skeletonSerialized * skel,float factorX);
|
||||
int scaleSerializedSkeletonY(struct skeletonSerialized * skel,float factorY);
|
||||
|
||||
int scaleSerializedSkeletonFromCenter(struct skeletonSerialized * skel,float factorX,float factorY);
|
||||
|
||||
|
||||
int perturbSerializedSkeletonUsingGaussianNoise(struct skeletonSerialized * skel,float gaussianNoiseInNormalizedPixelsX,float gaussianNoiseInNormalizedPixelsY);
|
||||
|
||||
|
||||
|
||||
std::vector<std::vector<float> > get2DPointsFromSkeleton(struct skeletonSerialized * skel);
|
||||
@@ -0,0 +1,251 @@
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../mocapnet2.hpp"
|
||||
#include "../tools.hpp"
|
||||
#include "csvWrite.hpp"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
int writeCSVHeaderFromVector(const char * filename,const char ** labels,unsigned int numberOfLabels)
|
||||
{
|
||||
FILE * fp = fopen(filename,"w");
|
||||
if (fp!=0)
|
||||
{
|
||||
for (int i=0; i<numberOfLabels; i++)
|
||||
{
|
||||
fprintf(fp,"%s",labels[i]);
|
||||
if (i<numberOfLabels-1)
|
||||
{
|
||||
fprintf(fp,",");
|
||||
}
|
||||
}
|
||||
fprintf(fp,"\n");
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
int writeCSVBodyFromVector(const char * filename,std::vector<float> inputValues)
|
||||
{
|
||||
FILE * fp = fopen(filename,"a");
|
||||
if (fp!=0)
|
||||
{
|
||||
if (inputValues.size()==0)
|
||||
{
|
||||
fprintf(stderr,"Failed to read from JSON file..\n");
|
||||
}
|
||||
|
||||
for (int i=0; i<inputValues.size(); i++)
|
||||
{
|
||||
if (i%3==2)
|
||||
{
|
||||
fprintf(fp,"%0.1f",inputValues[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(fp,"%f",inputValues[i]);
|
||||
}
|
||||
|
||||
if (i<inputValues.size()-1)
|
||||
{
|
||||
fprintf(fp,",");
|
||||
}
|
||||
}
|
||||
fprintf(fp,"\n");
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
int writeCSVHeaderFromLabelsAndVectorOfVectors(const char * filename,const char ** labels,unsigned int numberOfLabels,std::vector<std::vector<float> > inputFrames)
|
||||
{
|
||||
int totalWritesNeeded=0;
|
||||
int totalWritesSucceeded=0;
|
||||
|
||||
if ( writeCSVHeaderFromVector(filename,labels,numberOfLabels) )
|
||||
{
|
||||
for (int i=0; i<inputFrames.size(); i++)
|
||||
{
|
||||
++totalWritesNeeded;
|
||||
if ( writeCSVBodyFromVector(filename,inputFrames[i]) )
|
||||
{
|
||||
++totalWritesSucceeded;
|
||||
}
|
||||
}
|
||||
return (totalWritesSucceeded==totalWritesNeeded);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int writeOpenPoseCSVHeaderFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int width,unsigned int height)
|
||||
{
|
||||
FILE * fp = fopen(filename,"w");
|
||||
if (fp!=0)
|
||||
{
|
||||
|
||||
fprintf(fp,"frameNumber,");
|
||||
fprintf(fp,"skeletonID,");
|
||||
fprintf(fp,"totalSkeletons,");
|
||||
|
||||
char lowercaseName[512];
|
||||
|
||||
for (int i=0; i<BODY25_PARTS; i++)
|
||||
{
|
||||
convertStringToLowercase(lowercaseName,512,Body25BodyNames[i]);
|
||||
//----------------------------------
|
||||
fprintf(fp,"2DX_%s,",lowercaseName);
|
||||
fprintf(fp,"2DY_%s,",lowercaseName);
|
||||
fprintf(fp,"visible_%s,",lowercaseName);
|
||||
}
|
||||
|
||||
for (int i=0; i<COCO_HAND_PARTS; i++)
|
||||
{
|
||||
convertStringToLowercase(lowercaseName,512,COCOLeftHandNames[i]);
|
||||
//----------------------------------
|
||||
fprintf(fp,"2DX_%s,",lowercaseName);
|
||||
fprintf(fp,"2DY_%s,",lowercaseName);
|
||||
fprintf(fp,"visible_%s,",lowercaseName);
|
||||
}
|
||||
|
||||
for (int i=0; i<COCO_HAND_PARTS; i++)
|
||||
{
|
||||
convertStringToLowercase(lowercaseName,512,COCORightHandNames[i]);
|
||||
//----------------------------------
|
||||
fprintf(fp,"2DX_%s,",lowercaseName);
|
||||
fprintf(fp,"2DY_%s,",lowercaseName);
|
||||
fprintf(fp,"visible_%s,",lowercaseName);
|
||||
}
|
||||
|
||||
for (int i=0; i<OP_HEAD_PARTS; i++)
|
||||
{
|
||||
convertStringToLowercase(lowercaseName,512,HeadNames[i]);
|
||||
//----------------------------------
|
||||
fprintf(fp,"2DX_%s,",lowercaseName);
|
||||
fprintf(fp,"2DY_%s,",lowercaseName);
|
||||
fprintf(fp,"visible_%s",lowercaseName);
|
||||
if (i<OP_HEAD_PARTS-1)
|
||||
{
|
||||
fprintf(fp,",");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp,"\n");
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int writeOpenPoseCSVBodyFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int respectTrainingAspectRatio,unsigned int width,unsigned int height)
|
||||
{
|
||||
FILE * fp = fopen(filename,"a");
|
||||
if (fp!=0)
|
||||
{
|
||||
fprintf(fp,"%u,",skeleton->observationNumber);
|
||||
fprintf(fp,"%u,",skeleton->userID);
|
||||
fprintf(fp,"%u,",skeleton->totalUsersPresent);
|
||||
|
||||
|
||||
|
||||
|
||||
for (int i=0; i<BODY25_PARTS; i++)
|
||||
{
|
||||
//Normalize targets --------------------------------------------------------------
|
||||
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
&skeleton->body.joint2D[i].x,
|
||||
&skeleton->body.joint2D[i].y,
|
||||
width,
|
||||
height,
|
||||
respectTrainingAspectRatio,
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
);
|
||||
//--------------------------------------------------------------------------------
|
||||
fprintf(fp,"%f,",(float) skeleton->body.joint2D[i].x);
|
||||
fprintf(fp,"%f,",(float) skeleton->body.joint2D[i].y);
|
||||
fprintf(fp,"%u,", ( (skeleton->body.joint2D[i].x!=0) && (skeleton->body.joint2D[i].y!=0) ) );
|
||||
}
|
||||
|
||||
for (int i=0; i<COCO_HAND_PARTS; i++)
|
||||
{
|
||||
//Normalize targets --------------------------------------------------------------
|
||||
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
&skeleton->leftHand.joint2D[i].x,
|
||||
&skeleton->leftHand.joint2D[i].y,
|
||||
width,
|
||||
height,
|
||||
respectTrainingAspectRatio,
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
);
|
||||
//--------------------------------------------------------------------------------
|
||||
fprintf(fp,"%f,",(float) skeleton->leftHand.joint2D[i].x);
|
||||
fprintf(fp,"%f,",(float) skeleton->leftHand.joint2D[i].y);
|
||||
fprintf(fp,"%u,", ( (skeleton->leftHand.joint2D[i].x!=0) && (skeleton->leftHand.joint2D[i].y!=0) ) );
|
||||
}
|
||||
|
||||
for (int i=0; i<COCO_HAND_PARTS; i++)
|
||||
{
|
||||
//Normalize targets --------------------------------------------------------------
|
||||
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
&skeleton->rightHand.joint2D[i].x,
|
||||
&skeleton->rightHand.joint2D[i].y,
|
||||
width,
|
||||
height,
|
||||
respectTrainingAspectRatio,
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
);
|
||||
//--------------------------------------------------------------------------------
|
||||
fprintf(fp,"%f,",(float) skeleton->rightHand.joint2D[i].x);
|
||||
fprintf(fp,"%f,",(float) skeleton->rightHand.joint2D[i].y);
|
||||
fprintf(fp,"%u,", ( (skeleton->rightHand.joint2D[i].x!=0) && (skeleton->rightHand.joint2D[i].y!=0) ) );
|
||||
}
|
||||
|
||||
for (int i=0; i<OP_HEAD_PARTS; i++)
|
||||
{
|
||||
//Normalize targets --------------------------------------------------------------
|
||||
normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
&skeleton->head.joint2D[i].x,
|
||||
&skeleton->head.joint2D[i].y,
|
||||
width,
|
||||
height,
|
||||
respectTrainingAspectRatio,
|
||||
MocapNETTrainingWidth,
|
||||
MocapNETTrainingHeight
|
||||
);
|
||||
//--------------------------------------------------------------------------------
|
||||
fprintf(fp,"%f,",(float) skeleton->head.joint2D[i].x);
|
||||
fprintf(fp,"%f,",(float) skeleton->head.joint2D[i].y);
|
||||
fprintf(fp,"%u", ( (skeleton->head.joint2D[i].x!=0) && (skeleton->head.joint2D[i].y!=0) ) );
|
||||
if (i<OP_HEAD_PARTS-1)
|
||||
{
|
||||
fprintf(fp,",");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp,"\n");
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
/** @file csvWrite.hpp
|
||||
* @brief These are some simple functions to facilitate CSV writing
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
|
||||
#include "commonSkeleton.hpp"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write a skeleton to a CSV. This is the first call that prepares the header
|
||||
* @param Path to output file i.e. "output.bvh"
|
||||
* @param Pointer to Skeleton that we want to save
|
||||
* @param Width of Image where the skeleton was retreieved from
|
||||
* @param Height of Image where the skeleton was retreieved from
|
||||
* @retval 1=Success,0=Failure
|
||||
*/
|
||||
int writeCSVHeaderFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int width,unsigned int height);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write the body of a skeleton to a CSV. Each time this call is repeated an extra line is appended
|
||||
* @param Path to output file i.e. "output.bvh"
|
||||
* @param Pointer to Skeleton that we want to save
|
||||
* @param Width of Image where the skeleton was retreieved from
|
||||
* @param Height of Image where the skeleton was retreieved from
|
||||
* @retval 1=Success,0=Failure
|
||||
*/
|
||||
int writeCSVBodyFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int width,unsigned int height);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write an array of C-Strings
|
||||
* @param Path to output file i.e. "output.bvh"
|
||||
* @param Pointer to array of C-Strings i.e. MocapNETInputUncompressedArrayNames
|
||||
* @param Number of elements of labels array, MOCAPNET_UNCOMPRESSED_JOINT_PARTS*3 in the case of MocapNETInputUncompressedArrayNames
|
||||
* @retval 1=Success,0=Failure
|
||||
*/
|
||||
int writeCSVHeaderFromVector(const char * filename,const char ** labels,unsigned int numberOfLabels);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write the body of a skeleton in the form of std::vectors to a CSV. Each time this call is repeated an extra line is appended
|
||||
* @param Path to output file i.e. "output.bvh"
|
||||
* @param Pointer to Skeleton that we want to save
|
||||
* @param Width of Image where the skeleton was retreieved from
|
||||
* @param Height of Image where the skeleton was retreieved from
|
||||
* @retval 1=Success,0=Failure
|
||||
*/
|
||||
int writeCSVBodyFromVector(const char * filename,std::vector<float> inputValues);
|
||||
|
||||
|
||||
int writeCSVHeaderFromLabelsAndVectorOfVectors(const char * filename,const char ** labels,unsigned int numberOfLabels,std::vector<std::vector<float> > inputFrames);
|
||||
|
||||
|
||||
|
||||
int writeOpenPoseCSVHeaderFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int width,unsigned int height);
|
||||
|
||||
|
||||
int writeOpenPoseCSVBodyFromSkeleton(const char * filename,struct skeletonStructure * skeleton,unsigned int respectTrainingAspectRatio,unsigned int width,unsigned int height);
|
||||
@@ -0,0 +1,612 @@
|
||||
#include "jsonMocapNETHelpers.hpp"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../MocapNETLib2/IO/bvh.hpp"
|
||||
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
int bothZero(float a,float b)
|
||||
{
|
||||
return (a==0.0)&&(b==0.0);
|
||||
}
|
||||
|
||||
int jointIsNotZero(struct skeletonStructure * sk,int jointID)
|
||||
{
|
||||
if ( bothZero(sk->body.joint2D[jointID].x,sk->body.joint2D[jointID].y) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bothJointAreNotZero(struct skeletonStructure * sk,int jointIDA,int jointIDB)
|
||||
{
|
||||
if (
|
||||
( (sk->body.joint2D[jointIDA].x==0.0)&&(sk->body.joint2D[jointIDA].y==0.0) ) ||
|
||||
( (sk->body.joint2D[jointIDB].x==0.0)&&(sk->body.joint2D[jointIDB].y==0.0) )
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void addSkeletonJointFromTwoJoints(
|
||||
struct skeletonStructure * sk,
|
||||
std::vector<float> &result,
|
||||
int jointIDA,
|
||||
int jointIDB
|
||||
)
|
||||
{
|
||||
float x=(float) (sk->body.joint2D[jointIDA].x + sk->body.joint2D[jointIDB].x)/2;
|
||||
float y=(float) (sk->body.joint2D[jointIDA].y + sk->body.joint2D[jointIDB].y)/2;
|
||||
float v=1.0;
|
||||
if (
|
||||
( (sk->body.joint2D[jointIDA].x==0.0)&&(sk->body.joint2D[jointIDA].y==0.0) ) ||
|
||||
( (sk->body.joint2D[jointIDB].x==0.0)&&(sk->body.joint2D[jointIDB].y==0.0) )
|
||||
)
|
||||
{
|
||||
x=0.0;
|
||||
y=0.0;
|
||||
v=0.0;
|
||||
}
|
||||
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
}
|
||||
|
||||
void addSkeletonJoint(
|
||||
struct skeletonStructure * sk,
|
||||
std::vector<float> &result,
|
||||
int jointID
|
||||
)
|
||||
|
||||
{
|
||||
float x=(float) sk->body.joint2D[jointID].x;
|
||||
float y=(float) sk->body.joint2D[jointID].y;
|
||||
float v=1.0;
|
||||
if ( (x==0.0)&&(y==0.0) )
|
||||
{
|
||||
v=0.0;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
}
|
||||
|
||||
void addRightFinger(
|
||||
struct skeletonStructure * sk,
|
||||
std::vector<float> &result,
|
||||
int fingerJointA,
|
||||
int fingerJointB,
|
||||
int fingerJointC
|
||||
)
|
||||
|
||||
{
|
||||
float x=(float) sk->rightHand.joint2D[fingerJointA].x;
|
||||
float y=(float) sk->rightHand.joint2D[fingerJointA].y;
|
||||
float v=1.0;
|
||||
if ( (x==0.0)&&(y==0.0) )
|
||||
{
|
||||
v=0.0;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
//----------------------------------------------
|
||||
x=(float) sk->rightHand.joint2D[fingerJointB].x;
|
||||
y=(float) sk->rightHand.joint2D[fingerJointB].y;
|
||||
v=1.0;
|
||||
if ( (x==0.0)&&(y==0.0) )
|
||||
{
|
||||
v=0.0;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
//----------------------------------------------
|
||||
x=(float) sk->rightHand.joint2D[fingerJointC].x;
|
||||
y=(float) sk->rightHand.joint2D[fingerJointC].y;
|
||||
v=1.0;
|
||||
if ( (x==0.0)&&(y==0.0) )
|
||||
{
|
||||
v=0.0;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void addLeftFinger(
|
||||
struct skeletonStructure * sk,
|
||||
std::vector<float> &result,
|
||||
int fingerJointA,
|
||||
int fingerJointB,
|
||||
int fingerJointC
|
||||
)
|
||||
|
||||
{
|
||||
float x=(float) sk->leftHand.joint2D[fingerJointA].x;
|
||||
float y=(float) sk->leftHand.joint2D[fingerJointA].y;
|
||||
float v=1.0;
|
||||
if ( (x==0.0)&&(y==0.0) )
|
||||
{
|
||||
v=0.0;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
//----------------------------------------------
|
||||
x=(float) sk->leftHand.joint2D[fingerJointB].x;
|
||||
y=(float) sk->leftHand.joint2D[fingerJointB].y;
|
||||
v=1.0;
|
||||
if ( (x==0.0)&&(y==0.0) )
|
||||
{
|
||||
v=0.0;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
//----------------------------------------------
|
||||
x=(float) sk->leftHand.joint2D[fingerJointC].x;
|
||||
y=(float) sk->leftHand.joint2D[fingerJointC].y;
|
||||
v=1.0;
|
||||
if ( (x==0.0)&&(y==0.0) )
|
||||
{
|
||||
v=0.0;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<float> normalizeWhileAlsoMatchingTrainingAspectRatio(
|
||||
std::vector<float> input,
|
||||
unsigned int currentWidth,
|
||||
unsigned int currentHeight,
|
||||
unsigned int trainingWidth,
|
||||
unsigned int trainingHeight
|
||||
)
|
||||
{
|
||||
//fprintf(stderr,YELLOW "normalizeWhileAlsoMatchingTrainingAspectRatio\n" NORMAL);
|
||||
unsigned int addX=0,addY=0;
|
||||
unsigned int targetWidth=currentWidth,targetHeight=currentHeight;
|
||||
float currentAspectRatio = (float) currentWidth/currentHeight;
|
||||
float trainingAspectRatio = (float) trainingWidth/trainingHeight;
|
||||
|
||||
//fprintf(stderr,"Will try to correct aspect ratio from %0.2f(%ux%u) to %0.2f (%ux%u)\n",currentAspectRatio,currentWidth,currentHeight,trainingAspectRatio,trainingWidth,trainingHeight);
|
||||
|
||||
std::vector<float> fixedAspectRatio=input;
|
||||
|
||||
if (currentHeight<currentWidth)
|
||||
{
|
||||
targetHeight=(unsigned int) currentWidth/trainingAspectRatio;
|
||||
if (targetHeight>=currentHeight)
|
||||
{
|
||||
addY=(unsigned int) (targetHeight-currentHeight)/2;
|
||||
} else
|
||||
{
|
||||
//Turns out we will have to enlarge X instead of englarging Y
|
||||
addY=0;
|
||||
targetHeight=currentHeight;
|
||||
targetWidth=(unsigned int)currentHeight*trainingAspectRatio;
|
||||
addX=(unsigned int) (targetWidth-currentWidth)/2;
|
||||
}
|
||||
} else
|
||||
if (currentWidth<=currentHeight)
|
||||
{
|
||||
targetWidth=(unsigned int)currentHeight*trainingAspectRatio;
|
||||
if (targetWidth>=currentWidth)
|
||||
{
|
||||
addX=(unsigned int) (targetWidth-currentWidth)/2;
|
||||
} else
|
||||
{
|
||||
//Turns out we will have to enlarge Y instead of englarging X
|
||||
addX=0;
|
||||
targetWidth=currentWidth;
|
||||
targetHeight=(unsigned int) currentWidth/trainingAspectRatio;
|
||||
addY=(unsigned int) (targetHeight-currentHeight)/2;
|
||||
}
|
||||
}
|
||||
|
||||
//fprintf(stderr,"Target resolution is %ux%u to Y\n",targetWidth,targetHeight);
|
||||
//fprintf(stderr,"Will add %u to X and %u to Y to achieve it\n",addX,addY);
|
||||
|
||||
float targetAspectRatio=(float) targetWidth/targetHeight;
|
||||
if ((unsigned int) targetAspectRatio/100!= (unsigned int) trainingAspectRatio/100)
|
||||
{
|
||||
fprintf(stderr,RED "Failed to perfectly match training aspect ratio (%0.5f), managed to reach (%0.5f)\n" NORMAL,trainingAspectRatio,targetAspectRatio);
|
||||
}
|
||||
|
||||
for (int i=0; i<input.size()/3; i++)
|
||||
{
|
||||
if (input[i*3+2]!=0)
|
||||
{
|
||||
//Only Fix Aspect Ratio on visible points to preserve 0,0,0 that are
|
||||
//important to the neural network..
|
||||
fixedAspectRatio[i*3+0]=(float) (input[i*3+0]+addX)/targetWidth;
|
||||
fixedAspectRatio[i*3+1]=(float) (input[i*3+1]+addY)/targetHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return fixedAspectRatio;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::vector<float> flattenskeletonStructureToVector(struct skeletonStructure * sk,unsigned int width ,unsigned int height)
|
||||
{
|
||||
//Extra joints..
|
||||
float hipX=0.0;
|
||||
float hipY=0.0;
|
||||
int hipExists=0;
|
||||
|
||||
float x,y,v;
|
||||
std::vector<float> result;
|
||||
// MOCAPNET_UNCOMPRESSED_JOINT_HIP=0, //0
|
||||
x=(float) (sk->body.joint2D[BODY25_LHip].x + sk->body.joint2D[BODY25_RHip].x)/2;
|
||||
y=(float) (sk->body.joint2D[BODY25_LHip].y + sk->body.joint2D[BODY25_RHip].y)/2;
|
||||
if (
|
||||
( (sk->body.joint2D[BODY25_LHip].x==0.0)&&(sk->body.joint2D[BODY25_LHip].y==0.0) ) ||
|
||||
( (sk->body.joint2D[BODY25_RHip].x==0.0)&&(sk->body.joint2D[BODY25_RHip].y==0.0) )
|
||||
)
|
||||
{
|
||||
v=0.0;
|
||||
x=0.0;
|
||||
y=0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
v=1.0;
|
||||
hipX=x;
|
||||
hipY=y;
|
||||
hipExists=1;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
//------------------------------------
|
||||
|
||||
|
||||
float chestX= (float) (sk->body.joint2D[BODY25_Neck].x + hipX)/2;
|
||||
float chestY= (float) (sk->body.joint2D[BODY25_Neck].y + hipY)/2;
|
||||
int chestNotVisible= (( (sk->body.joint2D[BODY25_Neck].x==0.0)&&(sk->body.joint2D[BODY25_Neck].y==0.0) ) || ( (hipX==0.0)&&(hipY==0.0) ) );
|
||||
|
||||
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ABDOMEN, //1
|
||||
x=(float) (sk->body.joint2D[BODY25_Neck].x + chestX)/2;
|
||||
y=(float) (sk->body.joint2D[BODY25_Neck].y + chestY)/2;
|
||||
if ( (chestNotVisible) || ((sk->body.joint2D[BODY25_Neck].x==0.0)&&(sk->body.joint2D[BODY25_Neck].y==0.0)) )
|
||||
{
|
||||
v=0.0;
|
||||
x=0.0;
|
||||
y=0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
v=1.0;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
//TODO:
|
||||
//------------------------------------
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_CHEST, //2
|
||||
x=chestX;
|
||||
y=chestY;
|
||||
if ( chestNotVisible )
|
||||
{
|
||||
v=0.0;
|
||||
x=0.0;
|
||||
y=0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
v=1.0;
|
||||
}
|
||||
result.push_back(x);
|
||||
result.push_back(y);
|
||||
result.push_back(v);
|
||||
//------------------------------------
|
||||
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_NECK, //3
|
||||
addSkeletonJoint(sk,result,COCO_Neck);
|
||||
//------------------------------------
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_HEAD, //4
|
||||
//
|
||||
int guessNose=1;
|
||||
if (guessNose==1)
|
||||
{
|
||||
//TODO : The nose should only be visible in front
|
||||
//Eyes the same.. I should also add this to the BVH -> 3D CSV conversions..!
|
||||
|
||||
if (bothJointAreNotZero(sk,BODY25_LEar,BODY25_REar))
|
||||
{
|
||||
addSkeletonJointFromTwoJoints(sk,result,BODY25_LEar,BODY25_REar);
|
||||
}
|
||||
else
|
||||
if (bothJointAreNotZero(sk,BODY25_LEye,BODY25_REye))
|
||||
{
|
||||
addSkeletonJointFromTwoJoints(sk,result,BODY25_LEye,BODY25_REye);
|
||||
} else
|
||||
{
|
||||
addSkeletonJoint(sk,result,BODY25_Nose);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addSkeletonJoint(sk,result,BODY25_Nose);
|
||||
}
|
||||
//------------------------------------
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LEFTEYE, //5
|
||||
addSkeletonJoint(sk,result,BODY25_LEye);
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LEFTEYE, //6
|
||||
addSkeletonJoint(sk,result,BODY25_LEye);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RIGHTEYE, //7
|
||||
addSkeletonJoint(sk,result,BODY25_REye);
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RIGHTEYE, //8
|
||||
addSkeletonJoint(sk,result,BODY25_REye);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RCOLLAR, //9
|
||||
addSkeletonJointFromTwoJoints(sk,result,BODY25_Neck,BODY25_RShoulder);
|
||||
//------------------------------
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RSHOULDER, //10
|
||||
addSkeletonJoint(sk,result,BODY25_RShoulder);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RELBOW, //11
|
||||
addSkeletonJoint(sk,result,BODY25_RElbow);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RHAND, //12
|
||||
addSkeletonJoint(sk,result,BODY25_RWrist);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RTHUMB1, //13
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RTHUMB2, //14
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RTHUMB2, //15
|
||||
addRightFinger(sk,result,COCO_Hand_Thumb_1,COCO_Hand_Thumb_2,COCO_Hand_Thumb_3);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RINDEX1, //16
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RINDEX2, //17
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RINDEX2, //18
|
||||
addRightFinger(sk,result,COCO_Hand_Index_1,COCO_Hand_Index_2,COCO_Hand_Index_3);
|
||||
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RMID1, //19
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RMID2, //20
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RMID2, //21
|
||||
addRightFinger(sk,result,COCO_Hand_Middle_1,COCO_Hand_Middle_2,COCO_Hand_Middle_3);
|
||||
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RRING1, //22
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RRING2, //23
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RRING2, //24
|
||||
addRightFinger(sk,result,COCO_Hand_Ring_1,COCO_Hand_Ring_2,COCO_Hand_Ring_3);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RPINKY1, //25
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RPINKY2, //26
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RPINKY2, //27
|
||||
addRightFinger(sk,result,COCO_Hand_Pinky_1,COCO_Hand_Pinky_2,COCO_Hand_Pinky_3);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LCOLLAR, //28
|
||||
addSkeletonJointFromTwoJoints(sk,result,BODY25_Neck,BODY25_LShoulder);
|
||||
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LSHOULDER, //29
|
||||
addSkeletonJoint(sk,result,BODY25_LShoulder);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LELBOW, //30
|
||||
addSkeletonJoint(sk,result,BODY25_LElbow);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LHAND, //31
|
||||
addSkeletonJoint(sk,result,BODY25_LWrist);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LTHUMB1, //32
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LTHUMB2, //33
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LTHUMB2, //34
|
||||
addLeftFinger(sk,result,COCO_Hand_Thumb_1,COCO_Hand_Thumb_2,COCO_Hand_Thumb_3);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LINDEX1, //35
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LINDEX2, //36
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LINDEX2, //37
|
||||
addLeftFinger(sk,result,COCO_Hand_Index_1,COCO_Hand_Index_2,COCO_Hand_Index_3);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LMID1, //38
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LMID2, //39
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LMID2, //40
|
||||
addLeftFinger(sk,result,COCO_Hand_Middle_1,COCO_Hand_Middle_2,COCO_Hand_Middle_3);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LRING1, //41
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LRING2, //42
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LRING2, //43
|
||||
addLeftFinger(sk,result,COCO_Hand_Ring_1,COCO_Hand_Ring_2,COCO_Hand_Ring_3);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LPINKY1, //44
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LPINKY2, //45
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LPINKY2, //46
|
||||
addLeftFinger(sk,result,COCO_Hand_Pinky_1,COCO_Hand_Pinky_2,COCO_Hand_Pinky_3);
|
||||
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RBUTTOCK, //47
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RHIP, //48
|
||||
addSkeletonJoint(sk,result,BODY25_RHip);
|
||||
addSkeletonJoint(sk,result,BODY25_RHip);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RKNEE, //49
|
||||
addSkeletonJoint(sk,result,BODY25_RKnee);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_RFOOT, //50
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_RFOOT, //51
|
||||
addSkeletonJoint(sk,result,BODY25_RAnkle);
|
||||
addSkeletonJoint(sk,result,BODY25_RAnkle);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LBUTTOCK, //52
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LHIP, //53
|
||||
addSkeletonJoint(sk,result,BODY25_LHip);
|
||||
addSkeletonJoint(sk,result,BODY25_LHip);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LKNEE, //54
|
||||
addSkeletonJoint(sk,result,BODY25_LKnee);
|
||||
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_LFOOT, //55
|
||||
//MOCAPNET_UNCOMPRESSED_JOINT_ES_LFOOT, //56
|
||||
addSkeletonJoint(sk,result,BODY25_LAnkle);
|
||||
addSkeletonJoint(sk,result,BODY25_LAnkle);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Last sanity check..!
|
||||
//-----------------------------------------------------------
|
||||
for (int i=0; i<result.size()/3; i++)
|
||||
{
|
||||
if (
|
||||
( ( result[i*3+0]<=0 )&&( result[i*3+1]<=0 ) ) || //Both x,y are zero
|
||||
( ( result[i*3+0]==0 )||( result[i*3+1]==0 ) ) //Any of x or y are zero to combat a weird bug..
|
||||
)
|
||||
{
|
||||
result[i*3+0]=0;
|
||||
result[i*3+1]=0;
|
||||
result[i*3+2]=0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
if ( (width==1) && (height==1) )
|
||||
{
|
||||
//Input is already normalized, nothing to do here..
|
||||
//fprintf(stderr,"Input is already normalized\n");
|
||||
} else
|
||||
{
|
||||
//This is the training configuration of MocapNET
|
||||
unsigned int trainingWidth=1920;
|
||||
unsigned int trainingHeight=1080;
|
||||
|
||||
float currentAspectRatio = (float) width/height;
|
||||
float trainingAspectRatio = (float) trainingWidth/trainingHeight;
|
||||
|
||||
if (currentAspectRatio!=trainingAspectRatio)
|
||||
{
|
||||
//fprintf(stderr,"Normalizing WITH aspect ratio change\n");
|
||||
//MocapNET has been trained on 1920x1080 frames, so all the received coordinates are normalized in the
|
||||
//0..1 range based on that. This means that the NN learns the X and Y variations. If a joint lies at pixel 500,500
|
||||
//it will be represented as 500/1920 , 500/1080.
|
||||
//Now if a user uses another configuration, let's say a vertical (portrait) feed where the resolution is 1080x1920
|
||||
//the 2D points will get normalized at 500/1080 , 500/1920 and the resulting 2D joint cloud won't work as well
|
||||
//This is why it is better to change the aspect ratio while normalizing
|
||||
result = normalizeWhileAlsoMatchingTrainingAspectRatio(result,width,height,trainingWidth,trainingHeight);
|
||||
} else
|
||||
{
|
||||
//If we don't want to correct aspect ratio just go on with normalization..
|
||||
//fprintf(stderr,"Normalizing without aspect ratio change\n");
|
||||
for (int i=0; i<result.size()/3; i++)
|
||||
{
|
||||
result[i*3+0]=(float) result[i*3+0]/width;
|
||||
result[i*3+1]=(float) result[i*3+1]/height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (result.size()==0)
|
||||
{
|
||||
fprintf(stderr,"Could not convert skeleton to vector..\n");
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ./GroundTruthDumper --from dataset/gestures/comeleft.bvh --360 1 --bvh test.bvh
|
||||
// ./convertBVHToCSV --from test.bvh -o test.csv
|
||||
// ./MocapNETJSON --from test.csv --visualize
|
||||
|
||||
|
||||
|
||||
int convertBVHFrameToSkeletonCOCO(struct skeletonStructure * sk,std::vector<float> bvhFrame,unsigned int width ,unsigned int height)
|
||||
{
|
||||
std::vector<std::vector<float> > bvhFrame2DOutput = convertBVHFrameTo2DPoints(bvhFrame); //,width,height
|
||||
|
||||
const int INVALID_JOINT=6666;
|
||||
fprintf(stderr,"Converting BVH frame to a SkeletonCOCO assuming a %ux%u frame\n",width,height);
|
||||
for (unsigned int jointID=0; jointID<bvhFrame2DOutput.size(); jointID++)
|
||||
{
|
||||
fprintf(stderr,"Joint %u - %s - %0.2f,%0.2f \n",jointID,getBVHJointName(jointID),bvhFrame2DOutput[jointID][0],bvhFrame2DOutput[jointID][1]);
|
||||
|
||||
const char * jointName = getBVHJointName(jointID);
|
||||
unsigned int jointTargetID = INVALID_JOINT;
|
||||
if (strcmp("hip",jointName)==0) { jointTargetID=BODY25_MidHip; } else
|
||||
if (strcmp("neck",jointName)==0) { jointTargetID=BODY25_Neck; } else
|
||||
if (strcmp("head",jointName)==0) { jointTargetID=BODY25_Nose; } else
|
||||
if (strcmp("rShldr",jointName)==0) { jointTargetID=BODY25_RShoulder; } else
|
||||
if (strcmp("rForeArm",jointName)==0) { jointTargetID=BODY25_RElbow; } else
|
||||
if (strcmp("rHand",jointName)==0) { jointTargetID=BODY25_RWrist; } else
|
||||
if (strcmp("lShldr",jointName)==0) { jointTargetID=BODY25_LShoulder; } else
|
||||
if (strcmp("lForeArm",jointName)==0) { jointTargetID=BODY25_LElbow; } else
|
||||
if (strcmp("lHand",jointName)==0) { jointTargetID=BODY25_LWrist; } else
|
||||
if (strcmp("rThigh",jointName)==0) { jointTargetID=BODY25_RHip; } else
|
||||
if (strcmp("rShin",jointName)==0) { jointTargetID=BODY25_RKnee; } else
|
||||
if (strcmp("rFoot",jointName)==0) { jointTargetID=BODY25_RAnkle; } else
|
||||
if (strcmp("lThigh",jointName)==0) { jointTargetID=BODY25_LHip; } else
|
||||
if (strcmp("lShin",jointName)==0) { jointTargetID=BODY25_LKnee; } else
|
||||
if (strcmp("lFoot",jointName)==0) { jointTargetID=BODY25_LAnkle; } else
|
||||
if (strcmp("rightEye",jointName)==0) { jointTargetID=BODY25_REye; } else
|
||||
if (strcmp("leftEye",jointName)==0) { jointTargetID=BODY25_LEye; }
|
||||
|
||||
if (jointTargetID!=INVALID_JOINT)
|
||||
{
|
||||
sk->body.joint2D[jointTargetID].x=(float) bvhFrame2DOutput[jointID][0];
|
||||
sk->body.joint2D[jointTargetID].y=(float) bvhFrame2DOutput[jointID][1];
|
||||
fprintf(stderr,"-> %0.2f,%0.2f \n",sk->body.joint2D[jointTargetID].x,sk->body.joint2D[jointTargetID].y);
|
||||
}
|
||||
/*
|
||||
, //,
|
||||
, //,
|
||||
BODY25_Nose, //,
|
||||
BODY25_Nose, //,
|
||||
BODY25_REye, //BODY25_REar,
|
||||
BODY25_LEye, //BODY25_LEar,
|
||||
BODY25_LHeel, //BODY25_LBigToe,
|
||||
BODY25_LBigToe, //BODY25_LSmallToe,
|
||||
BODY25_LAnkle, //BODY25_LHeel,
|
||||
BODY25_RHeel, //BODY25_RBigToe,
|
||||
BODY25_RBigToe, //BODY25_RSmallToe,
|
||||
BODY25_RAnkle, // BODY25_RHeel,
|
||||
BODY25_Bkg //BODY25_Bkg
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
/** @file jsonMocapNETHelpers.hpp
|
||||
* @brief This file contains helpers to facilitate conversion between different skeleton formats.
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
#include "jsonRead.hpp"
|
||||
#include <vector>
|
||||
|
||||
|
||||
void addSkeletonJointFromTwoJoints(
|
||||
struct skeletonStructure * sk,
|
||||
std::vector<float> &result,
|
||||
int jointIDA,
|
||||
int jointIDB
|
||||
);
|
||||
|
||||
|
||||
void addSkeletonJoint(
|
||||
struct skeletonStructure * sk,
|
||||
std::vector<float> &result,
|
||||
int jointID
|
||||
);
|
||||
|
||||
void addRightFinger(
|
||||
struct skeletonStructure * sk,
|
||||
std::vector<float> &result,
|
||||
int fingerJointA,
|
||||
int fingerJointB,
|
||||
int fingerJointC
|
||||
);
|
||||
|
||||
|
||||
|
||||
void addLeftFinger(
|
||||
struct skeletonStructure * sk,
|
||||
std::vector<float> &result,
|
||||
int fingerJointA,
|
||||
int fingerJointB,
|
||||
int fingerJointC
|
||||
);
|
||||
|
||||
std::vector<float> flattenskeletonCOCOToVector(struct skeletonStructure * sk,unsigned int width ,unsigned int height);
|
||||
|
||||
|
||||
|
||||
int convertBVHFrameToSkeletonCOCO(struct skeletonStructure * sk,std::vector<float> bvhFrame,unsigned int width ,unsigned int height);
|
||||
@@ -0,0 +1,262 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
#include "jsonRead.hpp"
|
||||
#include "../../../../dependencies/InputParser/InputParser_C.h"
|
||||
|
||||
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
float checkSkeletonDistance(struct skeletonStructure * PreviousSkelA,struct skeletonStructure * skelB)
|
||||
{
|
||||
float score=0.0f,xSq=0.0f,ySq=0.0f;
|
||||
for (int i=0; i<COCO_PARTS; i++)
|
||||
{
|
||||
if (
|
||||
(skelB->body.joint2D[i].x==0) &&
|
||||
(skelB->body.joint2D[i].y==0)
|
||||
)
|
||||
{
|
||||
score+=1000;// Penalize holes..
|
||||
}
|
||||
else
|
||||
{
|
||||
xSq = PreviousSkelA->body.joint2D[i].x - skelB->body.joint2D[i].x ;
|
||||
xSq = xSq * xSq;
|
||||
ySq = PreviousSkelA->body.joint2D[i].y - skelB->body.joint2D[i].y;
|
||||
ySq = ySq * ySq;
|
||||
|
||||
score+=sqrt(xSq+ySq);
|
||||
}
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
int parseJsonCOCOSkeleton(const char * filename , struct skeletonStructure * skel,float acceptableThreshold,unsigned int frameID)
|
||||
{
|
||||
//memset(skel,0,sizeof(struct skeletonStructure));
|
||||
|
||||
ssize_t read;
|
||||
|
||||
FILE * fp = fopen(filename,"r");
|
||||
if (fp!=0)
|
||||
{
|
||||
fprintf(stderr,"Parsing 2D skeleton from %s \n",filename);
|
||||
struct InputParserC * ipc = InputParser_Create(2048,3);
|
||||
InputParser_SetDelimeter(ipc,0,',');
|
||||
InputParser_SetDelimeter(ipc,1,',');
|
||||
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
/*
|
||||
{"version":1.2,"people":[{"pose_keypoints_2d":[1051.33,389.167,0.90388,1054.25,474.35,0.834839,995.279,477.271,0.840843,977.646,592.078,0.843254,974.836,692.082,0.925783,1119.04,465.536,0.857748,1148.35,574.318,0.82055,1163.13,671.663,0.926104,1065.89,668.604,0.768351,1021.83,668.697,0.789775,998.248,833.448,0.891052,954.023,974.726,0.895817,1104.23,668.623,0.725152,1092.4,833.417,0.892817,1068.87,954.203,0.908514,1042.39,380.222,0.879022,1069.03,380.207,0.905886,1021.77,388.906,0.874647,1092.43,388.924,0.880871,1095.43,1001.27,0.875549,1110.14,995.311,0.873654,1048.35,968.843,0.832852,954.222,1024.87,0.826879,933.585,1021.78,0.818463,951.109,980.601,0.70936],"face_keypoints_2d":[1021.85,379.364,0.312111,1022.56,385.04,0.388846,1022.92,394.265,0.400321,1025.04,404.553,0.559545,1027.88,413.423,0.583821,1031.79,421.938,0.61052,1037.46,429.389,0.609643,1044.2,434.001,0.630441,1051.3,435.775,0.729202,1059.81,435.065,0.657737,1067.97,430.098,0.685271,1074.36,423.003,0.685615,1078.97,415.197,0.731754,1081.81,406.327,0.712712,1082.17,397.103,0.697536,1082.88,388.233,0.6253,1083.94,380.073,0.518587,1022.56,373.332,0.47997,1027.88,370.494,0.637251,1033.91,369.784,0.717338,1041.72,370.139,0.853094,1047.75,372.977,0.90591,1056.27,373.332,0.889469,1062.3,370.494,0.892274,1068.33,370.494,0.831293,1074.36,371.558,0.73095,1078.97,374.751,0.598676,1051.65,380.073,0.765338,1050.94,386.459,0.77752,1050.94,392.491,0.767245,1050.94,398.167,0.696292,1044.56,401.006,0.712432,1047.75,401.715,0.848516,1050.94,403.134,0.929941,1054.85,402.07,0.957662,1058.75,401.36,0.981191,1030.01,378.299,0.420897,1033.91,378.654,0.380504,1037.11,378.654,0.393703,1039.95,379.009,0.464231,1036.75,379.009,0.458442,1033.56,379.009,0.404015,1062.3,381.847,0.749875,1065.49,381.492,0.641693,1069.39,381.137,0.495781,1072.94,381.492,0.501538,1069.75,381.847,0.518428,1065.49,382.202,0.611457,1038.53,408.456,0.72183,1042.78,407.747,0.864191,1048.11,407.392,0.85783,1051.3,408.456,0.80366,1054.85,407.392,0.833569,1060.17,408.456,0.880244,1066.2,410.23,0.902783,1061.94,417.326,0.928561,1056.27,420.519,0.899355,1051.3,420.874,0.923864,1048.11,420.519,0.927453,1042.07,418.035,0.798128,1039.95,409.875,0.841352,1048.11,410.23,0.881547,1051.65,410.23,0.85485,1055.2,410.23,0.805752,1064.43,410.94,0.870964,1055.91,415.907,0.938425,1051.65,416.262,0.891374,1048.11,416.262,0.926013,1034.98,378.654,0.312223,1067.62,381.492,0.513061],"hand_left_keypoints_2d":[1165.94,680.642,0.466609,1156.44,688.082,0.629248,1153.13,701.72,0.761934,1153.13,715.359,0.819062,1151.89,726.518,0.775558,1168.84,711.64,0.671397,1168.84,728.172,0.799059,1163.88,737.264,0.725134,1160.16,742.224,0.736829,1172.97,711.64,0.702249,1171.73,728.172,0.808444,1166.77,738.091,0.642235,1161.4,742.224,0.604293,1173.38,710.813,0.666696,1172.97,724.865,0.61383,1166.77,732.718,0.536511,1163.88,740.157,0.497097,1172.56,708.747,0.597281,1172.14,721.559,0.59746,1167.18,727.345,0.381854,1163.88,729.411,0.33763],"hand_right_keypoints_2d":[976.039,702.5,0.411615,985.84,702.926,0.655772,996.066,713.152,0.692949,1002.03,726.362,0.772721,1009.7,733.605,0.864994,984.561,730.197,0.731554,988.822,745.536,0.812263,990.953,756.615,0.808444,991.805,765.137,0.836125,979.022,737.014,0.686607,982.005,749.798,0.65217,981.579,760.876,0.754628,979.448,767.694,0.727902,976.039,738.719,0.634819,977.317,749.798,0.69985,976.465,758.32,0.664762,975.187,765.137,0.690298,975.187,739.571,0.592209,975.187,748.093,0.492786,975.613,754.059,0.522497,974.761,760.45,0.43477],"pose_keypoints_3d":[],"face_keypoints_3d":[],"hand_left_keypoints_3d":[],"hand_right_keypoints_3d":[]}]}
|
||||
*/
|
||||
while ((read = getline(&line, &len, fp)) != -1)
|
||||
{
|
||||
skel->observationNumber=frameID;
|
||||
|
||||
//We should have the whole output.. since it is one line
|
||||
char * poseStart=0;
|
||||
char * poseEnd=0;
|
||||
//-----------------------------------------------
|
||||
poseStart=strstr(line,"\"pose_keypoints_2d\":[");
|
||||
if(poseStart!=0)
|
||||
{
|
||||
poseStart=strstr(poseStart,"[")+1;
|
||||
poseEnd=strstr(poseStart,"]");
|
||||
}
|
||||
//-----------------------------------------------
|
||||
char * handLeftStart=0;
|
||||
char * handLeftEnd=0;
|
||||
handLeftStart=strstr(line,"\"hand_left_keypoints_2d\":[");
|
||||
if (handLeftStart!=0)
|
||||
{
|
||||
handLeftStart=strstr(handLeftStart,"[")+1;
|
||||
handLeftEnd=strstr(handLeftStart,"]");
|
||||
}
|
||||
//-----------------------------------------------
|
||||
char * handRightStart=0;
|
||||
char * handRightEnd=0;
|
||||
handRightStart=strstr(line,"\"hand_right_keypoints_2d\":[");
|
||||
if (handRightStart!=0)
|
||||
{
|
||||
handRightStart=strstr(handRightStart,"[")+1;
|
||||
handRightEnd=strstr(handRightStart,"]");
|
||||
}
|
||||
//-----------------------------------------------
|
||||
char * headStart=0;
|
||||
char * headEnd=0;
|
||||
headStart=strstr(line,"\"face_keypoints_2d\":[");
|
||||
if (headStart!=0)
|
||||
{
|
||||
headStart=strstr(headStart,"[")+1;
|
||||
headEnd=strstr(headStart,"]");
|
||||
}
|
||||
//-----------------------------------------------
|
||||
|
||||
//Null Terminate strings..
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
if (poseEnd!=0) { *poseEnd=0; }
|
||||
if (handLeftEnd!=0) { *handLeftEnd=0; }
|
||||
if (handRightEnd!=0) { *handRightEnd=0; }
|
||||
if (headEnd!=0) { *headEnd=0; }
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//fprintf(stderr,"RHand : %s\n",handLeftStart);
|
||||
//fprintf(stderr,"LHand : %s\n",handRightStart);
|
||||
//fprintf(stderr,"Pose : %s\n",poseStart);
|
||||
//fprintf(stderr,"Head : %s\n",headStart);
|
||||
|
||||
int numberOfJoints;
|
||||
float value;
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
if (poseStart!=0)
|
||||
{
|
||||
numberOfJoints = InputParser_SeperateWords(ipc,poseStart,1)/3;
|
||||
if (numberOfJoints>=BODY25_PARTS)
|
||||
{
|
||||
fprintf(stderr,RED "The number of joints found in JSON file (%u) is more than our BODY25 internal structure (%u)\n" NORMAL,numberOfJoints,BODY25_PARTS);
|
||||
} else
|
||||
{
|
||||
if (numberOfJoints>0) { skel->body.isPopulated=1; }
|
||||
for (int poseNum=0; poseNum<numberOfJoints; poseNum++)
|
||||
{
|
||||
skel->body.joint2D[poseNum].x = InputParser_GetWordFloat(ipc,poseNum*3+0);
|
||||
//fprintf(stderr,"Pose%u x ( %u ) = %0.2f\n",poseNum,poseNum*3+0, skel->joint2D[poseNum].x );
|
||||
|
||||
skel->body.joint2D[poseNum].y = InputParser_GetWordFloat(ipc,poseNum*3+1);
|
||||
//fprintf(stderr,"Pose%u y ( %u ) = %0.2f\n",poseNum,poseNum*3+1,skel->joint2D[poseNum].y);
|
||||
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+2);
|
||||
if (value>1.0)
|
||||
{
|
||||
fprintf(stderr,"Warning : Too large value for accuracy\n");
|
||||
}
|
||||
skel->body.jointAccuracy[poseNum] = value;
|
||||
skel->body.active[poseNum] = (value>acceptableThreshold);
|
||||
//fprintf(stderr,"Pose%u A ( %u ) = %0.2f\n",poseNum,poseNum*3+2,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Left Hand Parser
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
if (handLeftStart!=0)
|
||||
{
|
||||
numberOfJoints = InputParser_SeperateWords(ipc,handLeftStart,1)/3;
|
||||
if (numberOfJoints>COCO_HAND_PARTS)
|
||||
{
|
||||
fprintf(stderr,RED "The number of left hand joints found in JSON file (%u) is more than our internal structure (%u)\n" NORMAL,numberOfJoints,COCO_HAND_PARTS);
|
||||
} else
|
||||
{
|
||||
skel->leftHand.isRight=0;
|
||||
skel->leftHand.isLeft=1;
|
||||
if (numberOfJoints>0) { skel->leftHand.isPopulated=1; }
|
||||
for (int poseNum=0; poseNum<numberOfJoints; poseNum++)
|
||||
{
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+0);
|
||||
skel->leftHand.joint2D[poseNum].x = value;
|
||||
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+1);
|
||||
skel->leftHand.joint2D[poseNum].y = value;
|
||||
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+2);
|
||||
skel->leftHand.jointAccuracy[poseNum] = value;
|
||||
skel->leftHand.active[poseNum] = (value>acceptableThreshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Right Hand Parser
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
if (handRightStart!=0)
|
||||
{
|
||||
numberOfJoints = InputParser_SeperateWords(ipc,handRightStart,1)/3;
|
||||
if (numberOfJoints>COCO_HAND_PARTS)
|
||||
{
|
||||
fprintf(stderr,RED "The number of right hand joints found in JSON file (%u) is more than our internal structure (%u)\n" NORMAL,numberOfJoints,COCO_HAND_PARTS);
|
||||
} else
|
||||
{
|
||||
skel->rightHand.isRight=1;
|
||||
skel->rightHand.isLeft=0;
|
||||
if (numberOfJoints>0) { skel->rightHand.isPopulated=1; }
|
||||
for (int poseNum=0; poseNum<numberOfJoints; poseNum++)
|
||||
{
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+0);
|
||||
skel->rightHand.joint2D[poseNum].x = value;
|
||||
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+1);
|
||||
skel->rightHand.joint2D[poseNum].y = value;
|
||||
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+2);
|
||||
skel->rightHand.jointAccuracy[poseNum] = value;
|
||||
skel->rightHand.active[poseNum] = (value>acceptableThreshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Head Parser
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
if (headStart!=0)
|
||||
{
|
||||
numberOfJoints = InputParser_SeperateWords(ipc,headStart,1)/3;
|
||||
if (numberOfJoints>OP_HEAD_PARTS)
|
||||
{
|
||||
fprintf(stderr,RED "The number of head joints found in JSON file (%u) is more than our internal structure (%u)\n" NORMAL,numberOfJoints,OP_HEAD_PARTS);
|
||||
} else
|
||||
{
|
||||
if (numberOfJoints>0) { skel->head.isPopulated=1; }
|
||||
for (int poseNum=0; poseNum<numberOfJoints; poseNum++)
|
||||
{
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+0);
|
||||
skel->head.joint2D[poseNum].x = value;
|
||||
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+1);
|
||||
skel->head.joint2D[poseNum].y = value;
|
||||
|
||||
value = InputParser_GetWordFloat(ipc,poseNum*3+2);
|
||||
skel->head.jointAccuracy[poseNum] = value;
|
||||
skel->head.active[poseNum] = (value>acceptableThreshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
InputParser_Destroy(ipc);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Could not open 2D skeleton file %s \n",filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
fprintf(stderr,"Could not find COCO 2D skeleton in %s \n",filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
/** @file jsonCocoSkeleton.hpp
|
||||
* @brief This is the code needed to parse an OpenPose JSON file to our struct skeletonStructure. This JSON parser barely works for the specific JSON output and so should be treated with caution.
|
||||
* It is not comformant to the JSON spec nor will it work for an arbitrary JSON file..!
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "commonSkeleton.hpp"
|
||||
|
||||
/**
|
||||
* @brief Parse a JSON file and retrieve a skeleton
|
||||
* @param Path to JSON file
|
||||
* @param Pointer to a struct skeletonStructure that will hold the information loaded
|
||||
* @param Threshold to set a joint to active ( 0.4-0.5 is a good value )
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int parseJsonCOCOSkeleton(const char * filename , struct skeletonStructure * skel,float acceptableThreshold,unsigned int frameID);
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "skeletonAbstraction.hpp"
|
||||
|
||||
#include "csvRead.hpp"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
#include <ctype.h> //toupper
|
||||
int strcasecmp_sk(const char * input1,const char * input2)
|
||||
{
|
||||
#if CASE_SENSITIVE_OBJECT_NAMES
|
||||
return strcmp(input1,input2);
|
||||
#endif
|
||||
|
||||
if ( (input1==0) || (input2==0) )
|
||||
{
|
||||
fprintf(stderr,"Error , calling strcasecmp_internal with null parameters \n");
|
||||
return 1;
|
||||
}
|
||||
unsigned int len1 = strlen(input1);
|
||||
unsigned int len2 = strlen(input2);
|
||||
if (len1!=len2)
|
||||
{
|
||||
//mismatched lengths of strings , they can't be equal..!
|
||||
return 1;
|
||||
}
|
||||
|
||||
char A; //<- character buffer for input1
|
||||
char B; //<- character buffer for input2
|
||||
unsigned int i=0;
|
||||
while (i<len1) //len1 and len2 are equal
|
||||
{
|
||||
A = toupper(input1[i]);
|
||||
B = toupper(input2[i]);
|
||||
if (A!=B) { return 1; }
|
||||
++i;
|
||||
}
|
||||
//if we reached this point , there where no reasons
|
||||
//why input1 and input2 could not be equal..
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int areFeetMissing(struct skeletonSerialized * skel)
|
||||
{
|
||||
unsigned int activeLegJoints=0;
|
||||
for (unsigned int i=0; i<skel->skeletonBodyElements; i++)
|
||||
{
|
||||
//If the specific label exists in our skeletonSerialized
|
||||
if (skel->skeletonHeader[i].str!=0)
|
||||
{
|
||||
//The strcmp was flipped, thx to yangjituan for noticing this https://github.com/FORTH-ModelBasedTracker/MocapNET/issues/57
|
||||
//This is a pretty inefficient function, at some point I need to restructure the skeletonSerialized structure to an enum like
|
||||
//https://github.com/FORTH-ModelBasedTracker/MocapNET/blob/master/src/MocapNET2/MocapNETLib2/mocapnet2.hpp#L839
|
||||
//it would just be 4 floating point checks instead of this loop going through labels etc.
|
||||
|
||||
//If we are at the correct skeletonSerialized label for the particular r/l foot or knee and check its value and it is non-zero
|
||||
//we can count it as present in the list of activeLegJoints count the number of active joints..
|
||||
if ( (strcasecmp_sk(skel->skeletonHeader[i].str,"visible_rfoot")==0) && (skel->skeletonBody[i].value) ) { ++activeLegJoints; } else
|
||||
if ( (strcasecmp_sk(skel->skeletonHeader[i].str,"visible_rknee")==0) && (skel->skeletonBody[i].value) ) { ++activeLegJoints; } else
|
||||
if ( (strcasecmp_sk(skel->skeletonHeader[i].str,"visible_lfoot")==0) && (skel->skeletonBody[i].value) ) { ++activeLegJoints; } else
|
||||
if ( (strcasecmp_sk(skel->skeletonHeader[i].str,"visible_lknee")==0) && (skel->skeletonBody[i].value) ) { ++activeLegJoints; }
|
||||
}
|
||||
}
|
||||
|
||||
if (activeLegJoints<3)
|
||||
{
|
||||
fprintf(stderr,YELLOW "Feet are missing, Only %u leg joints detected..\n" NORMAL,activeLegJoints);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int isLeftHardExtended(std::vector<float> result)
|
||||
{
|
||||
//TODO:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isRightHardExtended(std::vector<float> result)
|
||||
{
|
||||
//TODO:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int getPointOrientation(std::vector<float> result,float *x, float *y,float *r)
|
||||
{
|
||||
//TODO:
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "commonSkeleton.hpp"
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
int areFeetMissing(struct skeletonSerialized * skel);
|
||||
|
||||
|
||||
int isLeftHardExtended(std::vector<float> result);
|
||||
int isRightHardExtended(std::vector<float> result);
|
||||
|
||||
|
||||
int getPointOrientation(std::vector<float> result,float *x, float *y,float *r);
|
||||
+1401
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+276
@@ -0,0 +1,276 @@
|
||||
#include "artifactRecognition.hpp"
|
||||
|
||||
#include "../../../../dependencies/InputParser/InputParser_C.h"
|
||||
#include "../../../../dependencies/RGBDAcquisition/tools/AmMatrix/matrixCalculations.h"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#include <stdio.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 initializeArtifactsFromFile(struct sceneArtifacts * scene,const char * filename)
|
||||
{
|
||||
fprintf(stderr,"Initializing from %s .. \n",filename);
|
||||
|
||||
FILE * fp = fopen(filename,"r");
|
||||
if (fp!=0)
|
||||
{
|
||||
fprintf(stderr,GREEN "Successfully opened map file %s\n" NORMAL,filename);
|
||||
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
scene->numberOfArtifacts=0;
|
||||
unsigned int id=0;
|
||||
|
||||
struct InputParserC * ipc = InputParser_Create(8096,5);
|
||||
InputParser_SetDelimeter(ipc,0,',');
|
||||
InputParser_SetDelimeter(ipc,1,'(');
|
||||
InputParser_SetDelimeter(ipc,2,')');
|
||||
InputParser_SetDelimeter(ipc,3,10);
|
||||
InputParser_SetDelimeter(ipc,4,13);
|
||||
|
||||
do {
|
||||
read = getline(&line, &len, fp);
|
||||
if (line!=0)
|
||||
{
|
||||
int numberOfArguments = InputParser_SeperateWords(ipc,line,1);
|
||||
if ( InputParser_WordCompareNoCaseAuto(ipc,0,"AREA2D") )
|
||||
{
|
||||
if (scene->numberOfArtifacts+1<NUMBER_OF_ARTIFACTS)
|
||||
{
|
||||
++scene->numberOfArtifacts;
|
||||
if (scene->numberOfArtifacts>1)
|
||||
{
|
||||
++id;
|
||||
}
|
||||
|
||||
InputParser_GetWord(ipc,1,scene->artifact[id].label,512);
|
||||
fprintf(stderr,"New 2D Area declared ( %s )..!\n",scene->artifact[id].label);
|
||||
scene->artifact[id].y1 = InputParser_GetWordFloat(ipc,2);
|
||||
scene->artifact[id].x1 = InputParser_GetWordFloat(ipc,3);
|
||||
scene->artifact[id].y2 = InputParser_GetWordFloat(ipc,4);
|
||||
scene->artifact[id].x2 = InputParser_GetWordFloat(ipc,5);
|
||||
scene->artifact[id].is3D=0;
|
||||
scene->artifact[id].active=0;
|
||||
scene->artifact[id].hasAction=1;
|
||||
}
|
||||
} else
|
||||
|
||||
if ( InputParser_WordCompareNoCaseAuto(ipc,0,"OBJECT3D") )
|
||||
{
|
||||
if (scene->numberOfArtifacts+1<NUMBER_OF_ARTIFACTS)
|
||||
{
|
||||
++scene->numberOfArtifacts;
|
||||
if (scene->numberOfArtifacts>1)
|
||||
{
|
||||
++id;
|
||||
}
|
||||
|
||||
InputParser_GetWord(ipc,1,scene->artifact[id].label,512);
|
||||
fprintf(stderr,"New 3D Object declared ( %s )..!\n",scene->artifact[id].label);
|
||||
scene->artifact[id].y1 = InputParser_GetWordFloat(ipc,2);
|
||||
scene->artifact[id].x1 = InputParser_GetWordFloat(ipc,3);
|
||||
scene->artifact[id].z1 = InputParser_GetWordFloat(ipc,4);
|
||||
scene->artifact[id].y2 = InputParser_GetWordFloat(ipc,5);
|
||||
scene->artifact[id].x2 = InputParser_GetWordFloat(ipc,6);
|
||||
scene->artifact[id].z2 = InputParser_GetWordFloat(ipc,7);
|
||||
scene->artifact[id].is3D=1;
|
||||
scene->artifact[id].active=0;
|
||||
scene->artifact[id].hasAction=1;
|
||||
}
|
||||
} else
|
||||
|
||||
|
||||
if ( InputParser_WordCompareNoCaseAuto(ipc,0,"ACTIVATE_ON_POSITION") )
|
||||
{
|
||||
fprintf(stderr,"%s will activate on position\n",scene->artifact[id].label);
|
||||
scene->artifact[id].activatesOnPosition=1;
|
||||
} else
|
||||
if ( InputParser_WordCompareNoCaseAuto(ipc,0,"ACTIVATE_ON_LOOK") )
|
||||
{
|
||||
fprintf(stderr,"%s will activate on look\n",scene->artifact[id].label);
|
||||
scene->artifact[id].activatesOnLook=1;
|
||||
} else
|
||||
if ( InputParser_WordCompareNoCaseAuto(ipc,0,"ACTIVATE_ON_GESTURE") )
|
||||
{
|
||||
fprintf(stderr,"%s will activate on gesture\n",scene->artifact[id].label);
|
||||
scene->artifact[id].activateOnGesture=1;
|
||||
} else
|
||||
if ( InputParser_WordCompareNoCaseAuto(ipc,0,"ACTIVATE_ACTION") )
|
||||
{
|
||||
InputParser_GetWord(ipc,1,scene->artifact[id].actionToExecuteOnActivation,512);
|
||||
fprintf(stderr,"New Command for %s (%s) !\n",scene->artifact[id].label,scene->artifact[id].actionToExecuteOnActivation);
|
||||
scene->artifact[id].hasAction=1;
|
||||
} else
|
||||
if ( InputParser_WordCompareNoCaseAuto(ipc,0,"DEACTIVATE_ACTION") )
|
||||
{
|
||||
InputParser_GetWord(ipc,1,scene->artifact[id].actionToExecuteOnDeactivation,512);
|
||||
fprintf(stderr,"New Command for %s (%s) !\n",scene->artifact[id].label,scene->artifact[id].actionToExecuteOnDeactivation);
|
||||
scene->artifact[id].hasAction=1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
while( (line!=0) && (read>0) );
|
||||
|
||||
InputParser_Destroy(ipc);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int check3DArtifactCollision(struct artifactData * artifact,float x1, float y1, float z1,float x2, float y2, float z2)
|
||||
{
|
||||
if (artifact->is3D)
|
||||
{
|
||||
float initial[4]={x1,y1,z1,1.0};
|
||||
float target[4]={x2,y2,z2,1.0};
|
||||
//--------------------------------------------------------------
|
||||
float v0[4] = {
|
||||
std::min(artifact->x1,artifact->x2),
|
||||
std::min(artifact->y1,artifact->y2),
|
||||
(float) (artifact->z1+artifact->z2)/2,
|
||||
1.0
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
float v1[4] = {
|
||||
std::min(artifact->x1,artifact->x2),
|
||||
std::max(artifact->y1,artifact->y2),
|
||||
(float) (artifact->z1+artifact->z2)/2,
|
||||
1.0
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
float v2[4] = {
|
||||
std::max(artifact->x1,artifact->x2),
|
||||
std::max(artifact->y1,artifact->y2),
|
||||
(float) (artifact->z1+artifact->z2)/2,
|
||||
1.0
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
float v3[4] = {
|
||||
std::max(artifact->x1,artifact->x2),
|
||||
std::min(artifact->y1,artifact->y2),
|
||||
(float) (artifact->z1+artifact->z2)/2,
|
||||
1.0
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
if (rayIntersectsRectangle(initial,target,v0,v1,v2,v3))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int checkArtifactCollision(struct artifactData * artifact,float x, float y, float r)
|
||||
{
|
||||
if (
|
||||
(artifact->x1<x) && (artifact->y1<y) && (x<artifact->x2) && (y<artifact->y2)
|
||||
)
|
||||
{
|
||||
/*
|
||||
fprintf(stderr,"Artifact collision %0.2f %0.2f %0.2f %0.2f -> %0.2f %0.2f \n",
|
||||
artifact->x1,artifact->y1,
|
||||
artifact->x2,artifact->y2,
|
||||
x,y);
|
||||
*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
fprintf(stderr,"NO collision %0.2f %0.2f %0.2f %0.2f -> %0.2f %0.2f \n",
|
||||
artifact->x1,artifact->y1,
|
||||
artifact->x2,artifact->y2,
|
||||
x,y); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Given three colinear points p, q, r, the function checks if
|
||||
// point q lies on line segment 'pr'
|
||||
int onSegment(float pX,float pY, float qX,float qY, float rX, float rY)
|
||||
{
|
||||
if (qX <= std::max(pX, rX) && qX >= std::min(pX, rX) && qY <= std::max(pY, rY) && qY >= std::min(pY, rY)) { return 1; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// To find orientation of ordered triplet (p, q, r).
|
||||
// The function returns following values
|
||||
// 0 --> p, q and r are colinear
|
||||
// 1 --> Clockwise
|
||||
// 2 --> Counterclockwise
|
||||
int orientation(float pX,float pY, float qX,float qY, float rX, float rY)
|
||||
{
|
||||
// See https://www.geeksforgeeks.org/orientation-3-ordered-points/
|
||||
// for details of below formula.
|
||||
int val = (qY - pY) * (rX - qX) - (qX - pX) * (rY - qY);
|
||||
|
||||
if (val == 0) return 0; // colinear
|
||||
|
||||
return (val > 0)? 1: 2; // clock or counterclock wise
|
||||
}
|
||||
|
||||
// The main function that returns true if line segment 'p1q1'
|
||||
// and 'p2q2' intersect.
|
||||
int doIntersect(float p1X,float p1Y, float q1X, float q1Y,float p2X,float p2Y,float q2X, float q2Y)
|
||||
{
|
||||
// Find the four orientations needed for general and
|
||||
// special cases
|
||||
int o1 = orientation(p1X,p1Y, q1X,q1Y, p2X,p2Y);
|
||||
int o2 = orientation(p1X,p1Y, q1X,q1Y, q2X,q2Y);
|
||||
int o3 = orientation(p2X,p2Y, q2X,q2Y, p1X,p1Y);
|
||||
int o4 = orientation(p2X,p2Y, q2X,q2Y, q1X,q1Y);
|
||||
|
||||
// General case
|
||||
if (o1 != o2 && o3 != o4)
|
||||
return 1;
|
||||
|
||||
// Special Cases
|
||||
// p1, q1 and p2 are colinear and p2 lies on segment p1q1
|
||||
if (o1 == 0 && onSegment(p1X,p1Y, p2X,p2Y, q1X,q1Y)) return 1;
|
||||
|
||||
// p1, q1 and q2 are colinear and q2 lies on segment p1q1
|
||||
if (o2 == 0 && onSegment(p1X,p1Y, q2X,q2Y, q1X,q1Y)) return 1;
|
||||
|
||||
// p2, q2 and p1 are colinear and p1 lies on segment p2q2
|
||||
if (o3 == 0 && onSegment(p2X,p2Y, p1X,p1Y, q2X,q2Y)) return 1;
|
||||
|
||||
// p2, q2 and q1 are colinear and q1 lies on segment p2q2
|
||||
if (o4 == 0 && onSegment(p2X,p2Y, q1X,q1Y, q2X,q2Y)) return 1;
|
||||
|
||||
return 0; // Doesn't fall in any of the above cases
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int checkArtifactDirection(struct artifactData * artifact,float x1, float y1, float x2,float y2)
|
||||
{
|
||||
unsigned int check=0;
|
||||
|
||||
check+=doIntersect(x1,y1,x2,y2,artifact->x1,artifact->y1,artifact->x2,artifact->y1) ;
|
||||
if (check==0) { check+=doIntersect(x1,y1,x2,y2,artifact->x1,artifact->y2,artifact->x2,artifact->y2) ; }
|
||||
if (check==0) { check+=doIntersect(x1,y1,x2,y2,artifact->x1,artifact->y1,artifact->x1,artifact->y2) ; }
|
||||
if (check==0) { check+=doIntersect(x1,y1,x2,y2,artifact->x2,artifact->y1,artifact->x2,artifact->y2) ; }
|
||||
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
/** @file artifactRecognition.hpp
|
||||
* @brief MocapNET Artifact recognition is implemented here. Artifacts are places in 3D space that can trigger specific events for applications that need human computer interaction
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#define NUMBER_OF_ARTIFACTS 100
|
||||
|
||||
struct artifactData
|
||||
{
|
||||
float x1;
|
||||
float y1;
|
||||
float z1;
|
||||
float x2;
|
||||
float y2;
|
||||
float z2;
|
||||
char is3D;
|
||||
char activatesOnOrientation;
|
||||
char activatesOnLocation;
|
||||
char activatesOnGestures;
|
||||
|
||||
char hasAction;
|
||||
char active;
|
||||
char activatesOnLook;
|
||||
char activatesOnPosition;
|
||||
char activateOnGesture;
|
||||
char label[512];
|
||||
char actionToExecuteOnActivation[512];
|
||||
char actionToExecuteOnDeactivation[512];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief recorded gestures that can be used
|
||||
*/
|
||||
struct sceneArtifacts
|
||||
{
|
||||
int numberOfArtifacts;
|
||||
struct artifactData artifact[NUMBER_OF_ARTIFACTS];
|
||||
};
|
||||
|
||||
|
||||
//int initializeArtifacts(struct sceneArtifacts * scene);
|
||||
|
||||
int initializeArtifactsFromFile(struct sceneArtifacts * scene,const char * filename);
|
||||
|
||||
|
||||
int check3DArtifactCollision(struct artifactData * artifact,float x1, float y1, float z1,float x2, float y2, float z2);
|
||||
|
||||
int checkArtifactCollision(struct artifactData * artifact,float x, float y, float r);
|
||||
|
||||
int checkArtifactDirection(struct artifactData * artifact,float x1, float y1, float x2,float y2);
|
||||
|
||||
int doIntersect(float p1X,float p1Y, float q1X, float q1Y,float p2X,float p2Y,float q2X, float q2Y) ;
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
#include "gestureRecognition.hpp"
|
||||
#include "../mocapnet2.hpp"
|
||||
#include "../tools.hpp"
|
||||
#include "../IO/bvh.hpp"
|
||||
#include "../IO/csvRead.hpp"
|
||||
#include "poseRecognition.hpp"
|
||||
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
int addToMotionHistory(struct PoseHistory * poseHistoryStorage,std::vector<float> pose)
|
||||
{
|
||||
poseHistoryStorage->history.push_back(pose);
|
||||
if (poseHistoryStorage->history.size() > poseHistoryStorage->maxPoseHistory)
|
||||
{
|
||||
poseHistoryStorage->history.erase(poseHistoryStorage->history.begin());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dumpMotionHistory(const char * filename,struct PoseHistory * poseHistoryStorage)
|
||||
{
|
||||
return writeBVHFile(filename,0,0,poseHistoryStorage->history);
|
||||
}
|
||||
|
||||
int updateGestureActivity(std::vector<float> vecA,std::vector<float> vecB,std::vector<char> &active,float threshold)
|
||||
{
|
||||
if (vecA.size()!=vecB.size())
|
||||
{
|
||||
fprintf(stderr,"updateGestureActivity cannot compare different sized vectors..\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vecA.size()!=active.size())
|
||||
{
|
||||
fprintf(stderr,"updateGestureActivity cannot compare without allocated active vector..\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//Always skip X pos, Y pos, Z pos , and rotation
|
||||
for (int i=6; i<active.size(); i++)
|
||||
{
|
||||
float difference=abs(vecA[i]-vecB[i]);
|
||||
if (difference>threshold)
|
||||
{
|
||||
active[i]=1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int automaticallyObserveActiveJointsInGesture(struct RecordedGesture * gesture)
|
||||
{
|
||||
//fprintf(stderr,"automaticallyObserveActiveJointsInGesture:");
|
||||
if (gesture->gesture.size()==0)
|
||||
{
|
||||
fprintf(stderr,"Failed to automatically observe active joints\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<float> initialPose = gesture->gesture[0];
|
||||
|
||||
gesture->usedJoints.clear();
|
||||
for (int jointID=0; jointID<initialPose.size(); jointID++)
|
||||
{
|
||||
gesture->usedJoints.push_back(0);
|
||||
}
|
||||
|
||||
for (int gestureID=0; gestureID<gesture->gesture.size(); gestureID++)
|
||||
{
|
||||
updateGestureActivity(
|
||||
initialPose,
|
||||
gesture->gesture[gestureID],
|
||||
gesture->usedJoints,
|
||||
5
|
||||
);
|
||||
}
|
||||
|
||||
//fprintf(stderr,"done\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int loadGestures(struct GestureDatabase * gestureDB)
|
||||
{
|
||||
unsigned int gestureID;
|
||||
char gesturePath[512]= {0};
|
||||
|
||||
gestureDB->gestureChecksPerformed=0;
|
||||
|
||||
for (gestureID=0; gestureID<hardcodedGestureNumber; gestureID++)
|
||||
{
|
||||
snprintf(gesturePath,512,"dataset/gestures/%s",hardcodedGestureName[gestureID]);
|
||||
fprintf(stderr,"Loading Gesture %u -> %s : ",gestureID,gesturePath);
|
||||
|
||||
gestureDB->gesture[gestureID].gesture=loadBVHFileMotionFrames(gesturePath);
|
||||
//gestureDB->gesture[gestureID].bvhMotionGesture=loadBVHFile(gesturePath);
|
||||
|
||||
//if (gestureDB->gesture[gestureID].bvhMotionGesture!=0)
|
||||
if (gestureDB->gesture[gestureID].gesture.size()>0)
|
||||
{
|
||||
fprintf(stderr,"Gesture %s has %lu frames with %lu fields each\n",gesturePath,gestureDB->gesture[gestureID].gesture.size(),gestureDB->gesture[gestureID].gesture[0].size());
|
||||
gestureDB->gesture[gestureID].loaded=1;
|
||||
gestureDB->gesture[gestureID].gestureCallback=0;
|
||||
snprintf(gestureDB->gesture[gestureID].label,128,"%s",hardcodedGestureName[gestureID]);
|
||||
gestureDB->numberOfLoadedGestures +=1;
|
||||
|
||||
//Populate
|
||||
//gestureDB->gesture[gestureID].gesture;
|
||||
if (automaticallyObserveActiveJointsInGesture(&gestureDB->gesture[gestureID]))
|
||||
{
|
||||
for (int jointID=0; jointID<gestureDB->gesture[gestureID].usedJoints.size(); jointID++)
|
||||
{
|
||||
if (gestureDB->gesture[gestureID].usedJoints[jointID])
|
||||
{
|
||||
fprintf(stderr,YELLOW "Joint %u/%s is going to be used for gesture #%u\n" NORMAL,jointID,MocapNETOutputArrayNames[jointID],gestureID);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,YELLOW "Failure observing active joints\n" NORMAL);
|
||||
}
|
||||
|
||||
fprintf(stderr,GREEN "Success , loaded %lu frames\n" NORMAL,gestureDB->gesture[gestureID].gesture.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Failure\n" NORMAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (gestureDB->numberOfLoadedGestures>0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int compareHistoryWithGesture(
|
||||
struct RecordedGesture * gesture,
|
||||
struct PoseHistory * poseHistoryStorage,
|
||||
unsigned int checkSerialNumber,
|
||||
float currentFramerate,
|
||||
float targetFramerate,
|
||||
float percentageForDetection,
|
||||
float threshold
|
||||
)
|
||||
{
|
||||
unsigned int matchingFrames=0;
|
||||
if (poseHistoryStorage->history.size()==0)
|
||||
{
|
||||
fprintf(stderr,"Requested comparison with empty history..\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gesture->lastActivation>checkSerialNumber)
|
||||
{
|
||||
fprintf(stderr,RED "compareHistoryWithGesture: inverted timestmaps, something is terribly wrong..\n" NORMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (checkSerialNumber-gesture->lastActivation<GESTURE_ACTIVATION_COOLDOWN_IN_FRAMES)
|
||||
{
|
||||
fprintf(stderr,YELLOW "gesture %s on cooldown..\n" NORMAL,gesture->label);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//TODO: Compensate for different targetFramerate / currentFramerate here..!
|
||||
//In case of the currentFramerate being larger than the targetFramerate there should be more frames checked to increase accuracy
|
||||
//In case of the currentFramerate being smaller than the targetFramerate there should be skipped frames
|
||||
|
||||
if (poseHistoryStorage->history.size()>=gesture->gesture.size())
|
||||
{
|
||||
unsigned int frameID=0;
|
||||
unsigned int historyStart=poseHistoryStorage->history.size() - gesture->gesture.size();
|
||||
//unsigned int jointNumber=poseHistoryStorage->history[0].size();
|
||||
//unsigned int jointID=0;
|
||||
for (frameID=0; frameID<gesture->gesture.size(); frameID++)
|
||||
{
|
||||
matchingFrames+=areTwoBVHFramesCloseEnough(gesture->gesture[frameID],poseHistoryStorage->history[frameID+historyStart],gesture->usedJoints,threshold);
|
||||
}
|
||||
|
||||
gesture->percentageComplete = (float) matchingFrames/gesture->gesture.size();
|
||||
float percentComplete = 100*gesture->percentageComplete;
|
||||
|
||||
if (percentComplete > 100 )
|
||||
{
|
||||
fprintf(stderr,RED);
|
||||
fprintf(stderr,"There is something wrong in the gesture files ( size = %lu )\n ",gesture->gesture.size());
|
||||
}
|
||||
else if (percentComplete >= percentageForDetection )
|
||||
{
|
||||
fprintf(stderr,GREEN);
|
||||
gesture->lastActivation=checkSerialNumber;
|
||||
}
|
||||
else if (percentComplete >= 50.0 )
|
||||
{
|
||||
fprintf(stderr,YELLOW);
|
||||
}
|
||||
fprintf(stderr,"Gesture %s - %0.2f %% %u/%lu\n" NORMAL,gesture->label,percentComplete,matchingFrames,gesture->gesture.size());
|
||||
|
||||
//If we have more than 75% or whatever is the target percentage correct trigger..!
|
||||
return (percentComplete >= percentageForDetection );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int compareHistoryWithKnownGestures(struct GestureDatabase * gestureDB,struct PoseHistory * poseHistoryStorage,float percentageForDetection,float threshold)
|
||||
{
|
||||
unsigned long now=GetTickCountMicrosecondsMN();
|
||||
unsigned long previousRun=gestureDB->previousGestureCheckTimestamp;
|
||||
gestureDB->previousGestureCheckTimestamp = now;
|
||||
|
||||
float currentFramerate = convertStartEndTimeFromMicrosecondsToFPS(previousRun,now);
|
||||
float targetFramerate=16.0;
|
||||
|
||||
unsigned int gestureID=0;
|
||||
gestureDB->gestureChecksPerformed+=1;
|
||||
|
||||
for (gestureID=0; gestureID<gestureDB->numberOfLoadedGestures; gestureID++)
|
||||
{
|
||||
if (
|
||||
compareHistoryWithGesture(
|
||||
&gestureDB->gesture[gestureID],
|
||||
poseHistoryStorage,
|
||||
gestureDB->gestureChecksPerformed,
|
||||
currentFramerate,
|
||||
targetFramerate,
|
||||
percentageForDetection,
|
||||
threshold
|
||||
)
|
||||
)
|
||||
{
|
||||
return 1+gestureID;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
/** @file gestureRecognition.hpp
|
||||
* @brief MocapNET Gesture recognition is implemented here
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is an array of names for the hardcoded gestures included in the dataset/gestures/ subdirectory
|
||||
* Please remember to update hardcodedPoseNumber, its value should be the number of arguments in this array
|
||||
* If you have arguments 0 - 10 you should set hardcodedGestureNumber to 11
|
||||
*/
|
||||
static const char * hardcodedGestureName[] =
|
||||
{
|
||||
"help.bvh", //0
|
||||
"push.bvh", //1
|
||||
"lefthandcircle.bvh", //2
|
||||
"righthandcircle.bvh", //3
|
||||
"waveleft.bvh", //4
|
||||
"doubleclap.bvh", //5
|
||||
"waveright.bvh", //6
|
||||
"leftkick.bvh", //8
|
||||
"rightkick.bvh", //9
|
||||
"tpose.bvh", //10
|
||||
"handsup.bvh", //7
|
||||
"", //
|
||||
"" //13
|
||||
//hardcodedGestureNumber should be kept in sync
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief This needs to be kept in sync with hardcodedGestureName */
|
||||
const unsigned int hardcodedGestureNumber=10;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gesture tuning controls for the brave..
|
||||
**/
|
||||
const unsigned int GESTURE_ACTIVATION_COOLDOWN_IN_FRAMES=50;
|
||||
const float GESTURE_COMPLETION_PERCENT=80.0;
|
||||
const float GESTURE_ANGLE_SENSITIVITY=25.0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief history of poses
|
||||
*/
|
||||
struct PoseHistory
|
||||
{
|
||||
unsigned int maxPoseHistory;
|
||||
std::vector<std::vector<float> > history;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief recorded gestures that can be used
|
||||
*/
|
||||
struct RecordedGesture
|
||||
{
|
||||
unsigned int lastActivation;
|
||||
float percentageComplete;
|
||||
char loaded;
|
||||
char label[128];
|
||||
std::vector<std::vector<float> > gesture;
|
||||
std::vector<char> usedJoints;
|
||||
void * gestureCallback;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief gesture detection context, to facilitate gestures
|
||||
*/
|
||||
struct GestureDatabase
|
||||
{
|
||||
unsigned int gestureChecksPerformed;
|
||||
unsigned int numberOfLoadedGestures;
|
||||
struct RecordedGesture gesture[hardcodedGestureNumber];
|
||||
unsigned long previousGestureCheckTimestamp;
|
||||
};
|
||||
|
||||
|
||||
int loadGestures(struct GestureDatabase * gestureDB);
|
||||
|
||||
int addToMotionHistory(struct PoseHistory * poseHistoryStorage,std::vector<float> pose);
|
||||
|
||||
|
||||
int dumpMotionHistory(const char * filename,struct PoseHistory * poseHistoryStorage);
|
||||
|
||||
|
||||
int compareHistoryWithKnownGestures(struct GestureDatabase * gestureDB,struct PoseHistory * poseHistoryStorage,float percentageForDetection,float threshold);
|
||||
+663
@@ -0,0 +1,663 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../mocapnet2.hpp"
|
||||
#include "parseCommandlineOptions.hpp"
|
||||
#include "../IO/bvh.hpp"
|
||||
#include "../tools.hpp"
|
||||
|
||||
#include "../../../JointEstimator2D/jointEstimator2D.hpp"
|
||||
#include "../IO/jsonMocapNETHelpers.hpp"
|
||||
#include "../IO/csvRead.hpp"
|
||||
|
||||
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
const char outputPathStatic[]="out.bvh";
|
||||
|
||||
void defaultMocapNET2Options(struct MocapNET2Options * options)
|
||||
{
|
||||
memset(options,0,sizeof(struct MocapNET2Options));
|
||||
|
||||
options->isJSONFile=0;
|
||||
options->isCSVFile=0;
|
||||
options->webcamSource = 0;
|
||||
options->path=0;
|
||||
options->datasetPath=0;
|
||||
options->jointEstimatorUsed = JOINT_2D_ESTIMATOR_OPENPOSE; // JOINT_2D_ESTIMATOR_FORTH;
|
||||
|
||||
options->doUpperBody=1;
|
||||
options->doLowerBody=1;
|
||||
options->doFace=0;
|
||||
options->doHands=0;
|
||||
options->forceFront=0;
|
||||
options->forceLeft=0;
|
||||
options->forceRight=0;
|
||||
options->forceBack=0;
|
||||
options->visualizationType=0;
|
||||
|
||||
//Default IK options
|
||||
options->useInverseKinematics=0;
|
||||
options->learningRate=0.01;
|
||||
options->spring =20.0;
|
||||
options->iterations=5;
|
||||
options->epochs=30;
|
||||
|
||||
//Test under Simulated Gaussian Noise
|
||||
options->addNormalizedPixelGaussianNoiseX=0.0;
|
||||
options->addNormalizedPixelGaussianNoiseY=0.0;
|
||||
|
||||
options->outputPath = (char*) outputPathStatic;
|
||||
|
||||
options->visualize=1;
|
||||
options->doMultiThreadedIK=0;
|
||||
options->useOpenGLVisualization=0;
|
||||
options->save3DVisualization=0;
|
||||
options->save2DVisualization=0;
|
||||
options->saveVisualization=0;
|
||||
options->saveCSV3DFile=0;
|
||||
options->constrainPositionRotation=1;
|
||||
|
||||
options->delay=0;
|
||||
options->prependTPose=0;
|
||||
options->serialLength=5;
|
||||
options->bvhCenter=0;
|
||||
|
||||
if (getCPUName(options->CPUName,512))
|
||||
{
|
||||
fprintf(stderr,"CPU : %s\n",options->CPUName);
|
||||
}
|
||||
|
||||
if (getGPUName(options->GPUName,512))
|
||||
{
|
||||
fprintf(stderr,"GPU : %s\n",options->GPUName);
|
||||
}
|
||||
|
||||
options->inputFramerate = 30.0;
|
||||
|
||||
options->quality=1.0;
|
||||
options->mocapNETMode=5;
|
||||
options->doGestureDetection=0;
|
||||
options->doOutputFiltering=1;
|
||||
options->useCPUOnlyForMocapNET=1; //Use CPU for MocapNET
|
||||
options->useCPUOnlyFor2DEstimator=0; // Use GPU for 2D estimator
|
||||
options->brokenFrames=0;
|
||||
options->numberOfMissingJoints=0;
|
||||
|
||||
options->visWidth=1920;
|
||||
options->visHeight=1080;
|
||||
options->width=1920;
|
||||
options->height=1080;
|
||||
|
||||
|
||||
options->scale=1.0;
|
||||
options->scaleX=1.0;
|
||||
options->scaleY=1.0;
|
||||
options->fScaleX=1.0;
|
||||
options->fScaleY=1.0;
|
||||
|
||||
options->loopStartTime=0;
|
||||
options->loopEndTime=1000;
|
||||
options->totalLoopFPS=0.0;
|
||||
options->fpsMocapNET=0.0;
|
||||
options->fps2DEstimator=0.0;
|
||||
|
||||
options->frameSkip=0;
|
||||
options->frameLimit=0;
|
||||
}
|
||||
|
||||
|
||||
void checkVersion()
|
||||
{
|
||||
char hostname[1024];
|
||||
gethostname(hostname, 1024);
|
||||
//==========================
|
||||
//char username[1024];
|
||||
//getlogin_r(username,1024);
|
||||
//==========================
|
||||
|
||||
char command[2048];
|
||||
snprintf(command,2048,"wget -qO- \"http://ammar.gr/mocapnet/version/index.php?h=%s&v=%s\"&",hostname,MocapNETVersion);
|
||||
int i=0;
|
||||
//i = system(command); ammar.gr is not working :(
|
||||
}
|
||||
|
||||
|
||||
void argumentError(int currentlyAt,int extraAt,int argc, char *argv[])
|
||||
{
|
||||
fprintf(stderr,RED "Incorrect number of arguments, %u required ( @ %s )..\n" NORMAL,extraAt,argv[currentlyAt]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int loadOptionsFromCommandlineOptions(struct MocapNET2Options * options,int argc, char *argv[])
|
||||
{
|
||||
checkVersion();
|
||||
//(struct BVH_MotionCapture * bvhMotion,float shoulderToElbowLength,float elbowToHandLength,float hipToKneeLength,float kneeToFootLength)
|
||||
//------------------------------------------------------
|
||||
// Parse arguments
|
||||
//------------------------------------------------------
|
||||
for (int i=0; i<argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--forceOutputPositionRotation")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->forceOutputPositionRotation=1;
|
||||
options->outputPosRot[0]=atof(argv[i+1]);
|
||||
options->outputPosRot[1]=atof(argv[i+2]);
|
||||
options->outputPosRot[2]=atof(argv[i+3]);
|
||||
options->outputPosRot[3]=atof(argv[i+4]);
|
||||
options->outputPosRot[4]=atof(argv[i+5]);
|
||||
options->outputPosRot[5]=atof(argv[i+6]);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strcmp(argv[i],"--rotateSkeleton")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
if (strcmp(argv[i+1],"auto")==0)
|
||||
{
|
||||
options->skeletonRotation=360.0;
|
||||
} else
|
||||
{
|
||||
options->skeletonRotation=atof(argv[i+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (strcmp(argv[i],"--inputFramerate")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->inputFramerate = atof(argv[i+1]);
|
||||
fprintf(stderr,"Input Framerate set to %0.2f \n", options->inputFramerate);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (strcmp(argv[i],"--msg")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
fprintf(stderr,"Message set to %s \n",argv[i+1]);
|
||||
snprintf(options->message,512,"%s",argv[i+1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strcmp(argv[i],"--map")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
fprintf(stderr,"Configuring Map to use file %s \n",argv[i+1]);
|
||||
snprintf(options->mapFilePath,512,"%s",argv[i+1]);
|
||||
options->visualizationType=2;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (strcmp(argv[i],"--unconstrained")==0)
|
||||
{
|
||||
options->constrainPositionRotation=0;
|
||||
}
|
||||
else if ( (strcmp(argv[i],"-o")==0) || (strcmp(argv[i],"--output")==0) )
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->outputPath=argv[i+1];
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--dontbend")==0)
|
||||
{
|
||||
options->dontBend=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--opengl")==0)
|
||||
{
|
||||
options->useOpenGLVisualization=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--save")==0)
|
||||
{
|
||||
options->saveVisualization=1;
|
||||
}
|
||||
else if ( (strcmp(argv[i],"--save2D")==0) || (strcmp(argv[i],"--save2d")==0) )
|
||||
{
|
||||
options->save2DVisualization=1;
|
||||
}
|
||||
else if ( (strcmp(argv[i],"--save3D")==0) || (strcmp(argv[i],"--save3d")==0) )
|
||||
{
|
||||
options->save3DVisualization=1;
|
||||
}
|
||||
else if ( (strcmp(argv[i],"--saveCSV3D")==0) || (strcmp(argv[i],"--savecsv3d")==0) )
|
||||
{
|
||||
options->saveCSV3DFile=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--noik")==0)
|
||||
{
|
||||
options->useInverseKinematics=0;
|
||||
}
|
||||
else if (strcmp(argv[i],"--ik")==0)
|
||||
{
|
||||
if (argc>i+3)
|
||||
{
|
||||
options->useInverseKinematics=1;
|
||||
options->learningRate=atof(argv[i+1]);
|
||||
options->iterations=atoi(argv[i+2]);
|
||||
options->epochs=atoi(argv[i+3]);
|
||||
//options->spring=atof(argv[i+4]);
|
||||
}
|
||||
else
|
||||
{ argumentError(i,3,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--nv")==0)
|
||||
{
|
||||
fprintf(stderr,"Visualization disabled\n");
|
||||
options->visualize=0;
|
||||
}
|
||||
else if (strcmp(argv[i],"--novisualization")==0)
|
||||
{
|
||||
fprintf(stderr,"Visualization disabled\n");
|
||||
options->visualize=0;
|
||||
}
|
||||
else if (strcmp(argv[i],"-v")==0)
|
||||
{
|
||||
fprintf(stderr,"Visualization enabled\n");
|
||||
options->visualize=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--visualize")==0)
|
||||
{
|
||||
fprintf(stderr,"Visualization enabled\n");
|
||||
options->visualize=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--frameskip")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->frameSkip=atoi(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--nofilter")==0)
|
||||
{
|
||||
fprintf(stderr,"Filtering Disabled\n");
|
||||
options->doOutputFiltering=0;
|
||||
}
|
||||
else if (strcmp(argv[i],"--scale")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->scale=atof(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--scaleX")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->scaleX=atof(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--scaleY")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->scaleY=atof(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--focalLength")==0)
|
||||
{
|
||||
overrideBVHSubsystemFocalLength(atof(argv[i+1]),atof(argv[i+2]));
|
||||
}
|
||||
else if (strcmp(argv[i],"--fscale")==0)
|
||||
{
|
||||
if (argc>i+2)
|
||||
{
|
||||
options->fScaleX=atof(argv[i+1]);
|
||||
options->fScaleY=atof(argv[i+2]);
|
||||
} else
|
||||
{ argumentError(i,2,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--noise")==0)
|
||||
{
|
||||
if (argc>i+2)
|
||||
{
|
||||
options->addNormalizedPixelGaussianNoiseX=atof(argv[i+1]);
|
||||
options->addNormalizedPixelGaussianNoiseY=atof(argv[i+2]);
|
||||
} else
|
||||
{ argumentError(i,2,argc,argv); }
|
||||
}
|
||||
|
||||
else if (strcmp(argv[i],"--front")==0)
|
||||
{
|
||||
options->forceFront=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--back")==0)
|
||||
{
|
||||
options->forceBack=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--left")==0)
|
||||
{
|
||||
options->forceLeft=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--right")==0)
|
||||
{
|
||||
options->forceRight=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--bvhcenter")==0)
|
||||
{
|
||||
options->bvhCenter=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--forth")==0)
|
||||
{
|
||||
options->jointEstimatorUsed = JOINT_2D_ESTIMATOR_FORTH;
|
||||
}
|
||||
else if (strcmp(argv[i],"--openpose")==0)
|
||||
{
|
||||
options->jointEstimatorUsed = JOINT_2D_ESTIMATOR_OPENPOSE;
|
||||
}
|
||||
else if (strcmp(argv[i],"--vnect")==0)
|
||||
{
|
||||
options->jointEstimatorUsed = JOINT_2D_ESTIMATOR_VNECT;
|
||||
}
|
||||
else if (strcmp(argv[i],"--frames")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->frameLimit=atoi(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--maxFrames")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->frameLimit=atoi(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--from")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->webcamSource = argv[i+1];
|
||||
options->path = argv[i+1];
|
||||
if (strstr(options->path,".json")!=0)
|
||||
{
|
||||
fprintf(stderr,"JSON files no longer directly supported, please use the converter tool to convert them to .CSV");
|
||||
options->isJSONFile=1;
|
||||
options->isCSVFile=0;
|
||||
}
|
||||
if (strstr(options->path,".csv")!=0)
|
||||
{
|
||||
options->isJSONFile=0;
|
||||
options->isCSVFile=1;
|
||||
}
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--quality")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->quality=atof(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else
|
||||
if (strcmp(argv[i],"--mt")==0)
|
||||
{
|
||||
options->doMultiThreadedIK=1;
|
||||
}
|
||||
else
|
||||
if (strcmp(argv[i],"--cpu")==0)
|
||||
{
|
||||
options->useCPUOnlyForMocapNET=1;
|
||||
options->useCPUOnlyFor2DEstimator=1;
|
||||
}
|
||||
else
|
||||
//if (strcmp(argv[i],"--cpu")==0) { setenv("CUDA_VISIBLE_DEVICES", "", 1); } else
|
||||
if (strcmp(argv[i],"--gpu")==0)
|
||||
{
|
||||
options->useCPUOnlyForMocapNET=0;
|
||||
options->useCPUOnlyFor2DEstimator=0;
|
||||
}
|
||||
else if (strcmp(argv[i],"--delay")==0)
|
||||
{
|
||||
//If you want to take some time to check the results that
|
||||
//might otherwise pass by very fast
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->delay=atoi(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--skip")==0)
|
||||
{
|
||||
//Allow skipping of frames in the neural network and using only the very fast IK module..
|
||||
options->maximumNeuralNetworkSkipFrames=atoi(argv[i+1]);
|
||||
|
||||
if (options->maximumNeuralNetworkSkipFrames>0)
|
||||
{
|
||||
options->skipNeuralNetworkIfItIsNotNeeded=1;
|
||||
if (options->maximumNeuralNetworkSkipFrames==1)
|
||||
{
|
||||
fprintf(stderr,"Skipping 1 frame every one frame makes no sense, assuming user wants to skip 1 frame every 2 frames\n");
|
||||
options->maximumNeuralNetworkSkipFrames=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i],"--tpose")==0)
|
||||
{
|
||||
options-> prependTPose=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--nolowerbody")==0)
|
||||
{
|
||||
options->doLowerBody=0;
|
||||
}
|
||||
else if (strcmp(argv[i],"--show")==0)
|
||||
{
|
||||
options->visualizationType=atoi(argv[i+1]);
|
||||
}
|
||||
else if (strcmp(argv[i],"--nohands")==0)
|
||||
{
|
||||
options->doHands=0;
|
||||
}
|
||||
else if (strcmp(argv[i],"--hands")==0)
|
||||
{
|
||||
options->doHands=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--face")==0)
|
||||
{
|
||||
options->doFace=1;
|
||||
}
|
||||
else if (strcmp(argv[i],"--noface")==0)
|
||||
{
|
||||
options->doFace=0;
|
||||
}
|
||||
else if (strcmp(argv[i],"--label")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->label = argv[i+1];
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--seriallength")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->serialLength = atoi(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if ( (strcmp(argv[i],"-o")==0) || (strcmp(argv[i],"--output")==0) )
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->outputPath=argv[i+1];
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--mode")==0)
|
||||
{
|
||||
if (argc>i+1)
|
||||
{
|
||||
options->mocapNETMode=atoi(argv[i+1]);
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--size")==0)
|
||||
{
|
||||
if (argc>i+2)
|
||||
{
|
||||
options->width = atoi(argv[i+1]);
|
||||
options->height = atoi(argv[i+2]);
|
||||
} else
|
||||
{ argumentError(i,2,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--visualizationSize")==0)
|
||||
{
|
||||
if (argc>i+2)
|
||||
{
|
||||
options->visWidth = atoi(argv[i+1]);
|
||||
options->visHeight = atoi(argv[i+2]);
|
||||
} else
|
||||
{ argumentError(i,2,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--gestures")==0)
|
||||
{
|
||||
options->doGestureDetection=1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int loadOptionsAfterBVHLoadFromCommandlineOptions(struct MocapNET2Options * options,int argc, char *argv[])
|
||||
{
|
||||
options->hasInit=0;
|
||||
for (int i=0; i<argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--changeFeetDimensions")==0)
|
||||
{
|
||||
if(argc>i+2)
|
||||
{
|
||||
if (!options->hasInit)
|
||||
{
|
||||
initializeBVHConverter(0,options->visWidth,options->visHeight,0);
|
||||
options->hasInit=1;
|
||||
}
|
||||
|
||||
changeFeetDimensions(
|
||||
atof(argv[i+1]),
|
||||
atof(argv[i+2])
|
||||
);
|
||||
} else
|
||||
{ argumentError(i,2,argc,argv); }
|
||||
}
|
||||
else
|
||||
if (strcmp(argv[i],"--scaleAllJointDimensions")==0)
|
||||
{
|
||||
if(argc>i+1)
|
||||
{
|
||||
if (!options->hasInit)
|
||||
{
|
||||
initializeBVHConverter(0,options->visWidth,options->visHeight,0);
|
||||
options->hasInit=1;
|
||||
}
|
||||
scaleAllJoints(atof(argv[i+1]));
|
||||
} else
|
||||
{ argumentError(i,1,argc,argv); }
|
||||
}
|
||||
else if (strcmp(argv[i],"--changeJointDimensions")==0)
|
||||
{
|
||||
if(argc>i+9)
|
||||
{
|
||||
if (!options->hasInit)
|
||||
{
|
||||
initializeBVHConverter(0,options->visWidth,options->visHeight,0);
|
||||
options->hasInit=1;
|
||||
}
|
||||
changeJointDimensions(
|
||||
atof(argv[i+1]),
|
||||
atof(argv[i+2]),
|
||||
atof(argv[i+3]),
|
||||
atof(argv[i+4]),
|
||||
atof(argv[i+5]),
|
||||
atof(argv[i+6]),
|
||||
atof(argv[i+7]),
|
||||
atof(argv[i+8]),
|
||||
atof(argv[i+9])
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
argumentError(i,9,argc,argv);
|
||||
fprintf(stderr,"Incorrect number of parameters given..\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int takeCareOfScalingInputAndAddingNoiseAccordingToOptions(struct MocapNET2Options * options,struct skeletonSerialized * skeleton)
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Changing Input 2D Point Cloud by Scaling it
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
if (options->scale!=1.0)
|
||||
{
|
||||
uniformlyScaleSerializedSkeleton(skeleton,options->scale);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
if (options->scaleX!=1.0)
|
||||
{
|
||||
if (!scaleSerializedSkeletonX(skeleton,options->scaleX))
|
||||
{
|
||||
fprintf(stderr,RED "Failed to scale skeleton in X axis\n" NORMAL);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
if (options->scaleY!=1.0)
|
||||
{
|
||||
if (!scaleSerializedSkeletonY(skeleton,options->scaleY))
|
||||
{
|
||||
fprintf(stderr,RED "Failed to scale skeleton in Y axis\n" NORMAL);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
if ( (options->fScaleX!=1.0) || (options->fScaleY!=1.0) )
|
||||
{
|
||||
if (! scaleSerializedSkeletonFromCenter(skeleton,options->fScaleX,options->fScaleY) )
|
||||
{
|
||||
fprintf(stderr,RED "Failed to scale skeleton to approximate focal length change\n" NORMAL);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
if ( (options->addNormalizedPixelGaussianNoiseX>0.0) || (options->addNormalizedPixelGaussianNoiseY>0.0) )
|
||||
{
|
||||
fprintf(stderr,RED "Note: You are running adding gaussian noise of std deviation %0.2f,%0.2f pixels on 2D joints\n" NORMAL,
|
||||
options->width * options->addNormalizedPixelGaussianNoiseX,
|
||||
options->height * options->addNormalizedPixelGaussianNoiseY
|
||||
);
|
||||
perturbSerializedSkeletonUsingGaussianNoise(skeleton,options->addNormalizedPixelGaussianNoiseX,options->addNormalizedPixelGaussianNoiseY);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
/** @file parseCommandlineOptions.hpp
|
||||
* @brief MocapNET applications handle a large number of parameters. In order to simplify development and not having to manually sync all accepted parameters through all end-user applications this is the
|
||||
* central module that parses commandline parameters and populates the MocapNET2Options structure that holds them
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief MocapNET has many options depending on datasets etc, instead of storing them in each application
|
||||
* this is a central strcture to make it easier to parse them..
|
||||
*/
|
||||
struct MocapNET2Options
|
||||
{
|
||||
const char * webcamSource;
|
||||
const char * path;
|
||||
char * datasetPath;
|
||||
unsigned int inputIsSingleImage;
|
||||
|
||||
unsigned int isJSONFile;
|
||||
unsigned int isCSVFile;
|
||||
unsigned int jointEstimatorUsed;
|
||||
|
||||
unsigned int doUpperBody,doLowerBody,doFace,doHands;
|
||||
unsigned int forceFront,forceLeft,forceRight,forceBack;
|
||||
unsigned int useInverseKinematics;
|
||||
unsigned int visualizationType;
|
||||
|
||||
unsigned int skipNeuralNetworkIfItIsNotNeeded;
|
||||
unsigned int maximumNeuralNetworkSkipFrames;
|
||||
|
||||
float inputFramerate;
|
||||
|
||||
float learningRate;
|
||||
float spring;
|
||||
unsigned int iterations;
|
||||
unsigned int epochs;
|
||||
|
||||
float addNormalizedPixelGaussianNoiseX,addNormalizedPixelGaussianNoiseY;
|
||||
|
||||
char * outputPath;
|
||||
|
||||
unsigned int visualize,useOpenGLVisualization,save3DVisualization,save2DVisualization,saveVisualization,saveCSV3DFile,constrainPositionRotation;
|
||||
|
||||
char CPUName[512];
|
||||
char GPUName[512];
|
||||
char message[512];
|
||||
|
||||
unsigned int delay;
|
||||
unsigned int prependTPose;
|
||||
unsigned int serialLength;
|
||||
const char * label;
|
||||
unsigned int bvhCenter;
|
||||
|
||||
float quality;
|
||||
unsigned int mocapNETMode;
|
||||
int doGestureDetection;
|
||||
int doOutputFiltering;
|
||||
int doMultiThreadedIK;
|
||||
|
||||
unsigned int useCPUOnlyForMocapNET;
|
||||
unsigned int useCPUOnlyFor2DEstimator;
|
||||
unsigned int brokenFrames;
|
||||
unsigned int numberOfMissingJoints;
|
||||
|
||||
unsigned int visWidth,visHeight;
|
||||
unsigned int width,height;
|
||||
|
||||
long loopStartTime,loopEndTime;
|
||||
float totalLoopFPS;
|
||||
float fpsAcquisition,fpsMocapNET,fps2DEstimator,fpsIK;
|
||||
unsigned int frameLimit;
|
||||
unsigned int frameSkip;
|
||||
|
||||
float scale,scaleX,scaleY,fScaleX,fScaleY;
|
||||
|
||||
|
||||
float skeletonRotation;
|
||||
|
||||
int dontBend;
|
||||
char forceOutputPositionRotation;
|
||||
float outputPosRot[6];
|
||||
|
||||
|
||||
char mapFilePath[512];
|
||||
|
||||
int hasInit;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void defaultMocapNET2Options(struct MocapNET2Options * options);
|
||||
|
||||
int loadOptionsFromCommandlineOptions(struct MocapNET2Options * options,int argc, char *argv[]);
|
||||
|
||||
int loadOptionsAfterBVHLoadFromCommandlineOptions(struct MocapNET2Options * options,int argc, char *argv[]);
|
||||
|
||||
|
||||
int takeCareOfScalingInputAndAddingNoiseAccordingToOptions(struct MocapNET2Options * options,struct skeletonSerialized * skeleton);
|
||||
@@ -0,0 +1,180 @@
|
||||
#include "poseRecognition.hpp"
|
||||
#include "../mocapnet2.hpp"
|
||||
#include "../tools.hpp"
|
||||
#include "../IO/bvh.hpp"
|
||||
#include "../IO/csvRead.hpp"
|
||||
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
|
||||
|
||||
int loadPoses(struct PoseDatabase * poseDB)
|
||||
{
|
||||
unsigned int poseID;
|
||||
char posePath[512]= {0};
|
||||
|
||||
poseDB->poseChecksPerformed=0;
|
||||
|
||||
for (poseID=0; poseID<hardcodedPoseNumber; poseID++)
|
||||
{
|
||||
snprintf(posePath,512,"dataset/poses/%s",hardcodedPoseName[poseID]);
|
||||
fprintf(stderr,"Loading Pose %u -> %s : ",poseID,posePath);
|
||||
|
||||
std::vector<std::vector<float> > bvhFileLoaded = loadBVHFileMotionFrames(posePath);
|
||||
|
||||
if (bvhFileLoaded.size()==0)
|
||||
{
|
||||
fprintf(stderr,RED "Pose %u -> %s is corrupted\n" NORMAL,poseID,posePath);
|
||||
} else
|
||||
{
|
||||
poseDB->pose[poseID].pose=bvhFileLoaded[0];
|
||||
if (bvhFileLoaded.size()>1)
|
||||
{
|
||||
fprintf(stderr,YELLOW "Pose %u -> %s has more than one frames\n" NORMAL,poseID,posePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (poseDB->pose[poseID].pose.size()>0)
|
||||
{
|
||||
fprintf(stderr,"Pose %s has %lu frames with %lu fields each\n",posePath,poseDB->pose[poseID].pose.size(),poseDB->pose[poseID].pose.size());
|
||||
poseDB->pose[poseID].loaded=1;
|
||||
poseDB->pose[poseID].poseCallback=0;
|
||||
snprintf(poseDB->pose[poseID].label,128,"%s",hardcodedPoseName[poseID]);
|
||||
poseDB->numberOfLoadedPoses +=1;
|
||||
|
||||
fprintf(stderr,GREEN "Success , loaded a pose with %lu values\n" NORMAL,poseDB->pose[poseID].pose.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Failure\n" NORMAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (poseDB->numberOfLoadedPoses>0);
|
||||
}
|
||||
|
||||
|
||||
int areTwoBVHFramesCloseEnough(std::vector<float> vecA,std::vector<float> vecB,std::vector<char> active,float threshold)
|
||||
{
|
||||
if (vecA.size()!=vecB.size())
|
||||
{
|
||||
fprintf(stderr,"areTwoBVHFramesCloseEnough cannot compare different sized vectors..\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//Always skip X pos, Y pos, Z pos , and rotation
|
||||
for (int i=6; i<vecA.size(); i++)
|
||||
{
|
||||
float difference=abs(vecA[i]-vecB[i]);
|
||||
|
||||
if (active.size()==0)
|
||||
{
|
||||
//If there is no active vector consider all joints as active..
|
||||
if (difference>threshold)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i>=active.size())
|
||||
{
|
||||
fprintf(stderr,RED "Failure comparing bvh frames due to short activeJoint vector\n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (active[i]) && (difference>threshold) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int getBVHFramesMSE(std::vector<float> vecA,std::vector<float> vecB,std::vector<char> active)
|
||||
{
|
||||
if (vecA.size()!=vecB.size())
|
||||
{
|
||||
fprintf(stderr,"areTwoBVHFramesCloseEnough cannot compare different sized vectors..\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int samples=0;
|
||||
float total=0.0;
|
||||
|
||||
//Always skip X pos, Y pos, Z pos , and rotation
|
||||
for (int i=6; i<vecA.size(); i++)
|
||||
{
|
||||
float difference=abs(vecA[i]-vecB[i]);
|
||||
|
||||
if (active.size()==0)
|
||||
{
|
||||
++samples;
|
||||
total += difference * difference;
|
||||
//If there is no active vector consider all joints as active..
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i>=active.size())
|
||||
{
|
||||
fprintf(stderr,RED "Failure comparing bvh frames due to short activeJoint vector\n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
if ( (active[i]) )
|
||||
{
|
||||
++samples;
|
||||
total += difference * difference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total/samples;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int isThisPoseFamiliar(
|
||||
struct PoseDatabase * poseDB,
|
||||
std::vector<float> currentPose,
|
||||
float percentageForDetection,
|
||||
float threshold
|
||||
)
|
||||
{
|
||||
std::vector<char> active;
|
||||
|
||||
if (poseDB!=0)
|
||||
{
|
||||
for (unsigned int poseID=0; poseID<poseDB->numberOfLoadedPoses; poseID++)
|
||||
{
|
||||
|
||||
float thisD = getBVHFramesMSE(currentPose,poseDB->pose[poseID].pose,active);
|
||||
fprintf(stderr,GREEN "Difference from pose %u ( %s = %0.2f ) \n" NORMAL,poseID,hardcodedPoseName[poseID],thisD);
|
||||
|
||||
if ( areTwoBVHFramesCloseEnough(currentPose,poseDB->pose[poseID].pose,active,threshold))
|
||||
{
|
||||
fprintf(stderr,GREEN "Detected pose %u ( %s ) \n" NORMAL,poseID,hardcodedPoseName[poseID]);
|
||||
return poseID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr,YELLOW "Not a familiar pose \n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
/** @file poseRecognition.hpp
|
||||
* @brief MocapNET Pose recognition is implemented here
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is an array of names for the hardcoded poses included in the dataset/poses/ subdirectory
|
||||
* Please remember to update hardcodedPoseNumber, its value should be the number of arguments in this array
|
||||
* If you have arguments 0 - 10 you should set hardcodedPoseNumber to 11
|
||||
*/
|
||||
static const char * hardcodedPoseName[] =
|
||||
{
|
||||
"neutral.bvh",
|
||||
"tpose.bvh", //0
|
||||
"x.bvh",
|
||||
"handsup.bvh",
|
||||
"leftwave.bvh",
|
||||
"rightright.bvh",
|
||||
"leftleft.bvh",
|
||||
"push.bvh",
|
||||
"rightwave.bvh",
|
||||
"rightkick.bvh",
|
||||
"leftkick.bvh",
|
||||
""
|
||||
//hardcodedPoseName should be kept in sync
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief This needs to be kept in sync with hardcodedPoseName */
|
||||
const unsigned int hardcodedPoseNumber=9;
|
||||
|
||||
|
||||
/**
|
||||
* @brief recorded gestures that can be used
|
||||
*/
|
||||
struct RecordedPose
|
||||
{
|
||||
unsigned int lastActivation;
|
||||
float percentageComplete;
|
||||
char loaded;
|
||||
char label[128];
|
||||
std::vector<float> pose;
|
||||
std::vector<char> usedJoints;
|
||||
void * poseCallback;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief gesture detection context, to facilitate gestures
|
||||
*/
|
||||
struct PoseDatabase
|
||||
{
|
||||
unsigned int poseChecksPerformed;
|
||||
unsigned int numberOfLoadedPoses;
|
||||
struct RecordedPose pose[hardcodedPoseNumber];
|
||||
unsigned long previousPoseCheckTimestamp;
|
||||
};
|
||||
|
||||
|
||||
int loadPoses(struct PoseDatabase * poseDB);
|
||||
|
||||
int areTwoBVHFramesCloseEnough(std::vector<float> vecA,std::vector<float> vecB,std::vector<char> active,float threshold);
|
||||
|
||||
|
||||
int isThisPoseFamiliar(
|
||||
struct PoseDatabase * poseDB,
|
||||
std::vector<float> currentPose,
|
||||
float percentageForDetection,
|
||||
float threshold
|
||||
);
|
||||
@@ -0,0 +1,40 @@
|
||||
#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 1
|
||||
|
||||
//Also swap bvh rotations before IK step
|
||||
#define APPLY_BVH_FIX_TO_IK_INPUT 0
|
||||
|
||||
//Test swapped
|
||||
#define SWAP_LEFT_RIGHT_ENSEMBLES 0
|
||||
|
||||
//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,360 @@
|
||||
#include "core.hpp"
|
||||
|
||||
#include "../../../Tensorflow/tf_utils.hpp"
|
||||
|
||||
#include "../config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
//MOCAPNET2 ------------------------------------
|
||||
#include "../../MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../../MocapNETLib2/tools.hpp"
|
||||
#include "../../MocapNETLib2/IO/bvh.hpp"
|
||||
#include "../../MocapNETLib2/IO/jsonRead.hpp"
|
||||
#include "../../MocapNETLib2/IO/conversions.hpp"
|
||||
//----------------------------------------------
|
||||
#include "../../MocapNETLib2/remoteExecution.hpp"
|
||||
//----------------------------------------------
|
||||
#include "../../MocapNETLib2/solutionParts/body.hpp"
|
||||
#include "../../MocapNETLib2/solutionParts/upperBody.hpp"
|
||||
#include "../../MocapNETLib2/solutionParts/lowerBody.hpp"
|
||||
//----------------------------------------------
|
||||
#include "../../MocapNETLib2/core/singleThreaded.hpp"
|
||||
#include "../../MocapNETLib2/core/multiThreaded.hpp"
|
||||
//----------------------------------------------
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
float undoOrientationTrickForBackOrientation(float orientation)
|
||||
{
|
||||
if (orientation==180)
|
||||
{
|
||||
orientation=0;
|
||||
}
|
||||
else if (orientation<0)
|
||||
{
|
||||
orientation=180-orientation;
|
||||
}
|
||||
else
|
||||
{
|
||||
orientation=180-orientation;
|
||||
}
|
||||
return orientation;
|
||||
}
|
||||
|
||||
|
||||
int getMocapNETOrientationFromAngle(float direction)
|
||||
{
|
||||
float orientation = direction;
|
||||
|
||||
if ( (FRONT_MIN_ORIENTATION<=orientation) && (orientation<=FRONT_MAX_ORIENTATION) )
|
||||
{
|
||||
return MOCAPNET_ORIENTATION_FRONT;
|
||||
}
|
||||
else if ( (RIGHT_MIN_ORIENTATION<=orientation) && (orientation<=RIGHT_MAX_ORIENTATION) )
|
||||
{
|
||||
// To visualy inspect these orienteations use :
|
||||
// ./BVHGUI2 --from dataset/headerWithHeadAndOneMotion.bvh --set 4 135
|
||||
// ./BVHGUI2 --from dataset/headerWithHeadAndOneMotion.bvh --set 4 45
|
||||
#if SWAP_LEFT_RIGHT_ENSEMBLES
|
||||
fprintf(stderr,YELLOW "Swapped 45<=range<=135 to left ensemble\n" NORMAL);
|
||||
return MOCAPNET_ORIENTATION_LEFT;
|
||||
#else
|
||||
return MOCAPNET_ORIENTATION_RIGHT;
|
||||
#endif
|
||||
}
|
||||
else if ( (LEFT_MIN_ORIENTATION<=orientation) && (orientation<=LEFT_MAX_ORIENTATION) )
|
||||
{
|
||||
// To visualy inspect these orienteations use :
|
||||
// ./BVHGUI2 --from dataset/headerWithHeadAndOneMotion.bvh --set 4 -135
|
||||
// ./BVHGUI2 --from dataset/headerWithHeadAndOneMotion.bvh --set 4 -45
|
||||
#if SWAP_LEFT_RIGHT_ENSEMBLES
|
||||
fprintf(stderr,YELLOW "Swapped -135<=range<=-45 to right ensemble\n" NORMAL);
|
||||
return MOCAPNET_ORIENTATION_RIGHT;
|
||||
#else
|
||||
return MOCAPNET_ORIENTATION_LEFT;
|
||||
#endif
|
||||
}
|
||||
else if ( (BACK_ALT_MIN_ORIENTATION<=orientation) && (orientation<=BACK_ALT_MAX_ORIENTATION) )
|
||||
{
|
||||
return MOCAPNET_ORIENTATION_BACK;
|
||||
}
|
||||
else if ( (BACK_MIN_ORIENTATION<=orientation) && (orientation<=BACK_MAX_ORIENTATION) )
|
||||
{
|
||||
return MOCAPNET_ORIENTATION_BACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "[Unhandled orientation]\n" NORMAL);
|
||||
fprintf(stderr,"This probably means difficult input\n");
|
||||
return MOCAPNET_ORIENTATION_BACK;
|
||||
}
|
||||
fprintf(stderr,RED "Empty Direction Vector\n" NORMAL);
|
||||
return MOCAPNET_ORIENTATION_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int getMocapNETOrientationFromOutputVector(std::vector<float> direction)
|
||||
{
|
||||
if (direction.size()>0)
|
||||
{
|
||||
return getMocapNETOrientationFromAngle(direction[0]);
|
||||
}
|
||||
fprintf(stderr,RED "Empty Direction Vector\n" NORMAL);
|
||||
return MOCAPNET_ORIENTATION_NONE;
|
||||
}
|
||||
|
||||
|
||||
int getMocapNETOrientationFromProbabilities(float frontProb,float backProb,float leftProb,float rightProb)
|
||||
{
|
||||
if ((frontProb>backProb) && (frontProb>leftProb) && (frontProb>rightProb))
|
||||
{
|
||||
return MOCAPNET_ORIENTATION_FRONT;
|
||||
}
|
||||
else if ((backProb>frontProb) && (backProb>leftProb) && (backProb>rightProb))
|
||||
{
|
||||
return MOCAPNET_ORIENTATION_BACK;
|
||||
}
|
||||
else if ((leftProb>frontProb) && (leftProb>backProb) && (leftProb>rightProb))
|
||||
{
|
||||
return MOCAPNET_ORIENTATION_LEFT;
|
||||
}
|
||||
else if ((rightProb>frontProb) && (rightProb>backProb) && (rightProb>leftProb))
|
||||
{
|
||||
return MOCAPNET_ORIENTATION_RIGHT;
|
||||
}
|
||||
|
||||
fprintf(stderr,RED "Inconclusive Direction Classification\n" NORMAL);
|
||||
return MOCAPNET_ORIENTATION_NONE;
|
||||
}
|
||||
|
||||
|
||||
std::vector<float> MNET3Classes(struct MocapNET2SolutionPart * mnet,std::vector<float> mnetInput,int orientation)
|
||||
{
|
||||
std::vector<float> result;
|
||||
|
||||
if (orientation!=MOCAPNET_ORIENTATION_NONE)
|
||||
{
|
||||
fprintf(stderr,NORMAL "Orientation is : %d " NORMAL,orientation );
|
||||
//===========================================================
|
||||
if ( orientation==MOCAPNET_ORIENTATION_BACK )
|
||||
{
|
||||
//Back ----------------------------------------------=
|
||||
fprintf(stderr,"Back\n");
|
||||
result = predictTensorflow(&mnet->models[2],mnetInput);
|
||||
if (result.size()>4)
|
||||
{
|
||||
result[4]=undoOrientationTrickForBackOrientation(result[4]);
|
||||
}
|
||||
}
|
||||
else
|
||||
//===========================================================
|
||||
{
|
||||
//Front ----------------------------------------------
|
||||
fprintf(stderr,"Front\n");
|
||||
result = predictTensorflow(&mnet->models[1],mnetInput);
|
||||
}
|
||||
//===========================================================
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<float> MNET5Classes(struct MocapNET2SolutionPart * mnet,std::vector<float> mnetInput,int orientation,int targetHasOrientationTrick)
|
||||
{
|
||||
std::vector<float> result;
|
||||
int targetModel=0;
|
||||
|
||||
if (orientation!=MOCAPNET_ORIENTATION_NONE)
|
||||
{
|
||||
fprintf(stderr, "%s ",mnet->partName);
|
||||
switch (orientation)
|
||||
{
|
||||
//===========================================================
|
||||
case MOCAPNET_ORIENTATION_FRONT:
|
||||
fprintf(stderr,GREEN "Front " NORMAL);
|
||||
targetModel=1;
|
||||
if (mnet->loadedModels==4)
|
||||
{
|
||||
targetModel-=1;
|
||||
}
|
||||
result = predictTensorflow(&mnet->models[targetModel],mnetInput);
|
||||
|
||||
/*
|
||||
if ( (targetHasOrientationTrick) && (result.size()>4) )
|
||||
{
|
||||
fprintf(stderr,"Orientation changed from %0.2f ",result[4]);
|
||||
result[4]=-1.0 * result[4];
|
||||
fprintf(stderr,"to %0.2f",result[4]);
|
||||
}
|
||||
*/
|
||||
break;
|
||||
//===========================================================
|
||||
case MOCAPNET_ORIENTATION_BACK:
|
||||
fprintf(stderr,GREEN "Back " NORMAL);
|
||||
targetModel=2;
|
||||
if (mnet->loadedModels==4)
|
||||
{
|
||||
targetModel-=1;
|
||||
}
|
||||
result = predictTensorflow(&mnet->models[targetModel],mnetInput);
|
||||
|
||||
if ( (targetHasOrientationTrick) && (result.size()>4) )
|
||||
{
|
||||
fprintf(stderr,"Orientation changed from %0.2f ",result[4]);
|
||||
result[4]=undoOrientationTrickForBackOrientation(result[4]);
|
||||
//result[4]-=180.0;
|
||||
fprintf(stderr,"to %0.2f",result[4]);
|
||||
}
|
||||
break;
|
||||
//===========================================================
|
||||
case MOCAPNET_ORIENTATION_LEFT:
|
||||
fprintf(stderr,GREEN "Left " NORMAL);
|
||||
targetModel=3;
|
||||
if (mnet->loadedModels==4)
|
||||
{
|
||||
targetModel-=1;
|
||||
}
|
||||
result = predictTensorflow(&mnet->models[targetModel],mnetInput);
|
||||
|
||||
if ( (targetHasOrientationTrick) && (result.size()>4) )
|
||||
{
|
||||
fprintf(stderr,"Orientation changed from %0.2f ",result[4]);
|
||||
result[4]+=90.0;
|
||||
fprintf(stderr,"to %0.2f",result[4]);
|
||||
}
|
||||
break;
|
||||
//===========================================================
|
||||
case MOCAPNET_ORIENTATION_RIGHT:
|
||||
fprintf(stderr,GREEN "Right " NORMAL);
|
||||
targetModel=4;
|
||||
if (mnet->loadedModels==4)
|
||||
{
|
||||
targetModel-=1;
|
||||
}
|
||||
result = predictTensorflow(&mnet->models[targetModel],mnetInput);
|
||||
|
||||
if ( (targetHasOrientationTrick) && (result.size()>4) )
|
||||
{
|
||||
fprintf(stderr,"Orientation changed from %0.2f ",result[4]);
|
||||
result[4]+=-90.0;
|
||||
fprintf(stderr,"to %0.2f",result[4]);
|
||||
}
|
||||
break;
|
||||
//===========================================================
|
||||
default :
|
||||
fprintf(stderr,RED "Unhandled orientation, using front as a last resort \n" NORMAL);
|
||||
result = predictTensorflow(&mnet->models[1],mnetInput);
|
||||
break;
|
||||
//===========================================================
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,NORMAL "5Class Direction is not defined\n" NORMAL );
|
||||
}
|
||||
|
||||
fprintf(stderr,"\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int localOrientationExtraction(struct MocapNET2SolutionPart * mnet,std::vector<float> mnetInput)
|
||||
{
|
||||
if (mnet->loadedModels!=5)
|
||||
{
|
||||
fprintf(stderr,YELLOW "%s does not have an orientation classifier..\n" NORMAL, mnet->partName);
|
||||
return MOCAPNET_ORIENTATION_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,GREEN "%s has an orientation classifier..\n" NORMAL, mnet->partName);
|
||||
}
|
||||
|
||||
std::vector<float> direction = predictTensorflow(&mnet->models[0],mnetInput);
|
||||
|
||||
if (direction.size()>=4)
|
||||
{
|
||||
fprintf(stderr,NORMAL "Orientation : Front(%0.2f)/Back(%0.2f)/Left(%0.2f)/Right(%0.2f)\n" NORMAL,direction[0],direction[1],direction[2],direction[3]);
|
||||
//Output of each Neural Network is -45.0 to 0.0 to 45.0
|
||||
//We need to correct it ..
|
||||
|
||||
//Apply smoothing to probabilities !
|
||||
direction[0] = filter(&mnet->directionSignals[0],direction[0]);
|
||||
direction[1] = filter(&mnet->directionSignals[1],direction[1]);
|
||||
direction[2] = filter(&mnet->directionSignals[2],direction[2]);
|
||||
direction[3] = filter(&mnet->directionSignals[3],direction[3]);
|
||||
|
||||
//Cut negative values..
|
||||
if (direction[0]<0.0) { direction[0]=0.0; }
|
||||
if (direction[1]<0.0) { direction[1]=0.0; }
|
||||
if (direction[2]<0.0) { direction[2]=0.0; }
|
||||
if (direction[3]<0.0) { direction[3]=0.0; }
|
||||
|
||||
mnet->hasOrientationScan=1;
|
||||
mnet->orientationClassifications[0]=direction[0];
|
||||
mnet->orientationClassifications[1]=direction[1];
|
||||
mnet->orientationClassifications[2]=direction[2];
|
||||
mnet->orientationClassifications[3]=direction[3];
|
||||
|
||||
//int orientation = getMocapNETOrientationFromOutputVector(direction);
|
||||
return getMocapNETOrientationFromProbabilities(direction[0],direction[1],direction[2],direction[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "No Orientation Received ( direction vector -> %lu elements ) ..\n" NORMAL,direction.size());
|
||||
}
|
||||
return MOCAPNET_ORIENTATION_NONE;
|
||||
}
|
||||
|
||||
|
||||
std::vector<float> localExecution(struct MocapNET2SolutionPart * mnet,std::vector<float> mnetInput,int orientation,int targetHasOrientationTrick)
|
||||
{
|
||||
std::vector<float> result;
|
||||
|
||||
|
||||
|
||||
//Don't run empty data-------------------------------------------------
|
||||
unsigned int emptyInputElements=0;
|
||||
for (unsigned int i=0; i<mnetInput.size(); i++)
|
||||
{
|
||||
if (mnetInput[i]==0.0) { ++emptyInputElements; }
|
||||
}
|
||||
|
||||
if ( (mnetInput.size()==0) || (emptyInputElements == mnetInput.size()) )
|
||||
{
|
||||
fprintf(stderr,"Won't execute dead input..\n");
|
||||
return result;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
if (orientation!=MOCAPNET_ORIENTATION_NONE)
|
||||
{
|
||||
switch(mnet->mode)
|
||||
{
|
||||
case 3:
|
||||
result=MNET3Classes(mnet,mnetInput,orientation);
|
||||
break;
|
||||
case 5:
|
||||
result=MNET5Classes(mnet,mnetInput,orientation,targetHasOrientationTrick);
|
||||
break;
|
||||
//-----------------------------------------------------------
|
||||
default:
|
||||
fprintf(stderr,RED "MocapNET: Incorrect Mode %u for part %s ..\n" NORMAL,mnet->mode,mnet->partName);
|
||||
break;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Unable to predict pose orientation..\n" NORMAL);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../../MocapNETLib2/mocapnet2.hpp"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Given an orientation angle this function can decide on which orientation class it belong to corresponding to the MOCAPNET_Orientation enum
|
||||
* @param Angle in degrees
|
||||
* @retval MOCAPNET_Orientation enumeration value
|
||||
*/
|
||||
int getMocapNETOrientationFromAngle(float direction);
|
||||
|
||||
int getMocapNETOrientationFromOutputVector(std::vector<float> direction);
|
||||
|
||||
|
||||
int localOrientationExtraction(struct MocapNET2SolutionPart * mnet,std::vector<float> mnetInput);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief An internal function that handles local execution of a part of the final solution
|
||||
* @param Pointer to a valid and populated MocapNET2SolutionPart instance
|
||||
* @param The input to this MocapNET solution part
|
||||
* @param Orientation extracted from the localOrientationExtraction call
|
||||
* @param Some ensembles require an orientation change
|
||||
* @retval 1=Success,0=Failure
|
||||
*/
|
||||
std::vector<float> localExecution(
|
||||
struct MocapNET2SolutionPart * mnet,
|
||||
std::vector<float> mnetInput,
|
||||
int orientation,
|
||||
int targetHasOrientationTrick
|
||||
);
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
#include "multiThreaded.hpp"
|
||||
#include "singleThreaded.hpp"
|
||||
#include "core.hpp"
|
||||
|
||||
void * mocapNETWorkerThread(void * arg)
|
||||
{
|
||||
//We are a thread so lets retrieve our variables..
|
||||
struct threadContext * ptr = (struct threadContext *) arg;
|
||||
fprintf(stderr,"MNET Thread-%u: Started..!\n",ptr->threadID);
|
||||
struct mocapNETContext * contextArray = (struct mocapNETContext *) ptr->argumentToPass;
|
||||
struct mocapNETContext * ctx = &contextArray[ptr->threadID];
|
||||
|
||||
struct MocapNET2 * mnet = ctx->mnet;
|
||||
struct skeletonSerialized * input = ctx->input;
|
||||
int doLowerbody = ctx->doLowerbody;
|
||||
int doHands = ctx->doHands;
|
||||
int doFace = ctx->doFace;
|
||||
int doGestureDetection = ctx->doGestureDetection;
|
||||
unsigned int useInverseKinematics = ctx->useInverseKinematics;
|
||||
int doOutputFiltering = ctx->doOutputFiltering;
|
||||
|
||||
std::vector<float> result;
|
||||
|
||||
threadpoolWorkerInitialWait(ptr);
|
||||
|
||||
while (threadpoolWorkerLoopCondition(ptr))
|
||||
{
|
||||
switch (ptr->threadID)
|
||||
{
|
||||
case 0:
|
||||
result = mocapnetUpperBody_evaluateInput(mnet,input);
|
||||
break;
|
||||
//----------------------------------------------------------------
|
||||
case 1:
|
||||
if ( (doLowerbody) && (mnet->lowerBody.loadedModels>0) )
|
||||
{
|
||||
result = mocapnetLowerBody_evaluateInput(mnet,input);
|
||||
}
|
||||
break;
|
||||
//----------------------------------------------------------------
|
||||
case 2:
|
||||
if ( (doHands) && (mnet->leftHand.loadedModels>0) )
|
||||
{
|
||||
//TODO add hands
|
||||
//result = mocapnetLeftHand_evaluateInput(mnet,input);
|
||||
}
|
||||
break;
|
||||
//----------------------------------------------------------------
|
||||
case 3:
|
||||
if ( (doHands) && (mnet->rightHand.loadedModels>0) )
|
||||
{
|
||||
//TODO add hands
|
||||
//result = mocapnetRightHand_evaluateInput(mnet,input);
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
||||
//--------------------------------
|
||||
threadpoolWorkerLoopEnd(ptr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<float> multiThreadedMocapNET(
|
||||
struct MocapNET2 * mnet,
|
||||
struct skeletonSerialized * input,
|
||||
int doLowerbody,
|
||||
int doHands,
|
||||
int doFace,
|
||||
int doGestureDetection,
|
||||
unsigned int useInverseKinematics,
|
||||
int doOutputFiltering
|
||||
)
|
||||
{
|
||||
#if USE_BVH
|
||||
if (mnet->options->doMultiThreadedIK)
|
||||
{
|
||||
struct mocapNETContext ctx[4];
|
||||
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
ctx[i].mnet=mnet;
|
||||
ctx[i].input=input;
|
||||
ctx[i].doLowerbody=doLowerbody;
|
||||
ctx[i].doHands=doHands;
|
||||
ctx[i].doFace=doFace;
|
||||
ctx[i].doGestureDetection=doGestureDetection;
|
||||
ctx[i].useInverseKinematics=useInverseKinematics;
|
||||
ctx[i].doOutputFiltering=doOutputFiltering;
|
||||
}
|
||||
|
||||
int okToRunMTCode=0;
|
||||
if (!mnet->threadPool.initialized)
|
||||
{
|
||||
if (
|
||||
threadpoolCreate(
|
||||
&mnet->threadPool,
|
||||
4,
|
||||
(void*) mocapNETWorkerThread,
|
||||
ctx
|
||||
)
|
||||
)
|
||||
{
|
||||
fprintf(stderr,"MNET2: Survived threadpool creation \n");
|
||||
nanoSleepT(1000*1000);
|
||||
okToRunMTCode=1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
okToRunMTCode=1;
|
||||
}
|
||||
|
||||
|
||||
if (okToRunMTCode)
|
||||
{
|
||||
threadpoolMainThreadPrepareWorkForWorkers(&mnet->threadPool);
|
||||
mocapnetUpperBody_getOrientation(mnet,input);
|
||||
threadpoolMainThreadWaitForWorkersToFinish(&mnet->threadPool);
|
||||
|
||||
std::vector<float> result = gatherResults(
|
||||
mnet,
|
||||
mnet->body.result,
|
||||
mnet->upperBody.result,
|
||||
mnet->lowerBody.result,
|
||||
mnet->leftHand.result,
|
||||
mnet->rightHand.result,
|
||||
mnet->face.result
|
||||
);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//If we have reached this point it means that the multi-threaded code has failed..!
|
||||
//Fallback on single-threaded code
|
||||
return singleThreadedMocapNET(
|
||||
mnet,
|
||||
input,
|
||||
doLowerbody,
|
||||
doHands,
|
||||
doFace,
|
||||
doGestureDetection,
|
||||
useInverseKinematics,
|
||||
doOutputFiltering
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../Tensorflow/tf_utils.hpp"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
//MOCAPNET2 ------------------------------------
|
||||
#include "../../MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../../MocapNETLib2/tools.hpp"
|
||||
#include "../../MocapNETLib2/IO/bvh.hpp"
|
||||
#include "../../MocapNETLib2/IO/jsonRead.hpp"
|
||||
#include "../../MocapNETLib2/IO/conversions.hpp"
|
||||
|
||||
#include "../../MocapNETLib2/remoteExecution.hpp"
|
||||
//----------------------------------------------
|
||||
#include "../../MocapNETLib2/solutionParts/body.hpp"
|
||||
#include "../../MocapNETLib2/solutionParts/upperBody.hpp"
|
||||
#include "../../MocapNETLib2/solutionParts/lowerBody.hpp"
|
||||
|
||||
#if USE_BVH
|
||||
#include "../../../../dependencies/RGBDAcquisition/tools/PThreadWorkerPool/pthreadWorkerPool.h"
|
||||
#endif
|
||||
|
||||
|
||||
struct mocapNETContext
|
||||
{
|
||||
struct MocapNET2 * mnet;
|
||||
struct skeletonSerialized * input;
|
||||
int doLowerbody;
|
||||
int doHands;
|
||||
int doFace;
|
||||
int doGestureDetection;
|
||||
unsigned int useInverseKinematics;
|
||||
int doOutputFiltering;
|
||||
int forceFront;
|
||||
};
|
||||
|
||||
std::vector<float> multiThreadedMocapNET(
|
||||
struct MocapNET2 * mnet,
|
||||
struct skeletonSerialized * input,
|
||||
int doLowerbody,
|
||||
int doHands,
|
||||
int doFace,
|
||||
int doGestureDetection,
|
||||
unsigned int useInverseKinematics,
|
||||
int doOutputFiltering
|
||||
);
|
||||
@@ -0,0 +1,132 @@
|
||||
#include "singleThreaded.hpp"
|
||||
#include "core.hpp"
|
||||
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
|
||||
|
||||
std::vector<float> gatherResults(
|
||||
struct MocapNET2 * mnet,
|
||||
std::vector<float> resultBody,
|
||||
std::vector<float> resultUpperBody,
|
||||
std::vector<float> resultLowerBody,
|
||||
std::vector<float> resultLeftHand,
|
||||
std::vector<float> resultRightHand,
|
||||
std::vector<float> resultFace
|
||||
)
|
||||
{
|
||||
std::vector<float> result;
|
||||
//----------------------------------------------------------------------------------------------
|
||||
for (int i=0; i<MOCAPNET_OUTPUT_NUMBER; i++)
|
||||
{
|
||||
result.push_back(0.0);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// This is the place where we gather the various parts of the solution we have retrieved and
|
||||
// gather them to populate the final BVH armature, we only gather from sources that have been
|
||||
// loaded, if a part of the body is not important in this instance it will be considered
|
||||
// to be the default..
|
||||
//----------------------------------------------------------------------------------------------
|
||||
if (mnet->body.loadedModels>0)
|
||||
{
|
||||
mocapnetBody_fillResultVector(result,resultBody);
|
||||
}
|
||||
|
||||
if (mnet->upperBody.loadedModels>0)
|
||||
{
|
||||
mocapnetUpperBody_fillResultVector(result,resultUpperBody);
|
||||
}
|
||||
|
||||
if (mnet->lowerBody.loadedModels>0)
|
||||
{
|
||||
mocapnetLowerBody_fillResultVector(result,resultLowerBody);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::vector<float> singleThreadedMocapNET(
|
||||
struct MocapNET2 * mnet,
|
||||
struct skeletonSerialized * input,
|
||||
int doLowerbody,
|
||||
int doHands,
|
||||
int doFace,
|
||||
int doGestureDetection,
|
||||
unsigned int useInverseKinematics,
|
||||
int doOutputFiltering
|
||||
)
|
||||
{
|
||||
std::vector<float> resultBody,resultLowerBody,resultUpperBody,resultLeftHand,resultRightHand,resultFace;
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//resultBody = mocapnetBody_evaluateInput(mnet,input);
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
mocapnetUpperBody_getOrientation(mnet,input);
|
||||
resultUpperBody = mocapnetUpperBody_evaluateInput(mnet,input);
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if ( (doLowerbody) && (mnet->lowerBody.loadedModels>0) )
|
||||
{
|
||||
resultLowerBody = mocapnetLowerBody_evaluateInput(mnet,input);
|
||||
}
|
||||
else
|
||||
{
|
||||
mnet->lowerBody.NSDM.clear();
|
||||
}
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if ( (doHands) && (mnet->leftHand.loadedModels>0) )
|
||||
{
|
||||
//Not implemented..
|
||||
//resultLeftHand = mocapnetLeftHand_evaluateInput(mnet,input);
|
||||
}
|
||||
else
|
||||
{
|
||||
mnet->rightHand.NSDM.clear();
|
||||
}
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if ( (doHands) && (mnet->rightHand.loadedModels>0) )
|
||||
{
|
||||
//Not implemented..
|
||||
//resultRightHand = mocapnetRightHand_evaluateInput(mnet,input);
|
||||
}
|
||||
else
|
||||
{
|
||||
mnet->leftHand.NSDM.clear();
|
||||
}
|
||||
|
||||
if ( (doFace) && (mnet->face.loadedModels>0) )
|
||||
{
|
||||
//Not implemented..
|
||||
//resultFace = mocapnetFace_evaluateInput(mnet,input);
|
||||
}
|
||||
else
|
||||
{
|
||||
mnet->face.NSDM.clear();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
std::vector<float> result = gatherResults(
|
||||
mnet,
|
||||
resultBody,
|
||||
resultUpperBody,
|
||||
resultLowerBody,
|
||||
resultLeftHand,
|
||||
resultRightHand,
|
||||
resultFace
|
||||
);
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../Tensorflow/tf_utils.hpp"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
//MOCAPNET2 ------------------------------------
|
||||
#include "../../MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../../MocapNETLib2/tools.hpp"
|
||||
#include "../../MocapNETLib2/IO/bvh.hpp"
|
||||
#include "../../MocapNETLib2/IO/jsonRead.hpp"
|
||||
#include "../../MocapNETLib2/IO/conversions.hpp"
|
||||
|
||||
#include "../../MocapNETLib2/remoteExecution.hpp"
|
||||
//----------------------------------------------
|
||||
#include "../../MocapNETLib2/solutionParts/body.hpp"
|
||||
#include "../../MocapNETLib2/solutionParts/upperBody.hpp"
|
||||
#include "../../MocapNETLib2/solutionParts/lowerBody.hpp"
|
||||
|
||||
std::vector<float> gatherResults(
|
||||
struct MocapNET2 * mnet,
|
||||
std::vector<float> resultBody,
|
||||
std::vector<float> resultUpperBody,
|
||||
std::vector<float> resultLowerBody,
|
||||
std::vector<float> resultLeftHand,
|
||||
std::vector<float> resultRightHand,
|
||||
std::vector<float> resultFace
|
||||
);
|
||||
|
||||
std::vector<float> singleThreadedMocapNET(
|
||||
struct MocapNET2 * mnet,
|
||||
struct skeletonSerialized * input,
|
||||
int doLowerbody,
|
||||
int doHands,
|
||||
int doFace,
|
||||
int doGestureDetection,
|
||||
unsigned int useInverseKinematics,
|
||||
int doOutputFiltering
|
||||
);
|
||||
@@ -0,0 +1,512 @@
|
||||
//MOCAPNET2 ------------------------------------
|
||||
#include "../MocapNETLib2/mocapnet2.hpp"
|
||||
//----------------------------------------------
|
||||
#include "../MocapNETLib2/tools.hpp"
|
||||
#include "../MocapNETLib2/IO/bvh.hpp"
|
||||
#include "../MocapNETLib2/IO/jsonRead.hpp"
|
||||
#include "../MocapNETLib2/IO/conversions.hpp"
|
||||
//----------------------------------------------
|
||||
#include "../MocapNETLib2/remoteExecution.hpp"
|
||||
//----------------------------------------------
|
||||
#include "../MocapNETLib2/core/multiThreaded.hpp"
|
||||
//----------------------------------------------
|
||||
|
||||
#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 registerGestureEventCallbackWithMocapNET(struct MocapNET2 * mnet,void * callback)
|
||||
{
|
||||
fprintf(stderr,GREEN "New Gesture Event Callback registered\n" NORMAL);
|
||||
mnet->newGestureEventCallback=callback;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void requestRealtimePriority()
|
||||
{
|
||||
set_realtime_priority();
|
||||
}
|
||||
|
||||
|
||||
void commonInitialization(struct MocapNET2 * mnet)
|
||||
{
|
||||
mnet->newGestureEventCallback=0;
|
||||
|
||||
|
||||
fprintf(stderr,"MocapNET2 Initializing..\n");
|
||||
|
||||
//The following line will attempt to escalate the priority
|
||||
//to realtime, you probably need to run with sudo otherwise
|
||||
//it will silently fail.
|
||||
set_realtime_priority();
|
||||
|
||||
//Artifacts logic ---------------
|
||||
if (mnet->options!=0)
|
||||
{
|
||||
fprintf(stderr,"Map will be initialized from file %s \n",mnet->options->mapFilePath);
|
||||
initializeArtifactsFromFile(&mnet->artifacts,mnet->options->mapFilePath);
|
||||
}
|
||||
fprintf(stderr," artifacts ok\n");
|
||||
//---------------------------------
|
||||
|
||||
//Reset pose history..
|
||||
mnet->gesturesMasterSwitch=mnet->options->doGestureDetection;
|
||||
mnet->poseHistoryStorage.maxPoseHistory=150;
|
||||
mnet->poseHistoryStorage.history.clear();
|
||||
mnet->framesReceived=0;
|
||||
|
||||
//Inverse Kinematics defaults
|
||||
mnet->learningRate=0.01;
|
||||
mnet->iterations=5;
|
||||
mnet->epochs=30;
|
||||
mnet->spring = 20;
|
||||
|
||||
mnet->upperBody.perform2DAlignmentBeforeEvaluation=0;
|
||||
mnet->lowerBody.perform2DAlignmentBeforeEvaluation=0;
|
||||
//--------------------------------------------------
|
||||
mnet->leftHand.perform2DAlignmentBeforeEvaluation=1;
|
||||
mnet->rightHand.perform2DAlignmentBeforeEvaluation=1;
|
||||
|
||||
snprintf(mnet->body.partName,64,"Whole Body");
|
||||
snprintf(mnet->upperBody.partName,64,"Upper Body");
|
||||
snprintf(mnet->lowerBody.partName,64,"Lower Body");
|
||||
snprintf(mnet->leftHand.partName,64,"Left Hand");
|
||||
snprintf(mnet->rightHand.partName,64,"Right Hand");
|
||||
|
||||
if (mnet->gesturesMasterSwitch)
|
||||
{
|
||||
if (!loadGestures(&mnet->recognizedGestures))
|
||||
{
|
||||
fprintf(stderr,RED "Failed to read recognized Gestures\n" NORMAL);
|
||||
fprintf(stderr,RED "This is not fatal, but gestures/poses will be deactivated..\n" NORMAL);
|
||||
mnet->gesturesMasterSwitch=0;
|
||||
}
|
||||
|
||||
if (!loadPoses(&mnet->recognizedPoses))
|
||||
{
|
||||
fprintf(stderr,RED "Failed to read recognized Poses\n" NORMAL);
|
||||
fprintf(stderr,RED "This is not fatal, but poses/gestures will be deactivated..\n" NORMAL);
|
||||
mnet->gesturesMasterSwitch=0;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr,"Initializing output filters : ");
|
||||
float filterCutoff = 5.0;
|
||||
float approximateFramerate = mnet->options->inputFramerate;
|
||||
//---------------------------------------------------
|
||||
//initButterWorth(&mnet->directionSignal,approximateFramerate,filterCutoff);
|
||||
|
||||
for (int i=0; i<MOCAPNET_ORIENTATION_NUMBER; i++ )
|
||||
{
|
||||
fprintf(stderr,".");
|
||||
initButterWorth(&mnet->upperBody.directionSignals[i],approximateFramerate,filterCutoff);
|
||||
}
|
||||
|
||||
//XYZ are smoother
|
||||
for (int i=0; i<3; i++ )
|
||||
{
|
||||
fprintf(stderr,".");
|
||||
initButterWorth(&mnet->outputSignals[i],approximateFramerate*2,filterCutoff);
|
||||
}
|
||||
//hip rotations are large and smoother
|
||||
for (int i=3; i<6; i++ )
|
||||
{
|
||||
fprintf(stderr,".");
|
||||
initButterWorth(&mnet->outputSignals[i],approximateFramerate*2,filterCutoff);
|
||||
}
|
||||
|
||||
for (int i=3; i<MOCAPNET_OUTPUT_NUMBER; i++ )
|
||||
{
|
||||
fprintf(stderr,".");
|
||||
initButterWorth(&mnet->outputSignals[i],approximateFramerate,filterCutoff);
|
||||
}
|
||||
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
|
||||
int loadMocapNET2(struct MocapNET2 * mnet, const char * description)
|
||||
{
|
||||
commonInitialization(mnet);
|
||||
|
||||
int result = 0;
|
||||
int target = 0;
|
||||
|
||||
float qualitySetting = mnet->options->quality;
|
||||
int mode = mnet->options->mocapNETMode;
|
||||
unsigned int doUpperBody = mnet->options->doUpperBody;
|
||||
unsigned int doLowerBody = mnet->options->doLowerBody;
|
||||
unsigned int doFace = mnet->options->doFace;
|
||||
unsigned int doHands = mnet->options->doHands;
|
||||
unsigned int forceCPU = mnet->options->useCPUOnlyForMocapNET;
|
||||
|
||||
if (doUpperBody)
|
||||
{
|
||||
result += mocapnetUpperBody_initialize(mnet,description,qualitySetting,mode,forceCPU);
|
||||
++target;
|
||||
}
|
||||
|
||||
if (doLowerBody)
|
||||
{
|
||||
result += mocapnetLowerBody_initialize(mnet,description,qualitySetting,mode,forceCPU);
|
||||
++target;
|
||||
}
|
||||
|
||||
if (doHands)
|
||||
{
|
||||
//TODO add hands
|
||||
//result += mocapnetRightHand_initialize(mnet,description,qualitySetting,mode,forceCPU);
|
||||
//result += mocapnetLeftHand_initialize(mnet,description,qualitySetting,mode,forceCPU);
|
||||
//target += 2;
|
||||
}
|
||||
|
||||
//doFace
|
||||
|
||||
if (target==0)
|
||||
{
|
||||
fprintf(stderr,RED "loadMocapNET2: No body pose estimation functionality was selected..\n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (result==target);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int initializeMocapNET2InputAssociation(struct MocapNET2 * mnet,struct skeletonSerialized * input,int doLowerbody,int doHands,int doFace)
|
||||
{
|
||||
int results=0;
|
||||
int attempts=0;
|
||||
|
||||
//==============================================
|
||||
|
||||
fprintf(stderr,"Doing body associations..\n");
|
||||
results+=mocapnetBody_initializeAssociations(mnet,input);
|
||||
++attempts;
|
||||
|
||||
fprintf(stderr,"Doing upper body associations..\n");
|
||||
results+=mocapnetUpperBody_initializeAssociations(mnet,input);
|
||||
++attempts;
|
||||
|
||||
//if (doLowerbody) // always do lowerbody..
|
||||
{
|
||||
fprintf(stderr,"Doing lower body associations..\n");
|
||||
results+=mocapnetLowerBody_initializeAssociations(mnet,input);
|
||||
++attempts;
|
||||
}
|
||||
|
||||
if (doHands)
|
||||
{
|
||||
//TODO add hands
|
||||
//fprintf(stderr,"Doing lhand associations..\n");
|
||||
//results+= mocapnetLeftHand_initializeAssociations(mnet,input);
|
||||
//++attempts;
|
||||
|
||||
//fprintf(stderr,"Doing rhand associations..\n");
|
||||
//results+= mocapnetRightHand_initializeAssociations(mnet,input);
|
||||
//++attempts;
|
||||
}
|
||||
|
||||
//This message is confusing and removed - https://github.com/FORTH-ModelBasedTracker/MocapNET/issues/31
|
||||
//fprintf(stderr,"TODO: do face associations..\n");
|
||||
|
||||
//==============================================
|
||||
if (results==attempts)
|
||||
{
|
||||
mnet->indexesPopulated=1;
|
||||
}
|
||||
|
||||
return (results==attempts);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::vector<float> runMocapNET2(
|
||||
struct MocapNET2 * mnet,
|
||||
struct skeletonSerialized * input,
|
||||
int doLowerbody,
|
||||
int doHands,
|
||||
int doFace,
|
||||
int doGestureDetection,
|
||||
unsigned int useInverseKinematics,
|
||||
int doOutputFiltering
|
||||
)
|
||||
{
|
||||
|
||||
std::vector<float> emptyResult;
|
||||
|
||||
if (mnet==0)
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Cannot work without initialization\n" NORMAL);
|
||||
return emptyResult;
|
||||
}
|
||||
if (input==0)
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Cannot work without input\n" NORMAL);
|
||||
return emptyResult;
|
||||
}
|
||||
|
||||
//We need indexes to be populated in order to be able to convert input to a usable vector
|
||||
if (!mnet->indexesPopulated)
|
||||
{
|
||||
if (initializeMocapNET2InputAssociation(mnet,input,doLowerbody,doHands,doFace))
|
||||
{
|
||||
fprintf(stderr,GREEN "MocapNET adapted to source of input\n" NORMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Could not adapt to particular source of input\n" NORMAL);
|
||||
exit(1);
|
||||
return emptyResult;
|
||||
}
|
||||
}
|
||||
|
||||
++mnet->framesReceived;
|
||||
|
||||
if (input->skeletonHeaderElements != input->skeletonBodyElements)
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Mismatch of input Header/Body element number\n" NORMAL);
|
||||
fprintf(stderr,RED "Check your input source(!)\n" NORMAL);
|
||||
fprintf(stderr,RED "Header suggested %u elements, body has %u elements\n" NORMAL,input->skeletonHeaderElements,input->skeletonBodyElements);
|
||||
|
||||
return emptyResult;
|
||||
}
|
||||
|
||||
fprintf(stderr,GREEN "MocapNET: Received %u elements\n" NORMAL,input->skeletonHeaderElements);
|
||||
|
||||
int useNeuralNetworkToExtractResult = ( (!mnet->options->skipNeuralNetworkIfItIsNotNeeded) || (mnet->framesReceived % mnet->options->maximumNeuralNetworkSkipFrames == 1) );
|
||||
|
||||
std::vector<float> result;
|
||||
|
||||
//We might not want to run the neural network based on our options
|
||||
//If we dont use the neural network we will rely on the inverse kinematics module..!
|
||||
//If we dont want to use the inverse kinematics module then we are forced to use the neural network..
|
||||
if ( (useNeuralNetworkToExtractResult) || (!useInverseKinematics) )
|
||||
{
|
||||
//If user has enabled skeleton Rotation turned on on auto ( auto = 360 ) then the skeleton will be automatically rotated..!
|
||||
//-------------------------------------------------------------
|
||||
char inputHasBeenAltered=0;
|
||||
struct skeletonSerialized pureInput;
|
||||
memcpy(&pureInput,input,sizeof(struct skeletonSerialized));
|
||||
//-----------------------------------
|
||||
if (mnet->options->skeletonRotation==360.0)
|
||||
{
|
||||
inputHasBeenAltered=1;
|
||||
makeSkeletonUpright(input); //Give MocapNET a hand with aligning the skeleton to an easier orientation
|
||||
} else
|
||||
{
|
||||
inputHasBeenAltered=1;
|
||||
affineSkeletonRotation(input,mnet->options->skeletonRotation);
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
|
||||
|
||||
//Run multithreaded mocapNET ( it will fallback to single threaded if multi threading is not enabled through options )
|
||||
long startTimeNeuralNetwork = GetTickCountMicrosecondsMN();
|
||||
//-----------------------------------------------------
|
||||
result = multiThreadedMocapNET(
|
||||
mnet,
|
||||
input,
|
||||
doLowerbody,
|
||||
doHands,
|
||||
doFace,
|
||||
doGestureDetection,
|
||||
useInverseKinematics,
|
||||
doOutputFiltering
|
||||
);
|
||||
//-----------------------------------------------------
|
||||
long endTimeNeuralNetwork = GetTickCountMicrosecondsMN();
|
||||
mnet->neuralNetworkFramerate = convertStartEndTimeFromMicrosecondsToFPS(startTimeNeuralNetwork,endTimeNeuralNetwork);
|
||||
|
||||
if (inputHasBeenAltered)
|
||||
{
|
||||
//If we have altered the input to help the neural network lets restore it for the IK module..!
|
||||
memcpy(input,&pureInput,sizeof(struct skeletonSerialized));
|
||||
}
|
||||
} else
|
||||
{
|
||||
result = mnet->previousSolution;
|
||||
}
|
||||
|
||||
if (result.size()>0)
|
||||
{
|
||||
|
||||
if (useInverseKinematics)
|
||||
{
|
||||
long startTimeIK = GetTickCountMicrosecondsMN();
|
||||
unsigned int springIgnoreChanges=0;
|
||||
result = improveBVHFrameUsingInverseKinematics(
|
||||
mnet->penultimateSolution,
|
||||
mnet->previousSolution,
|
||||
result,
|
||||
mnet->framesReceived,
|
||||
( (doHands) && (mnet->leftHand.loadedModels>0) ),
|
||||
( (doHands) && (mnet->rightHand.loadedModels>0)),
|
||||
doFace,
|
||||
input,
|
||||
mnet->learningRate,
|
||||
mnet->iterations,
|
||||
mnet->epochs,
|
||||
mnet->spring,
|
||||
springIgnoreChanges,
|
||||
mnet->options->doMultiThreadedIK
|
||||
);
|
||||
long endTimeIK = GetTickCountMicrosecondsMN();
|
||||
|
||||
mnet->inverseKinematicsFramerate = convertStartEndTimeFromMicrosecondsToFPS(startTimeIK,endTimeIK);
|
||||
}
|
||||
else
|
||||
{
|
||||
//If we suddenly turn of IK we need to signal this in the framerate..
|
||||
mnet->inverseKinematicsFramerate = 0.0;
|
||||
}
|
||||
|
||||
|
||||
//User wants to force a specific position and rotation
|
||||
//on BVH output
|
||||
if (mnet->options->forceOutputPositionRotation)
|
||||
{
|
||||
fprintf(stderr,YELLOW "forcing output position rotation \n" NORMAL);
|
||||
result[0]=mnet->options->outputPosRot[0];
|
||||
result[1]=mnet->options->outputPosRot[1];
|
||||
result[2]=mnet->options->outputPosRot[2];
|
||||
result[3]=mnet->options->outputPosRot[3];
|
||||
result[4]=mnet->options->outputPosRot[4];
|
||||
result[5]=mnet->options->outputPosRot[5];
|
||||
}
|
||||
|
||||
|
||||
if (doOutputFiltering)
|
||||
{
|
||||
if (result.size()==MOCAPNET_OUTPUT_NUMBER)
|
||||
{
|
||||
for (int i=0; i<result.size(); i++ )
|
||||
{
|
||||
result[i] = filter(&mnet->outputSignals[i],result[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Incorrect number of output elements/Cannot filter output as a result..!\n" NORMAL);
|
||||
fprintf(stderr,RED "Result size = %lu , MocapNET output = %u \n" NORMAL,result.size(),MOCAPNET_OUTPUT_NUMBER);
|
||||
}
|
||||
}
|
||||
|
||||
addToMotionHistory(&mnet->poseHistoryStorage,result);
|
||||
//----------------------------------------------------------------------------------------------
|
||||
if (doGestureDetection)
|
||||
{
|
||||
if (mnet->gesturesMasterSwitch)
|
||||
{
|
||||
|
||||
int gestureDetected=compareHistoryWithKnownGestures(
|
||||
&mnet->recognizedGestures,
|
||||
&mnet->poseHistoryStorage,
|
||||
GESTURE_COMPLETION_PERCENT,//Percentage complete..
|
||||
GESTURE_ANGLE_SENSITIVITY //Angle threshold
|
||||
);
|
||||
if (gestureDetected!=0)
|
||||
{
|
||||
mnet->lastActivatedGesture=gestureDetected;
|
||||
mnet->gestureTimestamp=mnet->recognizedGestures.gestureChecksPerformed;
|
||||
fprintf(stderr,GREEN "Gesture Detection : %u\n" NORMAL,gestureDetected);
|
||||
|
||||
if (mnet->newGestureEventCallback!=0)
|
||||
{ //We have a callback associated..!
|
||||
void ( *DoCallback) (struct MocapNET2 * ,unsigned int)=0 ;
|
||||
DoCallback = (void(*) (struct MocapNET2 * ,unsigned int) ) mnet->newGestureEventCallback;
|
||||
DoCallback(mnet ,gestureDetected-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Check if the pose we see is familiar, based on the ones we know..
|
||||
int poseDetected = isThisPoseFamiliar(
|
||||
&mnet->recognizedPoses,
|
||||
result,
|
||||
GESTURE_COMPLETION_PERCENT,//Percentage complete..
|
||||
34.0 //Angle threshold
|
||||
);
|
||||
if (poseDetected!=0)
|
||||
{
|
||||
if (mnet->lastActivatedPose==poseDetected)
|
||||
{
|
||||
fprintf(stderr,YELLOW "Pose is still on : %u\n" NORMAL,poseDetected);
|
||||
mnet->activePose=0;
|
||||
}
|
||||
else if (mnet->activePose!=poseDetected)
|
||||
{
|
||||
mnet->activePose=poseDetected;
|
||||
mnet->lastActivatedPose=poseDetected;
|
||||
fprintf(stderr,GREEN "Pose Detection : %u\n" NORMAL,poseDetected);
|
||||
if (mnet->newPoseEventCallback!=0)
|
||||
{
|
||||
//We have a callback associated..!
|
||||
void ( *DoCallback) (struct MocapNET2 *,unsigned int)=0 ;
|
||||
DoCallback = (void(*) (struct MocapNET2 *,unsigned int) ) mnet->newPoseEventCallback;
|
||||
DoCallback(mnet,poseDetected-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,YELLOW "Pose Detection but filtered : %u\n" NORMAL,poseDetected);
|
||||
mnet->activePose=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mnet->activePose=0;
|
||||
mnet->lastActivatedPose=0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Gesture Detection is enabled but it failed to initialize..\n" NORMAL);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
mnet->penultimateSolution = mnet->previousSolution;
|
||||
mnet->previousSolution = mnet->currentSolution;
|
||||
mnet->currentSolution = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fprintf(stderr,RED "MocapNET: failed to retrieve a result..\n" NORMAL);
|
||||
//-----------------
|
||||
return emptyResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int unloadMocapNET2(struct MocapNET2 * mnet)
|
||||
{
|
||||
if (mnet->threadPool.initialized)
|
||||
{
|
||||
if (!threadpoolDestroy(&mnet->threadPool))
|
||||
{
|
||||
fprintf(stderr,"Failed deleting IK thread pool\n");
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
mocapnetBody_unload(mnet) &&
|
||||
mocapnetUpperBody_unload(mnet) &&
|
||||
mocapnetLowerBody_unload(mnet)
|
||||
//&& mocapnetRightHand_unload(mnet)
|
||||
//&& mocapnetLeftHand_unload(mnet)
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,123 @@
|
||||
#ifndef _BUTTERWORTH_FILTER_H_INCLUDED
|
||||
#define _BUTTERWORTH_FILTER_H_INCLUDED
|
||||
|
||||
/** @file outputFiltering.hpp
|
||||
* @brief From Wikipedia : The Butterworth filter is a type of signal processing filter designed to have a frequency response as flat as possible in the passband.
|
||||
* It is also referred to as a maximally flat magnitude filter.
|
||||
* It was first described in 1930 by the British engineer and physicist Stephen Butterworth in his paper entitled "On the Theory of Filter Amplifiers"
|
||||
* https://en.wikipedia.org/wiki/Butterworth_filter
|
||||
*
|
||||
* The frequency response of the Butterworth filter is maximally flat (i.e. has no ripples) in the passband and rolls off towards zero in the stopband.
|
||||
* That's why it is used as a post-processing step if you don't disable it from the GUI. It should be noted that this is a relatively new addition to the codebase ( 30 -10-2019 )
|
||||
* the original BMVC 2019 paper ( https://www.youtube.com/watch?v=fH5e-KMBvM0 ) did not have any post processing done..!
|
||||
*
|
||||
* However some sort of filtering had to be added after numerous comments regarding signal noise. And here it is, in a header-only vanilla C compatible version.
|
||||
* Thanks to Stelios Piperakis ( https://github.com/mrsp ) for giving me the initial code implementation that this filter is based on
|
||||
*
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* @brief The complete state of a Butterworth filter instance
|
||||
*/
|
||||
struct ButterWorth
|
||||
{
|
||||
//https://en.wikipedia.org/wiki/Butterworth_filter
|
||||
//https://github.com/mrsp/serow/blob/master/src/butterworthLPF.cpp
|
||||
float unfilteredValue;
|
||||
float filteredValue;
|
||||
//-----------
|
||||
char initialized;
|
||||
//-----------
|
||||
float a;
|
||||
float fx;
|
||||
float fs;
|
||||
float a1;
|
||||
float a2;
|
||||
float b0;
|
||||
float b1;
|
||||
float b2;
|
||||
float ff;
|
||||
float ita;
|
||||
float q;
|
||||
int i;
|
||||
float y_p;
|
||||
float y_pp;
|
||||
float x_p;
|
||||
float x_pp;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize a "sensor" using fsampling/fcutoff values
|
||||
* @param Butterworth filter instance
|
||||
* @param frequency of sampling
|
||||
* @param frequency of cutoff
|
||||
*/
|
||||
static void initButterWorth(struct ButterWorth * sensor,float fsampling,float fcutoff)
|
||||
{
|
||||
sensor->fs = fsampling;
|
||||
sensor->fx = fcutoff;
|
||||
|
||||
sensor->i = 0;
|
||||
sensor->ff = (float) sensor->fx/sensor->fs;
|
||||
sensor->ita = (float) 1.0/tan((float) 3.14159265359 * sensor->ff);
|
||||
sensor->q = 1.41421356237;
|
||||
sensor->b0 = (float) 1.0 / (1.0 + sensor->q*sensor->ita + sensor->ita*sensor->ita);
|
||||
sensor->b1 = 2*sensor->b0;
|
||||
sensor->b2 = sensor->b0;
|
||||
sensor->a1 = 2.0 * (sensor->ita*sensor->ita - 1.0) * sensor->b0;
|
||||
sensor->a2 = -(1.0 - sensor->q*sensor->ita + sensor->ita*sensor->ita) * sensor->b0;
|
||||
sensor->a =(float) (2.0*3.14159265359*sensor->ff)/(2.0*3.14159265359*sensor->ff+1.0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Filter a new incoming value and get the result
|
||||
* @param Butterworth filter instance
|
||||
* @param Unfiltered input value
|
||||
* @retval Filtered output value
|
||||
*/
|
||||
static float filter(struct ButterWorth * sensor,float unfilteredValue)
|
||||
{
|
||||
sensor->unfilteredValue = unfilteredValue;
|
||||
|
||||
float y = sensor->unfilteredValue;
|
||||
float out;
|
||||
if ((sensor->i>2)&&(1))
|
||||
{
|
||||
out = sensor->b0 * y + sensor->b1 * sensor->y_p + sensor->b2* sensor->y_pp + sensor->a1 * sensor->x_p + sensor->a2 * sensor->x_pp;
|
||||
}
|
||||
else
|
||||
{
|
||||
out = sensor->x_p + sensor->a * (y - sensor->x_p);
|
||||
sensor->i=sensor->i+1;
|
||||
}
|
||||
|
||||
sensor->y_pp = sensor->y_p;
|
||||
sensor->y_p = y;
|
||||
sensor->x_pp = sensor->x_p;
|
||||
sensor->x_p = out;
|
||||
|
||||
sensor->filteredValue = out;
|
||||
|
||||
if (!sensor->initialized)
|
||||
{
|
||||
//Do a warmup..
|
||||
//Make sure we dont start from 0
|
||||
|
||||
sensor->initialized=1;
|
||||
for (unsigned int i=0; i<5; i++)
|
||||
{
|
||||
filter(sensor,unfilteredValue);
|
||||
}
|
||||
|
||||
return filter(sensor,unfilteredValue);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "qualityControl.hpp"
|
||||
#include <math.h>
|
||||
|
||||
//./GroundTruthDumper --from dataset/MotionCapture/01/01_02.bvh --selectJoints 1 13 hip eye.r eye.l abdomen chest neck head rshoulder relbow rhand lshoulder lelbow lhand --selectJoints 0 13 hip eye.r eye.l abdomen chest neck head rshoulder relbow rhand lshoulder lelbow lhand --selectJoints 1 14 hip abdomen chest neck rhip rknee rfoot lhip lknee lfoot toe1-2.r toe5-3.r toe1-2.l toe5-3.l --hide2DLocationOfJoints 0 6 abdomen chest toe1-2.r toe5-3.r toe1-2.l toe5-3.l --selectJoints 1 16 rhand finger5-1.r finger5-2.r finger5-3.r finger4-1.r finger4-2.r finger4-3.r finger3-1.r finger3-2.r finger3-3.r finger2-1.r finger2-2.r finger2-3.r rthumb finger1-2.r finger1-3.r --selectJoints 1 16 lhand finger5-1.l finger5-2.l finger5-3.l finger4-1.l finger4-2.l finger4-3.l finger3-1.l finger3-2.l finger3-3.l finger2-1.l finger2-2.l finger2-3.l lthumb finger1-2.l finger1-3.l --occlusions --setPositionRotation 0 0 2000 0 0 0 --csv ./ quality.csv 2d+bvh
|
||||
|
||||
|
||||
//./GroundTruthDumper --from dataset/MotionCapture/02/02_05.bvh --selectJoints 1 13 hip eye.r eye.l abdomen chest neck head rshoulder relbow rhand lshoulder lelbow lhand --selectJoints 0 13 hip eye.r eye.l abdomen chest neck head rshoulder relbow rhand lshoulder lelbow lhand --selectJoints 1 14 hip abdomen chest neck rhip rknee rfoot lhip lknee lfoot toe1-2.r toe5-3.r toe1-2.l toe5-3.l --hide2DLocationOfJoints 0 6 abdomen chest toe1-2.r toe5-3.r toe1-2.l toe5-3.l --selectJoints 1 16 rhand finger5-1.r finger5-2.r finger5-3.r finger4-1.r finger4-2.r finger4-3.r finger3-1.r finger3-2.r finger3-3.r finger2-1.r finger2-2.r finger2-3.r rthumb finger1-2.r finger1-3.r --selectJoints 1 16 lhand finger5-1.l finger5-2.l finger5-3.l finger4-1.l finger4-2.l finger4-3.l finger3-1.l finger3-2.l finger3-3.l finger2-1.l finger2-2.l finger2-3.l lthumb finger1-2.l finger1-3.l --occlusions --offsetPositionRotation 0 800 1500 0 0 0 --csv ./ quality.csv 2d+bvh
|
||||
@@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
#include "remoteExecution.hpp"
|
||||
#include "../../../dependencies/InputParser/InputParser_C.h"
|
||||
|
||||
|
||||
#if USE_NETWORKING
|
||||
#include "../../../dependencies/AmmarServer/src/AmmClient/AmmClient.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define SEND_RECV_BUFFER_SIZE 16000
|
||||
|
||||
char * strstrDoubleNewlineLocal(char * request,unsigned int requestLength,unsigned int * endOfLine)
|
||||
{
|
||||
if (request==0) { return request; }
|
||||
if (requestLength==0) { return request; }
|
||||
if (endOfLine==0) { return request; }
|
||||
|
||||
char * ptrA=request;
|
||||
char * ptrB=request+1;
|
||||
|
||||
char * ptrEnd = request + requestLength;
|
||||
|
||||
//fprintf(stderr,"\strstrDoubleNewline for 13 10 13 10 on a buffer with %u bytes of data : ",requestLength);
|
||||
while (ptrB<ptrEnd)
|
||||
{
|
||||
if ( ( (*ptrA==10) && (*ptrB==10) ) || (*ptrA==0) )
|
||||
{
|
||||
++ptrB;
|
||||
|
||||
*ptrA=0; //Also make null terminated string..
|
||||
*endOfLine = ptrA-request;
|
||||
|
||||
//fprintf(stderr,"done\n");
|
||||
return ptrB;
|
||||
}
|
||||
//fprintf(stderr,"%c(%u) ",*ptrA,*ptrA);
|
||||
++ptrA; ++ptrB;
|
||||
}
|
||||
|
||||
//fprintf(stderr,"not found\n");
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
std::vector<float> remoteExecution(struct MocapNET2 * mnet,const std::vector<float> &mnetInput)
|
||||
{
|
||||
std::vector<float> result;
|
||||
|
||||
#if USE_NETWORKING
|
||||
fprintf(stderr,"remoteExecution :\n");
|
||||
//-----------------------------------------------------
|
||||
char requestBuffer[SEND_RECV_BUFFER_SIZE+1]={0};
|
||||
char part[128]={0};
|
||||
|
||||
snprintf(requestBuffer,SEND_RECV_BUFFER_SIZE,"control.html?skeleton=");
|
||||
for (int i=0; i<mnetInput.size(); i++)
|
||||
{
|
||||
|
||||
if (mnetInput[i]==0) { snprintf(part,128,"0"); } else
|
||||
{ snprintf(part,128,"%0.4f",mnetInput[i]); }
|
||||
//TODO : unsafe strcat
|
||||
strcat(requestBuffer,part);
|
||||
if (i<mnetInput.size()-1)
|
||||
{ strcat(requestBuffer,","); }
|
||||
}
|
||||
|
||||
//fprintf(stderr,"Request is %lu bytes long : %s\n",strlen(requestBuffer),requestBuffer);
|
||||
|
||||
struct AmmClient_Instance * instance = (struct AmmClient_Instance *) mnet->remoteContext;
|
||||
|
||||
char resultBuffer[SEND_RECV_BUFFER_SIZE+1]={0};
|
||||
unsigned int filecontentSize=SEND_RECV_BUFFER_SIZE;
|
||||
|
||||
if (
|
||||
AmmClient_RecvFile(
|
||||
instance,
|
||||
requestBuffer,
|
||||
resultBuffer,
|
||||
&filecontentSize,
|
||||
1,//keepAlive,
|
||||
0// reallyFastImplementation
|
||||
)
|
||||
)
|
||||
{
|
||||
unsigned int startOfData=0;
|
||||
char * onlyResults = strstrDoubleNewlineLocal(resultBuffer,filecontentSize,&startOfData);
|
||||
if (onlyResults==0) {
|
||||
fprintf(stderr,"Couldnt find body.. \n");
|
||||
onlyResults=resultBuffer;
|
||||
}
|
||||
|
||||
//fprintf(stderr,"Got back:\n %s \n\n",resultBuffer);
|
||||
|
||||
struct InputParserC * ipc = InputParser_Create(4096,1);
|
||||
InputParser_SetDelimeter(ipc,0,',');
|
||||
|
||||
if (ipc!=0)
|
||||
{
|
||||
result.clear();
|
||||
//fprintf(stderr,"Disregarding headers we have: %s \n\n",onlyResults);
|
||||
int numberOfArguments = InputParser_SeperateWords(ipc,onlyResults,1);
|
||||
//fprintf(stderr,"Skeleton Arguments : %u\n",numberOfArguments);
|
||||
for (int argument=0; argument<numberOfArguments; argument++) //InputParser_GetNumberOfArguments(ipc)
|
||||
{
|
||||
//fprintf(stderr,"%u - %0.2f \n",argument,InputParser_GetWordFloat(ipc,argument));
|
||||
result.push_back(InputParser_GetWordFloat(ipc,argument));
|
||||
}
|
||||
InputParser_Destroy(ipc);
|
||||
|
||||
fprintf(stderr,"We got back %lu arguments from network\n",result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//-----------------------------------------------------
|
||||
#else
|
||||
fprintf(stderr,"remoteExecution cannot be used without it beeing compiled in.. Please run initialize.sh and opt in for AmmarServer installation\n");
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void * intializeRemoteExecution(const char * ip,unsigned int port,unsigned int socketTimeoutSeconds)
|
||||
{
|
||||
#if USE_NETWORKING
|
||||
return (void *) AmmClient_Initialize(ip,port,socketTimeoutSeconds);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int stopRemoteExecution(void * instance)
|
||||
{
|
||||
#if USE_NETWORKING
|
||||
return AmmClient_Close((struct AmmClient_Instance *) instance);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
/** @file remoteExecution.hpp
|
||||
* @brief This is a deprecated abstraction layer that allowed remote execution of the NeuralNetwork of MocapNET 1 , it is currently not working..
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "mocapnet2.hpp"
|
||||
|
||||
std::vector<float> remoteExecution(struct MocapNET2 * mnet,const std::vector<float> &mnetInput);
|
||||
|
||||
|
||||
void * intializeRemoteExecution(const char * ip,unsigned int port,unsigned int socketTimeoutSeconds);
|
||||
int stopRemoteExecution(void * instance);
|
||||
@@ -0,0 +1,307 @@
|
||||
#include "body.hpp"
|
||||
|
||||
#include "../../MocapNETLib2/config.h"
|
||||
#include "../../MocapNETLib2/IO/conversions.hpp"
|
||||
#include "../../MocapNETLib2/tools.hpp"
|
||||
#include "../../MocapNETLib2/core/core.hpp"
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
int mocapnetBody_initializeAssociations(struct MocapNET2 * mnet, struct skeletonSerialized * input)
|
||||
{
|
||||
return initializeAssociationsForSubsetOfSkeleton(
|
||||
&mnet->bodySelectionIndexesArePopulated,
|
||||
mnet->bodySelectionIndexes,
|
||||
mocapNET_InputLength_WithoutNSDM_body,
|
||||
mocapNET_body,
|
||||
input
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mocapnetBody_initialize(struct MocapNET2 * mnet,const char * filename,float qualitySetting,unsigned int mode,unsigned int forceCPU)
|
||||
{
|
||||
char modelPath[1024]= {0};
|
||||
int result = 0;
|
||||
int modelNumber=0;
|
||||
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case 3:
|
||||
mnet->body.mode=3;
|
||||
fprintf(stderr,RED "Fatal: Mode 3 No longer supported on MocapNET 2 \n" NORMAL);
|
||||
exit(0);
|
||||
break;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
case 5:
|
||||
mnet->body.mode=5;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// Regular 3 Model setup such as the BMVC 2019 Work..
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/categorize_body_all.pb",mode,qualitySetting);
|
||||
if (fileExists(modelPath))
|
||||
{
|
||||
result += loadTensorflowInstance(&mnet->body.models[modelNumber] ,modelPath ,"input_all" ,"result_all/concat",forceCPU);
|
||||
mnet->body.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->body.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->body.modelLimits[modelNumber].minimumYaw1=-360.0;
|
||||
mnet->body.modelLimits[modelNumber].maximumYaw1=360.0;
|
||||
modelNumber+=1;
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,YELLOW "Could not find a pose categorization classifier for Whole Body..\n " NORMAL );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/body_front.pb",mode,qualitySetting);
|
||||
result += loadTensorflowInstance(&mnet->body.models[modelNumber],modelPath,"input_front","result_front/concat",forceCPU);
|
||||
mnet->body.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->body.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->body.modelLimits[modelNumber].minimumYaw1=-45.0;
|
||||
mnet->body.modelLimits[modelNumber].maximumYaw1=45.0;
|
||||
modelNumber+=1;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/body_back.pb",mode,qualitySetting);
|
||||
result += loadTensorflowInstance(&mnet->body.models[modelNumber],modelPath,"input_back","result_back/concat",forceCPU);
|
||||
mnet->body.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->body.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->body.modelLimits[modelNumber].minimumYaw1=135.0;//-90.0;
|
||||
mnet->body.modelLimits[modelNumber].maximumYaw1=225.0;//-270.0;
|
||||
modelNumber+=1;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/body_left.pb",mode,qualitySetting);
|
||||
result += loadTensorflowInstance(&mnet->body.models[modelNumber] ,modelPath ,"input_left" ,"result_left/concat",forceCPU);
|
||||
mnet->body.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->body.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->body.modelLimits[modelNumber].minimumYaw1=-135.0;
|
||||
mnet->body.modelLimits[modelNumber].maximumYaw1=45.0;
|
||||
modelNumber+=1;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/body_right.pb",mode,qualitySetting);//
|
||||
result += loadTensorflowInstance(&mnet->body.models[modelNumber] ,modelPath ,"input_right" ,"result_right/concat",forceCPU);
|
||||
mnet->body.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->body.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->body.modelLimits[modelNumber].minimumYaw1=45.0;
|
||||
mnet->body.modelLimits[modelNumber].maximumYaw1=135.0;
|
||||
modelNumber+=1;
|
||||
|
||||
|
||||
|
||||
if(result==modelNumber) // make this 5
|
||||
{
|
||||
result=1;
|
||||
mnet->body.loadedModels=modelNumber; //make this 5
|
||||
}
|
||||
else
|
||||
{
|
||||
result=0;
|
||||
}
|
||||
break;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
default:
|
||||
fprintf(stderr,RED "You requested a MocapNET configuration that is incorrect ( mode=%u )\n" NORMAL , mode);
|
||||
return 0;
|
||||
break;
|
||||
};
|
||||
|
||||
if (result)
|
||||
{
|
||||
fprintf(stderr,"Caching networks after initialization to be ready for use..\n");
|
||||
std::vector<float> emptyValues;
|
||||
for (int i=0; i<MNET_BODY_IN_NUMBER; i++)
|
||||
{
|
||||
emptyValues.push_back(0.0);
|
||||
}
|
||||
//---------------------------------------------------
|
||||
for (int i=0; i<mnet->body.loadedModels; i++ )
|
||||
{
|
||||
std::vector<float> prediction = predictTensorflow(&mnet->body.models[i],emptyValues);
|
||||
if (prediction.size()>0)
|
||||
{
|
||||
fprintf(stderr, GREEN "Caching model %u (%s) was successful\n" NORMAL ,i,mnet->body.models[i].modelPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Caching model %u (%s) was unsuccessful\n" NORMAL,i,mnet->body.models[i].modelPath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mocapnetBody_unload(struct MocapNET2 * mnet)
|
||||
{
|
||||
unsigned int result=0;
|
||||
for (int i=0; i<mnet->body.loadedModels; i++ )
|
||||
{
|
||||
result+=unloadTensorflow(&mnet->body.models[i]);
|
||||
}
|
||||
|
||||
if (result==mnet->body.loadedModels) { result=1; } else
|
||||
{ result=0; }
|
||||
|
||||
mnet->body.loadedModels=0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<float> mocapnetBody_evaluateInput(struct MocapNET2 * mnet,struct skeletonSerialized * input)
|
||||
{
|
||||
|
||||
|
||||
mnet->body.positionalInput = deriveMocapNET2InputUsingAssociations(
|
||||
mnet,
|
||||
input,
|
||||
&mnet->bodySelectionIndexesArePopulated,
|
||||
mnet->bodySelectionIndexes,
|
||||
mocapNET_InputLength_WithoutNSDM_body,
|
||||
mocapNET_body,
|
||||
0 // Enable to debug input
|
||||
);
|
||||
|
||||
|
||||
mnet->body.NSDM = bodyCreateNDSM(mnet->body.positionalInput,1/*NSDM Positional*/,0/*NSDM Angular */,1 /*Use Normalization*/);
|
||||
mnet->body.neuralNetworkReadyInput.clear();
|
||||
mnet->body.neuralNetworkReadyInput.insert(mnet->body.neuralNetworkReadyInput.end(),mnet->body.positionalInput.begin(), mnet->body.positionalInput.end());
|
||||
mnet->body.neuralNetworkReadyInput.insert(mnet->body.neuralNetworkReadyInput.end(),mnet->body.NSDM.begin(), mnet->body.NSDM.end());
|
||||
//----------------------------------------------------------------------------------------------
|
||||
//The code block above should have done everything needed to make a 749 element vector
|
||||
//If input is not correct then we should stop right here
|
||||
//----------------------------------------------------------------------------------------------
|
||||
if (mnet->body.neuralNetworkReadyInput.size()!=MNET_BODY_IN_NUMBER)
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Incorrect size of MocapNET input .. \n" NORMAL);
|
||||
std::vector<float> emptyResult;
|
||||
return emptyResult;
|
||||
}
|
||||
|
||||
int orientationReceived =localOrientationExtraction(&mnet->body,mnet->body.neuralNetworkReadyInput);
|
||||
if (orientationReceived!=MOCAPNET_ORIENTATION_NONE)
|
||||
{
|
||||
mnet->orientation=orientationReceived;
|
||||
mnet->orientationClassifications[0]= mnet->body.orientationClassifications[0];
|
||||
mnet->orientationClassifications[1]= mnet->body.orientationClassifications[1];
|
||||
mnet->orientationClassifications[2]= mnet->body.orientationClassifications[2];
|
||||
mnet->orientationClassifications[3]= mnet->body.orientationClassifications[3];
|
||||
}
|
||||
//First run the network that can predict the orientation of the skeleton so we will use the correct
|
||||
//network to get the full BVH result from it
|
||||
//----------------------------------------------------------------------------------------------
|
||||
std::vector<float> result = localExecution(
|
||||
&mnet->body,
|
||||
mnet->body.neuralNetworkReadyInput,
|
||||
mnet->orientation,
|
||||
NN_ORIENTATIONS_TRAINED_AROUND_ZERO_AND_REQUIRE_TRICK /*Body Requires orientation trick*/
|
||||
);
|
||||
mnet->body.result = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int mocapnetBody_fillResultVector(std::vector<float> &result ,std::vector<float> resultBody)
|
||||
{
|
||||
if (resultBody.size()==MOCAPNET_BODY_OUTPUT_NUMBER)
|
||||
{ //This is output that targets the old body only armature..!
|
||||
result[MOCAPNET_OUTPUT_HIP_XPOSITION]=resultBody[MOCAPNET_BODY_OUTPUT_HIP_XPOSITION];
|
||||
result[MOCAPNET_OUTPUT_HIP_YPOSITION]=resultBody[MOCAPNET_BODY_OUTPUT_HIP_YPOSITION];
|
||||
result[MOCAPNET_OUTPUT_HIP_ZPOSITION]=resultBody[MOCAPNET_BODY_OUTPUT_HIP_ZPOSITION];
|
||||
result[MOCAPNET_OUTPUT_HIP_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_HIP_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_HIP_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_HIP_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_HIP_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_HIP_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_ABDOMEN_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_ABDOMEN_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_ABDOMEN_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_ABDOMEN_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_ABDOMEN_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_ABDOMEN_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_CHEST_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_CHEST_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_CHEST_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_CHEST_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_CHEST_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_CHEST_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_NECK_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_NECK_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_NECK_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_NECK_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_NECK_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_NECK_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_HEAD_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_HEAD_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_HEAD_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_HEAD_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_HEAD_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_HEAD_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_L_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_EYE_L_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_L_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_EYE_L_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_L_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_EYE_L_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_R_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_EYE_R_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_R_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_EYE_R_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_R_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_EYE_R_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RSHOULDER_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RSHOULDER_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RSHOULDER_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RSHOULDER_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RSHOULDER_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RSHOULDER_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RELBOW_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RELBOW_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RELBOW_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RELBOW_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RELBOW_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RELBOW_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHAND_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RHAND_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHAND_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RHAND_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHAND_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RHAND_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LSHOULDER_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LSHOULDER_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LSHOULDER_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LSHOULDER_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LSHOULDER_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LSHOULDER_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LELBOW_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LELBOW_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LELBOW_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LELBOW_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LELBOW_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LELBOW_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHAND_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LHAND_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHAND_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LHAND_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHAND_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LHAND_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHIP_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RHIP_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHIP_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RHIP_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHIP_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RHIP_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RKNEE_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RKNEE_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RKNEE_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RKNEE_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RKNEE_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RKNEE_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RFOOT_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RFOOT_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RFOOT_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RFOOT_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RFOOT_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_RFOOT_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_R_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE1_2_R_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_R_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE1_2_R_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_R_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE1_2_R_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_R_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE5_3_R_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_R_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE5_3_R_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_R_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE5_3_R_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHIP_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LHIP_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHIP_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LHIP_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHIP_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LHIP_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LKNEE_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LKNEE_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LKNEE_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LKNEE_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LKNEE_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LKNEE_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LFOOT_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LFOOT_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LFOOT_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LFOOT_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LFOOT_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_LFOOT_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_L_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE1_2_L_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_L_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE1_2_L_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_L_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE1_2_L_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_L_ZROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE5_3_L_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_L_XROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE5_3_L_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_L_YROTATION]=resultBody[MOCAPNET_BODY_OUTPUT_TOE5_3_L_YROTATION];
|
||||
return 1;
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,YELLOW "MocapNET: Execution yielded %lu items ( expected %u ) for body don't know what to do with them.. \n" NORMAL,resultBody.size(),MOCAPNET_BODY_OUTPUT_NUMBER);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
/** @file body.hpp
|
||||
* @brief Code that handles regressing the whole body using the legacy ( MocapNET 1 ) engine that encoded the whole body at once..
|
||||
* This is no longer used since the body has been split in upper and lower body to more effectively treat occlusions
|
||||
* however the code remains here as documentation and for backwards compatibility
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
|
||||
/**
|
||||
* @brief An array with string labels for what each element of an input should be after concatenating uncompressed and compressed input.
|
||||
* Use ./GroundTruthDumper --from dataset/headerWithHeadAndOneMotion.bvh --printc
|
||||
* to extract this automatically
|
||||
*/
|
||||
/*
|
||||
enum MOCAPNET_BODY_Output_Joints
|
||||
{
|
||||
MOCAPNET_BODY_OUTPUT_HIP_XPOSITION=0, //0
|
||||
MOCAPNET_BODY_OUTPUT_HIP_YPOSITION, //1
|
||||
MOCAPNET_BODY_OUTPUT_HIP_ZPOSITION, //2
|
||||
MOCAPNET_BODY_OUTPUT_HIP_ZROTATION, //3
|
||||
MOCAPNET_BODY_OUTPUT_HIP_YROTATION, //4
|
||||
MOCAPNET_BODY_OUTPUT_HIP_XROTATION, //5
|
||||
MOCAPNET_BODY_OUTPUT_ABDOMEN_ZROTATION, //6
|
||||
MOCAPNET_BODY_OUTPUT_ABDOMEN_XROTATION, //7
|
||||
MOCAPNET_BODY_OUTPUT_ABDOMEN_YROTATION, //8
|
||||
MOCAPNET_BODY_OUTPUT_CHEST_ZROTATION, //9
|
||||
MOCAPNET_BODY_OUTPUT_CHEST_XROTATION, //10
|
||||
MOCAPNET_BODY_OUTPUT_CHEST_YROTATION, //11
|
||||
MOCAPNET_BODY_OUTPUT_NECK_ZROTATION, //12
|
||||
MOCAPNET_BODY_OUTPUT_NECK_XROTATION, //13
|
||||
MOCAPNET_BODY_OUTPUT_NECK_YROTATION, //14
|
||||
MOCAPNET_BODY_OUTPUT_HEAD_ZROTATION, //15
|
||||
MOCAPNET_BODY_OUTPUT_HEAD_XROTATION, //16
|
||||
MOCAPNET_BODY_OUTPUT_HEAD_YROTATION, //17
|
||||
MOCAPNET_BODY_OUTPUT_EYE_L_ZROTATION, //18
|
||||
MOCAPNET_BODY_OUTPUT_EYE_L_XROTATION, //19
|
||||
MOCAPNET_BODY_OUTPUT_EYE_L_YROTATION, //20
|
||||
MOCAPNET_BODY_OUTPUT_EYE_R_ZROTATION, //21
|
||||
MOCAPNET_BODY_OUTPUT_EYE_R_XROTATION, //22
|
||||
MOCAPNET_BODY_OUTPUT_EYE_R_YROTATION, //23
|
||||
MOCAPNET_BODY_OUTPUT_RSHOULDER_ZROTATION,//24
|
||||
MOCAPNET_BODY_OUTPUT_RSHOULDER_XROTATION,//25
|
||||
MOCAPNET_BODY_OUTPUT_RSHOULDER_YROTATION,//26
|
||||
MOCAPNET_BODY_OUTPUT_RELBOW_ZROTATION, //27
|
||||
MOCAPNET_BODY_OUTPUT_RELBOW_XROTATION, //28
|
||||
MOCAPNET_BODY_OUTPUT_RELBOW_YROTATION, //29
|
||||
MOCAPNET_BODY_OUTPUT_RHAND_ZROTATION, //30
|
||||
MOCAPNET_BODY_OUTPUT_RHAND_XROTATION, //31
|
||||
MOCAPNET_BODY_OUTPUT_RHAND_YROTATION, //32
|
||||
MOCAPNET_BODY_OUTPUT_LSHOULDER_ZROTATION,//33
|
||||
MOCAPNET_BODY_OUTPUT_LSHOULDER_XROTATION,//34
|
||||
MOCAPNET_BODY_OUTPUT_LSHOULDER_YROTATION,//35
|
||||
MOCAPNET_BODY_OUTPUT_LELBOW_ZROTATION,//36
|
||||
MOCAPNET_BODY_OUTPUT_LELBOW_XROTATION,//37
|
||||
MOCAPNET_BODY_OUTPUT_LELBOW_YROTATION,//38
|
||||
MOCAPNET_BODY_OUTPUT_LHAND_ZROTATION,//39
|
||||
MOCAPNET_BODY_OUTPUT_LHAND_XROTATION,//40
|
||||
MOCAPNET_BODY_OUTPUT_LHAND_YROTATION,//41
|
||||
MOCAPNET_BODY_OUTPUT_RHIP_ZROTATION,//42
|
||||
MOCAPNET_BODY_OUTPUT_RHIP_XROTATION,//43
|
||||
MOCAPNET_BODY_OUTPUT_RHIP_YROTATION,//44
|
||||
MOCAPNET_BODY_OUTPUT_RKNEE_ZROTATION,//45
|
||||
MOCAPNET_BODY_OUTPUT_RKNEE_XROTATION,//46
|
||||
MOCAPNET_BODY_OUTPUT_RKNEE_YROTATION,//47
|
||||
MOCAPNET_BODY_OUTPUT_RFOOT_ZROTATION,//48
|
||||
MOCAPNET_BODY_OUTPUT_RFOOT_XROTATION,//49
|
||||
MOCAPNET_BODY_OUTPUT_RFOOT_YROTATION,//50
|
||||
MOCAPNET_BODY_OUTPUT_TOE1_2_R_ZROTATION,//51
|
||||
MOCAPNET_BODY_OUTPUT_TOE1_2_R_XROTATION,//52
|
||||
MOCAPNET_BODY_OUTPUT_TOE1_2_R_YROTATION,//53
|
||||
MOCAPNET_BODY_OUTPUT_TOE5_3_R_ZROTATION,//54
|
||||
MOCAPNET_BODY_OUTPUT_TOE5_3_R_XROTATION,//55
|
||||
MOCAPNET_BODY_OUTPUT_TOE5_3_R_YROTATION,//56
|
||||
MOCAPNET_BODY_OUTPUT_LHIP_ZROTATION,//57
|
||||
MOCAPNET_BODY_OUTPUT_LHIP_XROTATION,//58
|
||||
MOCAPNET_BODY_OUTPUT_LHIP_YROTATION,//59
|
||||
MOCAPNET_BODY_OUTPUT_LKNEE_ZROTATION,//60
|
||||
MOCAPNET_BODY_OUTPUT_LKNEE_XROTATION,//61
|
||||
MOCAPNET_BODY_OUTPUT_LKNEE_YROTATION,//62
|
||||
MOCAPNET_BODY_OUTPUT_LFOOT_ZROTATION,//63
|
||||
MOCAPNET_BODY_OUTPUT_LFOOT_XROTATION,//64
|
||||
MOCAPNET_BODY_OUTPUT_LFOOT_YROTATION,//65
|
||||
MOCAPNET_BODY_OUTPUT_TOE1_2_L_ZROTATION,//66
|
||||
MOCAPNET_BODY_OUTPUT_TOE1_2_L_XROTATION,//67
|
||||
MOCAPNET_BODY_OUTPUT_TOE1_2_L_YROTATION,//68
|
||||
MOCAPNET_BODY_OUTPUT_TOE5_3_L_ZROTATION,//69
|
||||
MOCAPNET_BODY_OUTPUT_TOE5_3_L_XROTATION,//70
|
||||
MOCAPNET_BODY_OUTPUT_TOE5_3_L_YROTATION,//71
|
||||
//-----------------------------
|
||||
MOCAPNET_BODY_OUTPUT_NUMBER// = 72
|
||||
};
|
||||
*/
|
||||
|
||||
int mocapnetBody_initializeAssociations(struct MocapNET2 * mnet, struct skeletonSerialized * input);
|
||||
|
||||
int mocapnetBody_initialize(struct MocapNET2 * mnet,const char * filename,float qualitySetting,unsigned int mode,unsigned int forceCPU);
|
||||
|
||||
int mocapnetBody_unload(struct MocapNET2 * mnet);
|
||||
|
||||
int mocapnetBody_fillResultVector(std::vector<float> &finalResultVector,std::vector<float> resultBody);
|
||||
|
||||
std::vector<float> mocapnetBody_evaluateInput(struct MocapNET2 * mnet,struct skeletonSerialized * input);
|
||||
@@ -0,0 +1,310 @@
|
||||
#include "lowerBody.hpp"
|
||||
|
||||
#include "../../MocapNETLib2/config.h"
|
||||
#include "../../MocapNETLib2/IO/conversions.hpp"
|
||||
#include "../../MocapNETLib2/tools.hpp"
|
||||
#include "../../MocapNETLib2/core/core.hpp"
|
||||
|
||||
#define NORMAL "\033[0m"
|
||||
#define BLACK "\033[30m" /* Black */
|
||||
#define RED "\033[31m" /* Red */
|
||||
#define GREEN "\033[32m" /* Green */
|
||||
#define YELLOW "\033[33m" /* Yellow */
|
||||
|
||||
int mocapnetLowerBody_initializeAssociations(struct MocapNET2 * mnet, struct skeletonSerialized * input)
|
||||
{
|
||||
return initializeAssociationsForSubsetOfSkeleton(
|
||||
&mnet->lowerBodySelectionIndexesArePopulated,
|
||||
mnet->lowerBodySelectionIndexes,
|
||||
mocapNET_InputLength_WithoutNSDM_lowerbody,
|
||||
mocapNET_lowerbody,
|
||||
input
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mocapnetLowerBody_initialize(struct MocapNET2 * mnet,const char * filename,float qualitySetting,unsigned int mode,unsigned int forceCPU)
|
||||
{
|
||||
char modelPath[1024]= {0};
|
||||
int result = 0;
|
||||
|
||||
int modelNumber=0;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case 3:
|
||||
mnet->lowerBody.mode=3;
|
||||
fprintf(stderr,RED "Fatal: Mode 3 No longer supported on MocapNET 2 \n" NORMAL);
|
||||
exit(0);
|
||||
break;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
case 5:
|
||||
mnet->lowerBody.mode=5;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// Regular 3 Model setup such as the BMVC 2019 Work..
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/categorize_lowerbody_all.pb",mode,qualitySetting);
|
||||
if (fileExists(modelPath))
|
||||
{
|
||||
result += loadTensorflowInstance(&mnet->lowerBody.models[modelNumber] ,modelPath ,"input_all" ,"result_all/concat",forceCPU);
|
||||
mnet->lowerBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->lowerBody.modelLimits[modelNumber].minimumYaw1=-360.0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].maximumYaw1=360.0;
|
||||
modelNumber+=1;
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,YELLOW "Could not find a pose categorization classifier for LowerBody..\n " NORMAL );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/lowerbody_front.pb",mode,qualitySetting);
|
||||
result += loadTensorflowInstance(&mnet->lowerBody.models[modelNumber],modelPath,"input_front","result_front/concat",forceCPU);
|
||||
mnet->lowerBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->lowerBody.modelLimits[modelNumber].minimumYaw1=-45.0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].maximumYaw1=45.0;
|
||||
modelNumber+=1;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/lowerbody_back.pb",mode,qualitySetting);
|
||||
result += loadTensorflowInstance(&mnet->lowerBody.models[modelNumber],modelPath,"input_back","result_back/concat",forceCPU);
|
||||
mnet->lowerBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->lowerBody.modelLimits[modelNumber].minimumYaw1=135.0;//-90.0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].maximumYaw1=225.0;//-270.0;
|
||||
modelNumber+=1;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/lowerbody_left.pb",mode,qualitySetting);
|
||||
result += loadTensorflowInstance(&mnet->lowerBody.models[modelNumber] ,modelPath ,"input_left" ,"result_left/concat",forceCPU);
|
||||
mnet->lowerBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->lowerBody.modelLimits[modelNumber].minimumYaw1=-135.0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].maximumYaw1=45.0;
|
||||
modelNumber+=1;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/lowerbody_right.pb",mode,qualitySetting);//
|
||||
result += loadTensorflowInstance(&mnet->lowerBody.models[modelNumber] ,modelPath ,"input_right" ,"result_right/concat",forceCPU);
|
||||
mnet->lowerBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->lowerBody.modelLimits[modelNumber].minimumYaw1=45.0;
|
||||
mnet->lowerBody.modelLimits[modelNumber].maximumYaw1=135.0;
|
||||
modelNumber+=1;
|
||||
|
||||
|
||||
|
||||
if(result==modelNumber)
|
||||
{
|
||||
result=1;
|
||||
mnet->lowerBody.loadedModels=modelNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
result=0;
|
||||
}
|
||||
break;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
default:
|
||||
fprintf(stderr,RED "You requested a MocapNET configuration that is incorrect ( mode=%u )\n" NORMAL , mode);
|
||||
return 0;
|
||||
break;
|
||||
};
|
||||
|
||||
if (result)
|
||||
{
|
||||
fprintf(stderr,"Caching networks after initialization to be ready for use..\n");
|
||||
std::vector<float> emptyValues;
|
||||
for (int i=0; i<MNET_LOWERBODY_IN_NUMBER; i++)
|
||||
{
|
||||
emptyValues.push_back(0.0);
|
||||
}
|
||||
//---------------------------------------------------
|
||||
for (int i=0; i<mnet->lowerBody.loadedModels; i++ )
|
||||
{
|
||||
std::vector<float> prediction = predictTensorflow(&mnet->lowerBody.models[i],emptyValues);
|
||||
if (prediction.size()>0)
|
||||
{
|
||||
fprintf(stderr, GREEN "Caching model %u (%s) was successful\n" NORMAL ,i,mnet->lowerBody.models[i].modelPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Caching model %u (%s) was unsuccessful\n" NORMAL,i,mnet->lowerBody.models[i].modelPath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mocapnetLowerBody_unload(struct MocapNET2 * mnet)
|
||||
{
|
||||
unsigned int result=0;
|
||||
for (int i=0; i<mnet->lowerBody.loadedModels; i++ )
|
||||
{
|
||||
result+=unloadTensorflow(&mnet->lowerBody.models[i]);
|
||||
}
|
||||
|
||||
if (result==mnet->lowerBody.loadedModels) { result=1; } else
|
||||
{ result=0; }
|
||||
|
||||
mnet->lowerBody.loadedModels=0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<float> mocapnetLowerBody_evaluateInput(struct MocapNET2 * mnet,struct skeletonSerialized * input)
|
||||
{
|
||||
mnet->lowerBody.positionalInput = deriveMocapNET2InputUsingAssociations(
|
||||
mnet,
|
||||
input,
|
||||
&mnet->lowerBodySelectionIndexesArePopulated,
|
||||
mnet->lowerBodySelectionIndexes,
|
||||
mocapNET_InputLength_WithoutNSDM_lowerbody,
|
||||
mocapNET_lowerbody,
|
||||
0 // Enable to debug input
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
mnet->lowerBody.NSDM = lowerbodyCreateNDSM(mnet->lowerBody.positionalInput,0/*NSDM Positional*/,1/*NSDM Angular */,0 /*Use Normalization*/);
|
||||
|
||||
/*
|
||||
fprintf(stderr,"LowerBodyNSDM:\n");
|
||||
for (unsigned int y=0; y<17; y++)
|
||||
{
|
||||
for (unsigned int x=0; x<17; x++)
|
||||
{
|
||||
fprintf(stderr,"%0.1f ",mnet->lowerBody.NSDM[y*17+x]);
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}*/
|
||||
|
||||
mnet->lowerBody.neuralNetworkReadyInput.clear();
|
||||
mnet->lowerBody.neuralNetworkReadyInput.insert(mnet->lowerBody.neuralNetworkReadyInput.end(),mnet->lowerBody.positionalInput.begin(), mnet->lowerBody.positionalInput.end());
|
||||
mnet->lowerBody.neuralNetworkReadyInput.insert(mnet->lowerBody.neuralNetworkReadyInput.end(),mnet->lowerBody.NSDM.begin(), mnet->lowerBody.NSDM.end());
|
||||
//----------------------------------------------------------------------------------------------
|
||||
//The code block above should have done everything needed to make a 749 element vector
|
||||
//If input is not correct then we should stop right here
|
||||
//----------------------------------------------------------------------------------------------
|
||||
if (mnet->lowerBody.neuralNetworkReadyInput.size()!=MNET_LOWERBODY_IN_NUMBER)
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Incorrect size of MocapNET input .. \n" NORMAL);
|
||||
std::vector<float> emptyResult;
|
||||
return emptyResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip extra calculations by relying on upperbody orientation..
|
||||
*
|
||||
int orientationReceived =localOrientationExtraction(&mnet->lowerBody,mnet->lowerBody.neuralNetworkReadyInput);
|
||||
if (orientationReceived!=MOCAPNET_ORIENTATION_NONE)
|
||||
{
|
||||
mnet->orientation=orientationReceived;
|
||||
mnet->orientationClassifications[0]= mnet->lowerBody.orientationClassifications[0];
|
||||
mnet->orientationClassifications[1]= mnet->lowerBody.orientationClassifications[1];
|
||||
mnet->orientationClassifications[2]= mnet->lowerBody.orientationClassifications[2];
|
||||
mnet->orientationClassifications[3]= mnet->lowerBody.orientationClassifications[3];
|
||||
}
|
||||
*/
|
||||
if (
|
||||
vectorcmp(
|
||||
mnet->lowerBody.lastNeuralNetworkReadyInput,
|
||||
mnet->lowerBody.neuralNetworkReadyInput,
|
||||
0.1
|
||||
)!=0
|
||||
)
|
||||
{
|
||||
//First run the network that can predict the orientation of the skeleton so we will use the correct
|
||||
//network to get the full BVH result from it
|
||||
//----------------------------------------------------------------------------------------------
|
||||
std::vector<float> result = localExecution(
|
||||
&mnet->lowerBody,
|
||||
mnet->lowerBody.neuralNetworkReadyInput,
|
||||
mnet->orientation,
|
||||
NN_ORIENTATIONS_TRAINED_AROUND_ZERO_AND_REQUIRE_TRICK /*Body Requires orientation trick*/
|
||||
);
|
||||
mnet->lowerBody.result = result;
|
||||
mnet->lowerBody.lastNeuralNetworkReadyInput = mnet->lowerBody.neuralNetworkReadyInput;
|
||||
|
||||
return result;
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,GREEN "Nothing changed on lower body, returning previous result.. \n" NORMAL);
|
||||
return mnet->lowerBody.result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int mocapnetLowerBody_fillResultVector(std::vector<float> &result ,std::vector<float> resultBody)
|
||||
{
|
||||
if (resultBody.size()==MOCAPNET_LOWERBODY_OUTPUT_NUMBER)
|
||||
{ //This is output that targets the old body only armature..!
|
||||
//result[MOCAPNET_OUTPUT_HIP_XPOSITION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_HIP_XPOSITION];
|
||||
//result[MOCAPNET_OUTPUT_HIP_YPOSITION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_HIP_YPOSITION];
|
||||
//result[MOCAPNET_OUTPUT_HIP_ZPOSITION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_HIP_ZPOSITION];
|
||||
//result[MOCAPNET_OUTPUT_HIP_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_HIP_ZROTATION];
|
||||
//result[MOCAPNET_OUTPUT_HIP_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_HIP_YROTATION];
|
||||
//result[MOCAPNET_OUTPUT_HIP_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_HIP_XROTATION];
|
||||
//result[MOCAPNET_OUTPUT_ABDOMEN_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_ABDOMEN_ZROTATION];
|
||||
//result[MOCAPNET_OUTPUT_ABDOMEN_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_ABDOMEN_XROTATION];
|
||||
//result[MOCAPNET_OUTPUT_ABDOMEN_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_ABDOMEN_YROTATION];
|
||||
//result[MOCAPNET_OUTPUT_CHEST_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_CHEST_ZROTATION];
|
||||
//result[MOCAPNET_OUTPUT_CHEST_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_CHEST_XROTATION];
|
||||
//result[MOCAPNET_OUTPUT_CHEST_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_CHEST_YROTATION];
|
||||
//result[MOCAPNET_OUTPUT_NECK_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_NECK_ZROTATION];
|
||||
//result[MOCAPNET_OUTPUT_NECK_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_NECK_XROTATION];
|
||||
//result[MOCAPNET_OUTPUT_NECK_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_NECK_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHIP_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_RHIP_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHIP_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_RHIP_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHIP_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_RHIP_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RKNEE_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_RKNEE_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RKNEE_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_RKNEE_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RKNEE_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_RKNEE_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RFOOT_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_RFOOT_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RFOOT_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_RFOOT_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RFOOT_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_RFOOT_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_R_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE1_2_R_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_R_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE1_2_R_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_R_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE1_2_R_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_R_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE5_3_R_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_R_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE5_3_R_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_R_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE5_3_R_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHIP_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_LHIP_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHIP_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_LHIP_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHIP_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_LHIP_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LKNEE_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_LKNEE_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LKNEE_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_LKNEE_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LKNEE_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_LKNEE_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LFOOT_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_LFOOT_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LFOOT_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_LFOOT_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LFOOT_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_LFOOT_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_L_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE1_2_L_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_L_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE1_2_L_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE1_2_L_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE1_2_L_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_L_ZROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE5_3_L_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_L_XROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE5_3_L_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_TOE5_3_L_YROTATION]=resultBody[MOCAPNET_LOWERBODY_OUTPUT_TOE5_3_L_YROTATION];
|
||||
return 1;
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,YELLOW "MocapNET: Execution yielded %lu items ( expected %u ) for lower body don't know what to do with them.. \n" NORMAL,resultBody.size(),MOCAPNET_LOWERBODY_OUTPUT_NUMBER);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
/** @file lowerBody.hpp
|
||||
* @brief Code that handles getting 2D joints packed in their skeletonSerialized and vector formats and can run the tensorflow code retrieving a 3D BVH motion frame that estimates the human lower body
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
/**
|
||||
* @brief Since the C/C++ code in this repository depends on a seperate python trainer, and the networks can differ depending on training parameters (and this is a research project) the series of 2D joints
|
||||
* can often change. It is also very expensive to do string matching on every frame, so before evaluating any input this call has to be executed in order to perform the correct array associations and from then on
|
||||
* we can pass 2D data without searching for labels on each frame. It needs to be called before any mocapnetLowerBody_evaluateInput call
|
||||
* @param MocapNET instance
|
||||
* @param a skeletonSerialized structure that holds our 2D input
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int mocapnetLowerBody_initializeAssociations(struct MocapNET2 * mnet, struct skeletonSerialized * input);
|
||||
|
||||
/**
|
||||
* @brief This call loads and initializes the required Tensorflow models for the specific configuration requested, it needs to be called before any mocapnetLowerBody_evaluateInput call
|
||||
* @param MocapNET instance
|
||||
* @param This parameter is currently omitted
|
||||
* @param MocapNET 1 supported multiple quality settings, however for MocapNET2 you should default to 1.0
|
||||
* @param MocapNET 1 used 3 ensembles, MocapNET 2 uses 5 ensembles, so mode should default to 5
|
||||
* @param The network can be executed on the GPU or the CPU, if you supply 1 you will force CPU execution, if not MocapNET will try to run it on your GPU ( if tensorflow finds it )
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int mocapnetLowerBody_initialize(struct MocapNET2 * mnet,const char * filename,float qualitySetting,unsigned int mode,unsigned int forceCPU);
|
||||
|
||||
/**
|
||||
* @brief This call deallocates the tensorflow models
|
||||
* @param MocapNET instance
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int mocapnetLowerBody_unload(struct MocapNET2 * mnet);
|
||||
|
||||
/**
|
||||
* @brief This call inserts the 3D pose extracted from tensorflow into the final resulting BVH vector
|
||||
* @param The final BVH vector that we want to populate with lower body data
|
||||
* @param The lower body result
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int mocapnetLowerBody_fillResultVector(std::vector<float> &finalResultVector,std::vector<float> resultBody);
|
||||
|
||||
/**
|
||||
* @brief This call converts 2D input that is formatted on a skeletonSerialized structure to a 3D pose vector. You need to call mocapnetLowerBody_initializeAssociations and mocapnetLowerBody_initialize before calling this function
|
||||
* and if you want to convert the output result to the final result vector you need to use the mocapnetLowerBody_fillResultVector call.
|
||||
* @param MocapNET instance
|
||||
* @param a skeletonSerialized structure that holds our 2D input
|
||||
* correct ensemble for the perceived orientation.
|
||||
* @retval 3D pose output that needs to be processed through mocapnetLowerBody_fillResultVector to fill the final BVH buffer
|
||||
*/
|
||||
std::vector<float> mocapnetLowerBody_evaluateInput(struct MocapNET2 * mnet,struct skeletonSerialized * input);
|
||||
@@ -0,0 +1,404 @@
|
||||
#include "upperBody.hpp"
|
||||
|
||||
#include "../../MocapNETLib2/config.h"
|
||||
#include "../../MocapNETLib2/IO/conversions.hpp"
|
||||
#include "../../MocapNETLib2/core/core.hpp"
|
||||
#include "../../MocapNETLib2/tools.hpp"
|
||||
#include "../tools.hpp"
|
||||
|
||||
#include "../visualization/visualization.hpp" //debug alignment
|
||||
|
||||
|
||||
#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 mocapnetUpperBody_initializeAssociations(struct MocapNET2 * mnet, struct skeletonSerialized * input)
|
||||
{
|
||||
return initializeAssociationsForSubsetOfSkeleton(
|
||||
&mnet->upperBodySelectionIndexesArePopulated,
|
||||
mnet->upperBodySelectionIndexes,
|
||||
mocapNET_InputLength_WithoutNSDM_upperbody,
|
||||
mocapNET_upperbody,
|
||||
input
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mocapnetUpperBody_initialize(struct MocapNET2 * mnet,const char * filename,float qualitySetting,unsigned int mode,unsigned int forceCPU)
|
||||
{
|
||||
char modelPath[1025]= {0};
|
||||
int result = 0;
|
||||
|
||||
int modelNumber=0;
|
||||
switch (mode)
|
||||
{
|
||||
case 3:
|
||||
mnet->upperBody.mode=3;
|
||||
fprintf(stderr,RED "Fatal: Mode 3 No longer supported on MocapNET 2 \n" NORMAL);
|
||||
exit(0);
|
||||
break;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
case 5:
|
||||
mnet->upperBody.mode=5;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
// Regular 3 Model setup such as the BMVC 2019 Work..
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/upperbody_front.pb",mode,qualitySetting);
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/categorize_upperbody_all.pb",mode,qualitySetting);
|
||||
if (fileExists(modelPath))
|
||||
{
|
||||
//result += loadTensorflowInstance(&mnet->upperBody.models[modelNumber],modelPath,"input_front","result_front/concat",forceCPU);
|
||||
result += loadTensorflowInstance(&mnet->upperBody.models[modelNumber],modelPath,"input_all","result_all/concat",forceCPU);
|
||||
mnet->upperBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->upperBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->upperBody.modelLimits[modelNumber].minimumYaw1=-360.0;
|
||||
mnet->upperBody.modelLimits[modelNumber].maximumYaw1=360.0;
|
||||
modelNumber+=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,YELLOW "Could not find a pose categorization classifier for UpperBody..\n " NORMAL );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/upperbody_front.pb",mode,qualitySetting);
|
||||
result += loadTensorflowInstance(&mnet->upperBody.models[modelNumber],modelPath,"input_front","result_front/concat",forceCPU);
|
||||
mnet->upperBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->upperBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->upperBody.modelLimits[modelNumber].minimumYaw1=-45.0;
|
||||
mnet->upperBody.modelLimits[modelNumber].maximumYaw1=45.0;
|
||||
modelNumber+=1;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/upperbody_back.pb",mode,qualitySetting);
|
||||
result += loadTensorflowInstance(&mnet->upperBody.models[modelNumber],modelPath,"input_back","result_back/concat",forceCPU);
|
||||
mnet->upperBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->upperBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->upperBody.modelLimits[modelNumber].minimumYaw1=135.0;//-90.0;
|
||||
mnet->upperBody.modelLimits[modelNumber].maximumYaw1=225.0;//-270.0;
|
||||
modelNumber+=1;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/upperbody_left.pb",mode,qualitySetting);
|
||||
result += loadTensorflowInstance(&mnet->upperBody.models[modelNumber],modelPath,"input_left","result_left/concat",forceCPU);
|
||||
mnet->upperBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->upperBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->upperBody.modelLimits[modelNumber].minimumYaw1=-135.0;
|
||||
mnet->upperBody.modelLimits[modelNumber].maximumYaw1=45.0;
|
||||
modelNumber+=1;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
snprintf(modelPath,1024,"dataset/combinedModel/mocapnet2/mode%u/%0.1f/upperbody_right.pb",mode,qualitySetting);//
|
||||
result += loadTensorflowInstance(&mnet->upperBody.models[modelNumber],modelPath,"input_right","result_right/concat",forceCPU);
|
||||
mnet->upperBody.modelLimits[modelNumber].isFlipped=0;
|
||||
mnet->upperBody.modelLimits[modelNumber].numberOfLimits=1;
|
||||
mnet->upperBody.modelLimits[modelNumber].minimumYaw1=45.0;
|
||||
mnet->upperBody.modelLimits[modelNumber].maximumYaw1=135.0;
|
||||
modelNumber+=1;
|
||||
|
||||
|
||||
|
||||
if(result==modelNumber) // make this 5
|
||||
{
|
||||
result=1;
|
||||
mnet->upperBody.loadedModels=modelNumber; //make this 5
|
||||
}
|
||||
else
|
||||
{
|
||||
result=0;
|
||||
}
|
||||
break;
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
default:
|
||||
fprintf(stderr,RED "You requested a MocapNET configuration that is incorrect ( mode=%u )\n" NORMAL, mode);
|
||||
return 0;
|
||||
break;
|
||||
};
|
||||
|
||||
if (result)
|
||||
{
|
||||
fprintf(stderr,"Caching networks after initialization to be ready for use..\n");
|
||||
std::vector<float> emptyValues;
|
||||
for (int i=0; i<MNET_UPPERBODY_IN_NUMBER; i++)
|
||||
{
|
||||
emptyValues.push_back(0.0);
|
||||
}
|
||||
//---------------------------------------------------
|
||||
for (int i=0; i<mnet->upperBody.loadedModels; i++ )
|
||||
{
|
||||
std::vector<float> prediction = predictTensorflow(&mnet->upperBody.models[i],emptyValues);
|
||||
if (prediction.size()>0)
|
||||
{
|
||||
fprintf(stderr, GREEN "Caching model %u (%s) was successful\n" NORMAL,i,mnet->upperBody.models[i].modelPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,RED "Caching model %u (%s) was unsuccessful\n" NORMAL,i,mnet->upperBody.models[i].modelPath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mocapnetUpperBody_unload(struct MocapNET2 * mnet)
|
||||
{
|
||||
unsigned int result=0;
|
||||
for (int i=0; i<mnet->upperBody.loadedModels; i++ )
|
||||
{
|
||||
result+=unloadTensorflow(&mnet->upperBody.models[i]);
|
||||
}
|
||||
|
||||
if (result==mnet->upperBody.loadedModels)
|
||||
{
|
||||
result=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
result=0;
|
||||
}
|
||||
|
||||
mnet->upperBody.loadedModels=0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mocapnetUpperBody_getOrientation(struct MocapNET2 * mnet,struct skeletonSerialized * input)
|
||||
{
|
||||
mnet->upperBody.positionalInput = deriveMocapNET2InputUsingAssociations(
|
||||
mnet,
|
||||
input,
|
||||
&mnet->upperBodySelectionIndexesArePopulated,
|
||||
mnet->upperBodySelectionIndexes,
|
||||
mocapNET_InputLength_WithoutNSDM_upperbody,
|
||||
mocapNET_upperbody,
|
||||
0 // Enable to debug input
|
||||
);
|
||||
|
||||
if (mnet->upperBody.perform2DAlignmentBeforeEvaluation)
|
||||
{
|
||||
unsigned int pivotJoint = 0; //Hip
|
||||
unsigned int referenceJoint = 1; //Neck
|
||||
|
||||
//std::vector<float> original2DPoints = mnet->upperBody.positionalInput;
|
||||
//rotate2DPointsBasedOnJointAsCenter(mnet->upperBody.positionalInput,20,0);
|
||||
|
||||
//Force alignment of middle finger to make it easier on the neural network mnet->upperBody.positionalInput
|
||||
|
||||
float angleToRotate = getAngleToAlignToZero(mnet->upperBody.positionalInput,pivotJoint,referenceJoint);
|
||||
fprintf(stderr,YELLOW "Correcting upperbody skeleton by rotating it %0.2f degrees\n" NORMAL,angleToRotate);
|
||||
rotate2DPointsBasedOnJointAsCenter(mnet->upperBody.positionalInput,angleToRotate,0);
|
||||
|
||||
//debug2DPointAlignment("debugUpperAlignment",original2DPoints,mnet->upperBody.positionalInput,pivotJoint,referenceJoint,800,600);
|
||||
}
|
||||
|
||||
|
||||
mnet->upperBody.NSDM = upperbodyCreateNDSM(mnet->upperBody.positionalInput,0/*NSDM Positional*/,1/*NSDM Angular */,0/*Do Scale Compensation*/);
|
||||
|
||||
mnet->upperBody.neuralNetworkReadyInput.clear();
|
||||
mnet->upperBody.neuralNetworkReadyInput.insert(mnet->upperBody.neuralNetworkReadyInput.end(),mnet->upperBody.positionalInput.begin(), mnet->upperBody.positionalInput.end());
|
||||
mnet->upperBody.neuralNetworkReadyInput.insert(mnet->upperBody.neuralNetworkReadyInput.end(),mnet->upperBody.NSDM.begin(), mnet->upperBody.NSDM.end());
|
||||
//----------------------------------------------------------------------------------------------
|
||||
//The code block above should have done everything needed to make a 749 element vector
|
||||
//If input is not correct then we should stop right here
|
||||
//----------------------------------------------------------------------------------------------
|
||||
if (mnet->upperBody.neuralNetworkReadyInput.size()!=MNET_UPPERBODY_IN_NUMBER)
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Incorrect size of MocapNET input .. \n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int orientationReceived = MOCAPNET_ORIENTATION_NONE;
|
||||
|
||||
if (mnet->options->forceFront)
|
||||
{
|
||||
mnet->orientation = MOCAPNET_ORIENTATION_FRONT;
|
||||
} else
|
||||
if (mnet->options->forceLeft)
|
||||
{
|
||||
mnet->orientation = MOCAPNET_ORIENTATION_LEFT;
|
||||
} else
|
||||
if (mnet->options->forceBack)
|
||||
{
|
||||
mnet->orientation = MOCAPNET_ORIENTATION_BACK;
|
||||
} else
|
||||
if (mnet->options->forceRight)
|
||||
{
|
||||
mnet->orientation = MOCAPNET_ORIENTATION_RIGHT;
|
||||
} else
|
||||
{
|
||||
orientationReceived = localOrientationExtraction(&mnet->upperBody,mnet->upperBody.neuralNetworkReadyInput);
|
||||
if (orientationReceived!=MOCAPNET_ORIENTATION_NONE)
|
||||
{
|
||||
mnet->orientation=orientationReceived;
|
||||
|
||||
mnet->orientationClassifications[0]= mnet->upperBody.orientationClassifications[0];
|
||||
mnet->orientationClassifications[1]= mnet->upperBody.orientationClassifications[1];
|
||||
mnet->orientationClassifications[2]= mnet->upperBody.orientationClassifications[2];
|
||||
mnet->orientationClassifications[3]= mnet->upperBody.orientationClassifications[3];
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Incorrect orientation retrieved from upperbody .. \n" NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
return orientationReceived;
|
||||
}
|
||||
|
||||
|
||||
std::vector<float> mocapnetUpperBody_evaluateInput(struct MocapNET2 * mnet,struct skeletonSerialized * input)
|
||||
{
|
||||
mnet->upperBody.positionalInput = deriveMocapNET2InputUsingAssociations(
|
||||
mnet,
|
||||
input,
|
||||
&mnet->upperBodySelectionIndexesArePopulated,
|
||||
mnet->upperBodySelectionIndexes,
|
||||
mocapNET_InputLength_WithoutNSDM_upperbody,
|
||||
mocapNET_upperbody,
|
||||
0 // Enable to debug input
|
||||
);
|
||||
|
||||
if (mnet->upperBody.perform2DAlignmentBeforeEvaluation)
|
||||
{
|
||||
unsigned int pivotJoint = 0; //Hip
|
||||
unsigned int referenceJoint = 1; //Neck
|
||||
|
||||
//std::vector<float> original2DPoints = mnet->upperBody.positionalInput;
|
||||
//rotate2DPointsBasedOnJointAsCenter(mnet->upperBody.positionalInput,20,0);
|
||||
|
||||
//Force alignment of middle finger to make it easier on the neural network mnet->upperBody.positionalInput
|
||||
|
||||
float angleToRotate = getAngleToAlignToZero(mnet->upperBody.positionalInput,pivotJoint,referenceJoint);
|
||||
fprintf(stderr,YELLOW "Correcting upperbody skeleton by rotating it %0.2f degrees\n" NORMAL,angleToRotate);
|
||||
rotate2DPointsBasedOnJointAsCenter(mnet->upperBody.positionalInput,angleToRotate,0);
|
||||
|
||||
//debug2DPointAlignment("debugUpperAlignment",original2DPoints,mnet->upperBody.positionalInput,pivotJoint,referenceJoint,800,600);
|
||||
}
|
||||
|
||||
mnet->upperBody.NSDM = upperbodyCreateNDSM(mnet->upperBody.positionalInput,0/*NSDM Positional*/,1/*NSDM Angular */,0/*Do Scale Compensation*/);
|
||||
mnet->upperBody.neuralNetworkReadyInput.clear();
|
||||
mnet->upperBody.neuralNetworkReadyInput.insert(mnet->upperBody.neuralNetworkReadyInput.end(),mnet->upperBody.positionalInput.begin(), mnet->upperBody.positionalInput.end());
|
||||
mnet->upperBody.neuralNetworkReadyInput.insert(mnet->upperBody.neuralNetworkReadyInput.end(),mnet->upperBody.NSDM.begin(), mnet->upperBody.NSDM.end());
|
||||
//----------------------------------------------------------------------------------------------
|
||||
//The code block above should have done everything needed to make a 749 element vector
|
||||
//If input is not correct then we should stop right here
|
||||
//----------------------------------------------------------------------------------------------
|
||||
if (mnet->upperBody.neuralNetworkReadyInput.size()!=MNET_UPPERBODY_IN_NUMBER)
|
||||
{
|
||||
fprintf(stderr,RED "MocapNET: Incorrect size of MocapNET input .. \n" NORMAL);
|
||||
std::vector<float> emptyResult;
|
||||
return emptyResult;
|
||||
}
|
||||
|
||||
if (
|
||||
vectorcmp(
|
||||
mnet->upperBody.lastNeuralNetworkReadyInput,
|
||||
mnet->upperBody.neuralNetworkReadyInput,
|
||||
0.1
|
||||
)!=0
|
||||
)
|
||||
{
|
||||
//First run the network that can predict the orientation of the skeleton so we will use the correct
|
||||
//network to get the full BVH result from it
|
||||
//----------------------------------------------------------------------------------------------
|
||||
std::vector<float> result = localExecution(
|
||||
&mnet->upperBody,
|
||||
mnet->upperBody.neuralNetworkReadyInput,
|
||||
mnet->orientation,
|
||||
NN_ORIENTATIONS_TRAINED_AROUND_ZERO_AND_REQUIRE_TRICK /*Body Requires orientation trick*/
|
||||
);
|
||||
|
||||
mnet->upperBody.result = result;
|
||||
mnet->upperBody.lastNeuralNetworkReadyInput = mnet->upperBody.neuralNetworkReadyInput;
|
||||
|
||||
return result;
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,GREEN "Nothing changed on upper body, returning previous result.. \n" NORMAL);
|
||||
return mnet->upperBody.result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int mocapnetUpperBody_fillResultVector(std::vector<float> &result,std::vector<float> resultUpperBody)
|
||||
{
|
||||
if (resultUpperBody.size()==MOCAPNET_UPPERBODY_OUTPUT_NUMBER)
|
||||
{
|
||||
//This is output that targets the old body only armature..!
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
result[MOCAPNET_OUTPUT_HIP_XPOSITION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_HIP_XPOSITION];
|
||||
result[MOCAPNET_OUTPUT_HIP_YPOSITION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_HIP_YPOSITION];
|
||||
result[MOCAPNET_OUTPUT_HIP_ZPOSITION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_HIP_ZPOSITION];
|
||||
result[MOCAPNET_OUTPUT_HIP_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_HIP_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_HIP_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_HIP_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_HIP_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_HIP_XROTATION];
|
||||
//Abdomen/Chest encoders seem to be wrong, we overwrite them..
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
result[MOCAPNET_OUTPUT_ABDOMEN_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_ABDOMEN_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_ABDOMEN_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_ABDOMEN_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_ABDOMEN_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_ABDOMEN_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_ABDOMEN_ZROTATION]=(float) 0.0;
|
||||
result[MOCAPNET_OUTPUT_ABDOMEN_XROTATION]=(float) 0.0;
|
||||
result[MOCAPNET_OUTPUT_ABDOMEN_YROTATION]=(float) 0.0;
|
||||
result[MOCAPNET_OUTPUT_CHEST_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_CHEST_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_CHEST_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_CHEST_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_CHEST_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_CHEST_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_CHEST_ZROTATION]=(float) 0.0;
|
||||
result[MOCAPNET_OUTPUT_CHEST_XROTATION]=(float) 0.0;
|
||||
result[MOCAPNET_OUTPUT_CHEST_YROTATION]=(float) 0.0;
|
||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
result[MOCAPNET_OUTPUT_NECK_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_NECK_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_NECK_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_NECK_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_NECK_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_NECK_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_HEAD_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_HEAD_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_HEAD_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_HEAD_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_HEAD_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_HEAD_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_L_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_EYE_L_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_L_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_EYE_L_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_L_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_EYE_L_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_R_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_EYE_R_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_R_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_EYE_R_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_EYE_R_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_EYE_R_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RSHOULDER_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_RSHOULDER_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RSHOULDER_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_RSHOULDER_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RSHOULDER_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_RSHOULDER_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RELBOW_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_RELBOW_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RELBOW_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_RELBOW_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RELBOW_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_RELBOW_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHAND_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_RHAND_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHAND_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_RHAND_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_RHAND_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_RHAND_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LSHOULDER_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_LSHOULDER_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LSHOULDER_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_LSHOULDER_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LSHOULDER_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_LSHOULDER_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LELBOW_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_LELBOW_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LELBOW_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_LELBOW_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LELBOW_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_LELBOW_YROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHAND_ZROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_LHAND_ZROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHAND_XROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_LHAND_XROTATION];
|
||||
result[MOCAPNET_OUTPUT_LHAND_YROTATION]=resultUpperBody[MOCAPNET_UPPERBODY_OUTPUT_LHAND_YROTATION];
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,YELLOW "MocapNET: Execution yielded %lu items ( expected %u ) for upper body don't know what to do with them.. \n" NORMAL,resultUpperBody.size(),MOCAPNET_UPPERBODY_OUTPUT_NUMBER);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
/** @file upperBody.hpp
|
||||
* @brief Code that handles getting 2D joints packed in their skeletonSerialized and vector formats and can run the tensorflow code retrieving a 3D BVH motion frame that estimates the human upper body
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
/**
|
||||
* @brief Since the C/C++ code in this repository depends on a seperate python trainer, and the networks can differ depending on training parameters (and this is a research project) the series of 2D joints
|
||||
* can often change. It is also very expensive to do string matching on every frame, so before evaluating any input this call has to be executed in order to perform the correct array associations and from then on
|
||||
* we can pass 2D data without searching for labels on each frame. It needs to be called before any mocapnetUpperBody_evaluateInput call
|
||||
* @param MocapNET instance
|
||||
* @param a skeletonSerialized structure that holds our 2D input
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int mocapnetUpperBody_initializeAssociations(struct MocapNET2 * mnet, struct skeletonSerialized * input);
|
||||
|
||||
/**
|
||||
* @brief This call loads and initializes the required Tensorflow models for the specific configuration requested, it needs to be called before any mocapnetUpperBody_evaluateInput call
|
||||
* @param MocapNET instance
|
||||
* @param This parameter is currently omitted
|
||||
* @param MocapNET 1 supported multiple quality settings, however for MocapNET2 you should default to 1.0
|
||||
* @param MocapNET 1 used 3 ensembles, MocapNET 2 uses 5 ensembles, so mode should default to 5
|
||||
* @param The network can be executed on the GPU or the CPU, if you supply 1 you will force CPU execution, if not MocapNET will try to run it on your GPU ( if tensorflow finds it )
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int mocapnetUpperBody_initialize(struct MocapNET2 * mnet,const char * filename,float qualitySetting,unsigned int mode,unsigned int forceCPU);
|
||||
|
||||
/**
|
||||
* @brief This call deallocates the tensorflow models
|
||||
* @param MocapNET instance
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int mocapnetUpperBody_unload(struct MocapNET2 * mnet);
|
||||
|
||||
/**
|
||||
* @brief This call inserts the 3D pose extracted from tensorflow into the final resulting BVH vector
|
||||
* @param The final BVH vector that we want to populate with upper body data
|
||||
* @param The upper body result
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int mocapnetUpperBody_fillResultVector(std::vector<float> &finalResultVector,std::vector<float> resultBody);
|
||||
|
||||
|
||||
|
||||
int mocapnetUpperBody_getOrientation(struct MocapNET2 * mnet,struct skeletonSerialized * input);
|
||||
|
||||
/**
|
||||
* @brief This call converts 2D input that is formatted on a skeletonSerialized structure to a 3D pose vector. You need to call mocapnetUpperBody_initializeAssociations and mocapnetUpperBody_initialize before calling this function
|
||||
* and if you want to convert the output result to the final result vector you need to use the mocapnetUpperBody_fillResultVector call.
|
||||
* @param MocapNET instance
|
||||
* @param a skeletonSerialized structure that holds our 2D input
|
||||
* @param If this flag is set to 1 then the 2D input will be treated as front facing, otherwise the orientation classifier will decide on the orientation and call the
|
||||
* correct ensemble for the perceived orientation.
|
||||
* @retval 3D pose output that needs to be processed through mocapnetUpperBody_fillResultVector to fill the final BVH buffer
|
||||
*/
|
||||
std::vector<float> mocapnetUpperBody_evaluateInput(struct MocapNET2 * mnet,struct skeletonSerialized * input);
|
||||
@@ -0,0 +1,498 @@
|
||||
#include "tools.hpp"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h> //tolower
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
unsigned long tickBaseMN = 0;
|
||||
|
||||
|
||||
#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 vectorcmp(std::vector<float> vA,std::vector<float> vB, float maximumDistance)
|
||||
{
|
||||
//fprintf(stderr,"vectorcmp %u vs %u elements \n",vA.size(), vB.size());
|
||||
if (vA.size()>vB.size()) { return -1; }
|
||||
else
|
||||
if (vA.size()<vB.size()) { return 1; }
|
||||
else
|
||||
{
|
||||
for (int i=0; i<vA.size(); i++)
|
||||
{
|
||||
//fprintf(stderr," %0.2f/%0.2f ",vA[i],vB[i]);
|
||||
if (vA[i]<vB[i])
|
||||
{
|
||||
if (vB[i]-vA[i]>maximumDistance) { return -1; }
|
||||
} else
|
||||
if (vA[i]>vB[i])
|
||||
{
|
||||
if (vA[i]-vB[i]>maximumDistance) { return 1; }
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int nsleep(long nanoseconds)
|
||||
{
|
||||
struct timespec req, rem;
|
||||
|
||||
req.tv_sec = 0;
|
||||
req.tv_nsec = nanoseconds;
|
||||
|
||||
return nanosleep(&req , &rem);
|
||||
}
|
||||
|
||||
|
||||
/** @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(std::vector<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(std::vector<float> &positions,float angle,unsigned int centerJoint)
|
||||
{
|
||||
if (positions.size()%3!=0)
|
||||
{
|
||||
fprintf(stderr,RED "rotate2DPointsBasedOnJointAsCenter: incorrect positions.. \n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (positions.size()<=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: .. \n" NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (unsigned int jID=0; jID<positions.size()/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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
float * x,
|
||||
float * y,
|
||||
unsigned int currentWidth,
|
||||
unsigned int currentHeight,
|
||||
unsigned int respectTrainingAspectRatio,
|
||||
unsigned int trainingWidth,
|
||||
unsigned int trainingHeight
|
||||
)
|
||||
{
|
||||
if ( (*x==0) && (*y==0) )
|
||||
{
|
||||
//Only Fix Aspect Ratio on visible points to preserve 0,0,0 that are
|
||||
//important to the neural network..
|
||||
return;
|
||||
}
|
||||
|
||||
if (!respectTrainingAspectRatio)
|
||||
{
|
||||
*x=(float) *x/currentWidth;
|
||||
*y=(float) *y/currentHeight;
|
||||
return;
|
||||
}
|
||||
|
||||
//fprintf(stderr,YELLOW "normalizeWhileAlsoMatchingTrainingAspectRatio\n" NORMAL);
|
||||
unsigned int addX=0,addY=0;
|
||||
unsigned int targetWidth=currentWidth,targetHeight=currentHeight;
|
||||
float currentAspectRatio = (float) currentWidth/currentHeight;
|
||||
float trainingAspectRatio = (float) trainingWidth/trainingHeight;
|
||||
|
||||
//fprintf(stderr,"Will try to correct aspect ratio from %0.2f(%ux%u) to %0.2f (%ux%u)\n",currentAspectRatio,currentWidth,currentHeight,trainingAspectRatio,trainingWidth,trainingHeight);
|
||||
|
||||
|
||||
if (currentHeight<currentWidth)
|
||||
{
|
||||
targetHeight=(unsigned int) currentWidth/trainingAspectRatio;
|
||||
if (targetHeight>=currentHeight)
|
||||
{
|
||||
addY=(unsigned int) (targetHeight-currentHeight)/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Turns out we will have to enlarge X instead of englarging Y
|
||||
addY=0;
|
||||
targetHeight=currentHeight;
|
||||
targetWidth=(unsigned int)currentHeight*trainingAspectRatio;
|
||||
addX=(unsigned int) (targetWidth-currentWidth)/2;
|
||||
}
|
||||
}
|
||||
else if (currentWidth<=currentHeight)
|
||||
{
|
||||
targetWidth=(unsigned int)currentHeight*trainingAspectRatio;
|
||||
if (targetWidth>=currentWidth)
|
||||
{
|
||||
addX=(unsigned int) (targetWidth-currentWidth)/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Turns out we will have to enlarge Y instead of englarging X
|
||||
addX=0;
|
||||
targetWidth=currentWidth;
|
||||
targetHeight=(unsigned int) currentWidth/trainingAspectRatio;
|
||||
addY=(unsigned int) (targetHeight-currentHeight)/2;
|
||||
}
|
||||
}
|
||||
|
||||
//fprintf(stderr,"Target resolution is %ux%u to Y\n",targetWidth,targetHeight);
|
||||
//fprintf(stderr,"Will add %u to X and %u to Y to achieve it\n",addX,addY);
|
||||
|
||||
float targetAspectRatio=(float) targetWidth/targetHeight;
|
||||
if ((unsigned int) targetAspectRatio/100!= (unsigned int) trainingAspectRatio/100)
|
||||
{
|
||||
fprintf(stderr,"Failed to perfectly match training aspect ratio (%0.5f), managed to reach (%0.5f)\n",trainingAspectRatio,targetAspectRatio);
|
||||
}
|
||||
|
||||
|
||||
*x=(float) (*x+addX)/targetWidth;
|
||||
*y=(float) (*y+addY)/targetHeight;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int convertStringToLowercase(char * target,unsigned int targetLength,const char * source)
|
||||
{
|
||||
if (source==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
unsigned int sourceLength = strlen(source);
|
||||
|
||||
if (targetLength<=sourceLength)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i=0; i<sourceLength; i++)
|
||||
{
|
||||
target[i]=tolower(source[i]);
|
||||
}
|
||||
target[sourceLength]=0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int getNumberOfEmptyElements(std::vector<float> mocapNETInput)
|
||||
{
|
||||
unsigned int numberOfZeros=0;
|
||||
|
||||
for (int i=0; i<mocapNETInput.size(); i++)
|
||||
{
|
||||
if (mocapNETInput[i]==0)
|
||||
{
|
||||
++numberOfZeros;
|
||||
}
|
||||
|
||||
}
|
||||
return numberOfZeros;
|
||||
}
|
||||
|
||||
|
||||
int findFirstFormattedFileInDirectory(const char * path,const char * formatString, const char * label, unsigned int * frameIDOutput)
|
||||
{
|
||||
char filePathOfJSONFile[1025]= {0};
|
||||
|
||||
unsigned int frameID=0;
|
||||
int found=0;
|
||||
|
||||
while (!found)
|
||||
{
|
||||
snprintf(filePathOfJSONFile,1024,formatString,path,label,frameID);
|
||||
|
||||
if( fileExists(filePathOfJSONFile) )
|
||||
{
|
||||
*frameIDOutput=frameID;
|
||||
found=1;
|
||||
break;
|
||||
}
|
||||
|
||||
++frameID;
|
||||
if (frameID==10000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
int executeCommandLineNum(const char * command, char * what2GetBack, unsigned int what2GetBackMaxSize,unsigned int lineNumber)
|
||||
{
|
||||
/* Open the command for reading. */
|
||||
FILE * fp = popen(command, "r");
|
||||
if (fp == 0 )
|
||||
{
|
||||
fprintf(stderr,"Failed to run command (%s) \n",command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the output a line at a time - output it. */
|
||||
unsigned int i=0;
|
||||
while (fgets(what2GetBack, what2GetBackMaxSize, fp) != 0)
|
||||
{
|
||||
++i;
|
||||
if (lineNumber==i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* close */
|
||||
pclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simple way to get our CPU model name..
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int getCPUName(char * str,unsigned int maxLength)
|
||||
{
|
||||
if (!executeCommandLineNum("cat /proc/cpuinfo | grep \"model name\" | cut -d':' -f2 | tr -s ' '| uniq",str,maxLength,0))
|
||||
{
|
||||
fprintf(stderr,"Could not get our CPU model name\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int length=strlen(str);
|
||||
for (unsigned int c=0; c<length; c++)
|
||||
{
|
||||
if (str[c]==10) { str[c]=0; }
|
||||
if (str[c]==13) { str[c]=0; }
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simple way to get our GPU model name..
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int getGPUName(char * str,unsigned int maxLength)
|
||||
{
|
||||
if (!executeCommandLineNum("lspci | grep VGA | cut -d':' -f3 | tr -s ' '| uniq",str,maxLength,0))
|
||||
{
|
||||
fprintf(stderr,"Could not get our GPU model name\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int length=strlen(str);
|
||||
for (unsigned int c=0; c<length; c++)
|
||||
{
|
||||
if (str[c]==10) { str[c]=0; }
|
||||
if (str[c]==13) { str[c]=0; }
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
unsigned long GetTickCountMicrosecondsMN()
|
||||
{
|
||||
struct timespec ts;
|
||||
if ( clock_gettime(CLOCK_MONOTONIC,&ts) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tickBaseMN==0)
|
||||
{
|
||||
tickBaseMN = ts.tv_sec*1000000 + ts.tv_nsec/1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ( ts.tv_sec*1000000 + ts.tv_nsec/1000 ) - tickBaseMN;
|
||||
}
|
||||
|
||||
|
||||
unsigned long GetTickCountMillisecondsMN()
|
||||
{
|
||||
return (unsigned long) GetTickCountMicrosecondsMN()/1000;
|
||||
}
|
||||
|
||||
|
||||
float convertStartEndTimeFromMicrosecondsToFPS(unsigned long startTime, unsigned long endTime)
|
||||
{
|
||||
float timeInMilliseconds = (float) (endTime-startTime)/1000;
|
||||
if (timeInMilliseconds ==0.0)
|
||||
{
|
||||
timeInMilliseconds=0.00001; //Take care of division by null..
|
||||
}
|
||||
return (float) 1000/timeInMilliseconds;
|
||||
}
|
||||
|
||||
|
||||
char directoryExists(const char * folder)
|
||||
{
|
||||
struct stat sb;
|
||||
if (stat(folder, &sb) == 0 && S_ISDIR(sb.st_mode)) { return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char fileExists(const char * filename)
|
||||
{
|
||||
FILE *fp = fopen(filename,"r");
|
||||
if( fp )
|
||||
{
|
||||
/* exists */
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getImageWidthHeight(const char * filename,unsigned int * width, unsigned int * height)
|
||||
{
|
||||
if (!fileExists(filename))
|
||||
{
|
||||
fprintf(stderr,"File %s does not exist, unable to get its dimensions..\n",filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int retrievedWidth=0;
|
||||
unsigned int retrievedHeight=0;
|
||||
|
||||
char commandToExecute[1024]= {0};
|
||||
char result[1024]= {0};
|
||||
int results=0;
|
||||
|
||||
snprintf(commandToExecute,1024,"identify -format \"%%w\" %s",filename);
|
||||
if ( executeCommandLineNum(commandToExecute,result,1024,0) )
|
||||
{
|
||||
retrievedWidth = atoi(result);
|
||||
++results;
|
||||
}
|
||||
|
||||
snprintf(commandToExecute,1024,"identify -format \"%%h\" %s",filename);
|
||||
if ( executeCommandLineNum(commandToExecute,result,1024,0) )
|
||||
{
|
||||
retrievedHeight = atoi(result);
|
||||
++results;
|
||||
}
|
||||
|
||||
if (
|
||||
(retrievedWidth!=0) &&
|
||||
(retrievedHeight!=0)
|
||||
)
|
||||
{
|
||||
*width = retrievedWidth;
|
||||
*height = retrievedHeight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (results==2);
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
#pragma once
|
||||
/** @file tools.h
|
||||
* @brief System Tools that don't fit somewhere else
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
|
||||
const float goFromRadToDegrees=(float) 180.0 / M_PI;
|
||||
const float goFromDegreesToRad=(float) M_PI / 180.0;
|
||||
|
||||
|
||||
int vectorcmp(std::vector<float> vA,std::vector<float> vB, float maximumDistance);
|
||||
|
||||
int nsleep(long nanoseconds);
|
||||
|
||||
/**
|
||||
* @brief Get euclidean 2D distance between a pair of points
|
||||
* @ingroup tools
|
||||
* @param Point A, X coordinate
|
||||
* @param Point A, Y coordinate
|
||||
* @param Point B, X coordinate
|
||||
* @param Point B, Y coordinate
|
||||
* @retval Output rotation value
|
||||
*/
|
||||
float getJoint2DDistance_tools(float aX,float aY,float bX,float bY);
|
||||
|
||||
/**
|
||||
* @brief This is a very crucial function that converts a pair of 2D points to an NSRM rotation
|
||||
* @ingroup tools
|
||||
* @param Point A, X coordinate
|
||||
* @param Point A, Y coordinate
|
||||
* @param Point B, X coordinate
|
||||
* @param Point B, Y coordinate
|
||||
* @retval Output rotation value angle in rads
|
||||
*/
|
||||
float getAngleToAlignToZero_tools(float aX,float aY,float bX,float bY) ;
|
||||
|
||||
/**
|
||||
* @brief This is a wrapper for the getAngleToAlignToZero_tools function that applies it in a vector of positions while also optionally centering everything using a reference joint.
|
||||
* @ingroup tools
|
||||
* @param Vector of 2D points
|
||||
* @param Index to the 2D point to be treated as alignment center
|
||||
* @param Index to reference joint
|
||||
* @retval Output rotation value angle in rads
|
||||
*/
|
||||
float getAngleToAlignToZero(std::vector<float> &positions,unsigned int centerJoint,unsigned int referenceJoint);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This call aligns 2D points based on a single point that will be used as a pivot.
|
||||
* @ingroup tools
|
||||
* @param Vector of 2D points
|
||||
* @param Angle to rotate all points at
|
||||
* @param Index to the 2D point to be treated as alignment center
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int rotate2DPointsBasedOnJointAsCenter(std::vector<float> &positions,float angle,unsigned int centerJoint);
|
||||
|
||||
|
||||
void normalize2DPointWhileAlsoMatchingTrainingAspectRatio(
|
||||
float * x,
|
||||
float * y,
|
||||
unsigned int currentWidth,
|
||||
unsigned int currentHeight,
|
||||
unsigned int respectTrainingAspectRatio,
|
||||
unsigned int trainingWidth,
|
||||
unsigned int trainingHeight
|
||||
);
|
||||
|
||||
int convertStringToLowercase(
|
||||
char * target,
|
||||
unsigned int targetLength,
|
||||
const char * source
|
||||
);
|
||||
|
||||
|
||||
int findFirstFormattedFileInDirectory(
|
||||
const char * path,
|
||||
const char * formatString,
|
||||
const char * label,
|
||||
unsigned int * frameIDOutput
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Count the number of empty ( zero ) elements in a vector
|
||||
* @ingroup tools
|
||||
* @param Vector
|
||||
* @retval Number of zeros encountered
|
||||
*/
|
||||
unsigned int getNumberOfEmptyElements(std::vector<float> mocapNETInput);
|
||||
|
||||
/**
|
||||
* @brief Execute a shell command
|
||||
* @ingroup tools
|
||||
* @param CString to execute
|
||||
* @param Pointer to array that will contain our result
|
||||
* @param Size of array that will contain our result
|
||||
* @param If we have more than one lines of output which one we want?
|
||||
* @bug This function executes a string in the shell and this means that it is dangerous
|
||||
* @retval 1 = Success loading the files , 0 = Failure
|
||||
*/
|
||||
int executeCommandLineNum(
|
||||
const char * command ,
|
||||
char * what2GetBack ,
|
||||
unsigned int what2GetBackMaxSize,
|
||||
unsigned int lineNumber
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Get the CPU name
|
||||
* @param CString where the CPU name should be stored
|
||||
* @param Size of array that will contain our result
|
||||
* @ingroup tools
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int getCPUName(char * str,unsigned int maxLength);
|
||||
|
||||
/**
|
||||
* @brief Get the GPU name
|
||||
* @param CString where the GPU name should be stored
|
||||
* @param Size of array that will contain our result
|
||||
* @ingroup tools
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int getGPUName(char * str,unsigned int maxLength);
|
||||
|
||||
/**
|
||||
* @brief Get uptime in microseconds
|
||||
* @ingroup tools
|
||||
* @retval Microseconds of system uptime
|
||||
*/
|
||||
unsigned long GetTickCountMicrosecondsMN();
|
||||
|
||||
/**
|
||||
* @brief Get uptime in milliseconds
|
||||
* @ingroup tools
|
||||
* @retval Milliseconds of system uptime
|
||||
*/
|
||||
unsigned long GetTickCountMillisecondsMN();
|
||||
|
||||
/**
|
||||
* @brief Check if a directory exists on our filesystem
|
||||
* @ingroup tools
|
||||
* @retval 1=Exists/0=Doesnt Exist
|
||||
*/
|
||||
char directoryExists(const char * folder);
|
||||
|
||||
/**
|
||||
* @brief Check if a filename exists on our filesystem
|
||||
* @ingroup tools
|
||||
* @retval 1=Exists/0=Doesnt Exist
|
||||
*/
|
||||
char fileExists(const char * filename);
|
||||
|
||||
/**
|
||||
* @brief Convert start and end time to a framerate ( frames per second )
|
||||
* @ingroup demo
|
||||
* @retval Will return a framerate from two millisecond timestamps, if no time duration has been passed there is no division by zero.
|
||||
*/
|
||||
float convertStartEndTimeFromMicrosecondsToFPS(unsigned long startTime, unsigned long endTime);
|
||||
|
||||
/**
|
||||
* @brief Get the dimensions of an image by relying on the identify tool
|
||||
* @ingroup tools
|
||||
* @param CString with path to the image file to get dimensions for
|
||||
* @param Pointer to an unsigned int that will hold the width of the image file we specified
|
||||
* @param Pointer to an unsigned int that will hold the height of the image file we specified
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int getImageWidthHeight(
|
||||
const char * filename,
|
||||
unsigned int * width ,
|
||||
unsigned int * height
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
#include "allInOne.hpp"
|
||||
#include "visualization.hpp"
|
||||
#include "widgets.hpp"
|
||||
#include "drawSkeleton.hpp"
|
||||
#include "opengl.hpp"
|
||||
|
||||
|
||||
#include "../IO/jsonRead.hpp"
|
||||
#include "../IO/bvh.hpp"
|
||||
#include "../tools.hpp"
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
|
||||
std::vector<float> frameRateHistoryTotal;
|
||||
std::vector<float> frameRateIKHistory;
|
||||
std::vector<float> frameRateMNET2History;
|
||||
|
||||
|
||||
void appendToHistory(std::vector<float> & frameRateHistory, float newValue, unsigned int maximumValues)
|
||||
{
|
||||
//Keep framerate history
|
||||
frameRateHistory.push_back(newValue);
|
||||
if (frameRateHistory.size()>maximumValues)
|
||||
{
|
||||
frameRateHistory.erase(frameRateHistory.begin());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if USE_OPENCV
|
||||
cv::Mat openGLAllInOneFramePermanentMat;
|
||||
|
||||
|
||||
cv::Mat offsetImageWithPadding(const Mat& originalImage, int offsetX, int offsetY, Scalar backgroundColour)
|
||||
{
|
||||
cv::Mat padded = Mat(originalImage.rows + 2 * abs(offsetY), originalImage.cols + 2 * abs(offsetX), CV_8UC3, backgroundColour);
|
||||
originalImage.copyTo(padded(Rect(abs(offsetX), abs(offsetY), originalImage.cols, originalImage.rows)));
|
||||
return Mat(padded,Rect(abs(offsetX) + offsetX, abs(offsetY) + offsetY, originalImage.cols, originalImage.rows));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int extraWindow(
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedView
|
||||
)
|
||||
{
|
||||
//cv::Mat image = cv::Mat(800, 800, CV_8UC3);
|
||||
cv::Mat image = cv::Mat::zeros(1920, 1080, CV_8UC3);
|
||||
|
||||
//Switch that controls drawing skeleton labels
|
||||
int draw3DSkeletonJointLabels = 1;
|
||||
|
||||
//This is the 3D skeleton visualized to match the RGB image
|
||||
//drawSkeleton(image,points2DOutputGUIRealView,-1000,0,draw3DSkeletonJointLabels);
|
||||
|
||||
//This is the 3D skeleton nailed to be visualized to match the RGB image
|
||||
drawSkeleton(image,points2DOutputGUIForcedView,-800,0,draw3DSkeletonJointLabels);
|
||||
|
||||
cv::imshow("New Visualization",image);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int visualizeAllInOne(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int saveVisualization,
|
||||
cv::Mat * alreadyLoadedImage,
|
||||
const char * path,
|
||||
const char * label,
|
||||
unsigned int serialLength,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
struct skeletonSerialized * skeleton,
|
||||
struct MocapNET2 * mnet,
|
||||
struct MocapNET2Options * options,
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedView,
|
||||
unsigned int numberOfMissingJoints
|
||||
)
|
||||
{
|
||||
|
||||
#if USE_OPENCV
|
||||
int success=0;
|
||||
char finalFilename[2048]= {0};
|
||||
|
||||
|
||||
//Handle Background
|
||||
//-----------------------------------------------------------------------------------
|
||||
if (alreadyLoadedImage==0)
|
||||
{
|
||||
char formatString[256]= {0};
|
||||
snprintf(formatString,256,"%%s/%%s%%0%uu.jpg",serialLength);
|
||||
|
||||
//colorFrame_0_00001.jpg
|
||||
snprintf(finalFilename,2048,formatString,path,label,frameNumber/*Frame ID*/);
|
||||
//snprintf(finalFilename,2048,"%s/colorFrame_0_%05d.jpg",path,frameNumber+1);
|
||||
}
|
||||
|
||||
int showFramerate=30; //30 or 0
|
||||
|
||||
float scale=1.0;
|
||||
cv::Mat image;
|
||||
cv::Rect roi;
|
||||
cv::Mat destinationROI;
|
||||
|
||||
if ( (fileExists(finalFilename) ) || (alreadyLoadedImage!=0) )
|
||||
{
|
||||
if (alreadyLoadedImage!=0)
|
||||
{
|
||||
image = *alreadyLoadedImage;
|
||||
|
||||
if (
|
||||
( image.size().width < 640 ) ||
|
||||
( image.size().height < 480 )
|
||||
)
|
||||
{
|
||||
fprintf(stderr,"Very small given frame ( %ux%u..\n",image.size().width,image.size().height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//cv::imshow(windowName,image); //
|
||||
//cv::waitKey(0);
|
||||
}
|
||||
else
|
||||
if (fileExists(finalFilename) )
|
||||
{
|
||||
image = imread(finalFilename,cv::IMREAD_COLOR); // older versions might want the CV_LOAD_IMAGE_COLOR flag
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//The skeleton offset controls offset for the 3D skeleton rendering on top of the image
|
||||
//Offsets are wrong for resolutions other than 1920x1080 since they are hardcoded..
|
||||
float offsetX = (float) -1*image.size().width/4;
|
||||
float offsetY = 0.0;// (float) -1*image.size().height/1080;
|
||||
|
||||
//If you uncomment the next like the 3D overlay will stay exactly on top of the skeleton
|
||||
//offsetX=0;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// OpenGL overlay stuff
|
||||
//---------------------------------------------------------------------
|
||||
cv::Mat * openGLMatForVisualization = 0;
|
||||
if (options->useOpenGLVisualization) {
|
||||
//fprintf(stderr,"updateOpenGLView\n");
|
||||
updateOpenGLView(mnet->currentSolution);
|
||||
|
||||
//fprintf(stderr,"visualizeOpenGL\n");
|
||||
unsigned int openGLFrameWidth=width,openGLFrameHeight=height;
|
||||
char * openGLFrame = visualizeOpenGL(&openGLFrameWidth,&openGLFrameHeight);
|
||||
//=====================================================================
|
||||
if (openGLFrame!=0)
|
||||
{
|
||||
fprintf(stderr,"Got Back an OpenGL frame..!\n");
|
||||
cv::Mat openGLMat(openGLFrameHeight, openGLFrameWidth, CV_8UC3);
|
||||
unsigned char * initialPointer = openGLMat.data;
|
||||
openGLMat.data=(unsigned char * ) openGLFrame;
|
||||
|
||||
cv::cvtColor(openGLMat,openGLAllInOneFramePermanentMat,cv::COLOR_RGB2BGR);
|
||||
//cv::imshow("OpenGL",openGLAllInOneFramePermanentMat);
|
||||
openGLMatForVisualization = &openGLAllInOneFramePermanentMat;
|
||||
openGLMat.data=initialPointer;
|
||||
}
|
||||
//=====================================================================
|
||||
}
|
||||
|
||||
if (openGLMatForVisualization!=0)
|
||||
{
|
||||
cv::Mat * glMat = (cv::Mat *) openGLMatForVisualization;
|
||||
//float alpha=0.3;
|
||||
//image=cv::max(*glMat,image);
|
||||
|
||||
//example use with black borders along the right hand side and top:
|
||||
cv::Mat offsetImage = offsetImageWithPadding(*glMat, +offsetX, 0 , Scalar(0,0,0));
|
||||
image=overlay(image,offsetImage);
|
||||
//image=cv::max(offsetImage,image);
|
||||
//cv::addWeighted(offsetImage,1.0,image,0.8,0.0,image);
|
||||
//cv::add(offsetImage,image,image);
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//This is the 2D visualization sitting on top of the RGB image
|
||||
//fprintf(stderr,"2D Visualization skeleton(%0.2f,%0.2f) rendered on %ux%u image\n",skeleton->width,skeleton->height,image.size().width,image.size().height);
|
||||
visualizeSkeletonSerialized(
|
||||
image,
|
||||
skeleton,
|
||||
(mnet->leftHand.loadedModels>0),
|
||||
(mnet->rightHand.loadedModels>0),
|
||||
options->doFace,
|
||||
0,0,
|
||||
image.size().width,
|
||||
image.size().height
|
||||
);
|
||||
|
||||
|
||||
//Switch that controls drawing skeleton labels
|
||||
int draw3DSkeletonJointLabels = 0;
|
||||
|
||||
//This is the 3D skeleton visualized to match the RGB image
|
||||
drawSkeleton(image,points2DOutputGUIRealView,offsetX,offsetY,draw3DSkeletonJointLabels);
|
||||
|
||||
//Uncomment to spawn an extra window with a centered skeleton..!
|
||||
//extraWindow(points2DOutputGUIRealView,points2DOutputGUIForcedView);
|
||||
|
||||
//If you dont want to see widgets just turn them off using this switch
|
||||
int showWidgets = 1;
|
||||
|
||||
|
||||
if (showWidgets)
|
||||
{
|
||||
int borderToScreen = 15;
|
||||
int NSDMWidth=160; //body leftHand rightHand
|
||||
int NSDMHeight=160;
|
||||
|
||||
int positionX = image.size().width - NSDMWidth - borderToScreen;
|
||||
int positionY = 40;
|
||||
|
||||
cv::rectangle(image,cv::Rect(positionX-20,positionY-40,NSDMWidth+40,620+showFramerate),cv::Scalar(0,0,0),-1);
|
||||
|
||||
visualizeNSDM(image,"Upper Body",mnet->upperBody.NSDM,1 /*angles*/,positionX,positionY,NSDMWidth,NSDMHeight);
|
||||
positionY+=200;
|
||||
visualizeNSDM(image,"Lower Body",mnet->lowerBody.NSDM,1 /*angles*/,positionX,positionY,NSDMWidth,NSDMHeight);
|
||||
positionY+=200;
|
||||
|
||||
|
||||
if ( (mnet->leftHand.loadedModels>0) || (mnet->rightHand.loadedModels>0) )
|
||||
{
|
||||
int positionLX = borderToScreen;
|
||||
int positionLY = 40;
|
||||
cv::rectangle(image,cv::Rect(positionLX-20,positionLY-40,NSDMWidth+40,420),cv::Scalar(0,0,0),-1);
|
||||
|
||||
visualizeNSDM(image,"Left Hand",mnet->leftHand.NSDM,1 /*angles*/,positionLX,positionLY,NSDMWidth,NSDMHeight);
|
||||
positionLY+=200;
|
||||
visualizeNSDM(image,"Right Hand",mnet->rightHand.NSDM,1 /*angles*/,positionLX,positionLY,NSDMWidth,NSDMHeight);
|
||||
positionLY+=200;
|
||||
}
|
||||
|
||||
|
||||
visualizeOrientation(
|
||||
image,"Orientation",
|
||||
mnet->currentSolution[4],
|
||||
mnet->orientationClassifications[0],
|
||||
mnet->orientationClassifications[1],
|
||||
mnet->orientationClassifications[2],
|
||||
mnet->orientationClassifications[3],
|
||||
positionX,
|
||||
positionY,
|
||||
NSDMWidth,
|
||||
NSDMHeight
|
||||
);
|
||||
|
||||
|
||||
if (showFramerate>0)
|
||||
{
|
||||
unsigned int framerateWidgetWidth = NSDMWidth + 40;
|
||||
unsigned int framerateWidgetHeight = NSDMHeight;
|
||||
|
||||
|
||||
//Keep framerate history
|
||||
appendToHistory(frameRateHistoryTotal,options->totalLoopFPS,framerateWidgetWidth);
|
||||
appendToHistory(frameRateIKHistory,mnet->inverseKinematicsFramerate,framerateWidgetWidth);
|
||||
appendToHistory(frameRateMNET2History,mnet->neuralNetworkFramerate,framerateWidgetWidth);
|
||||
|
||||
//Plot framerate history
|
||||
plotFloatVector(
|
||||
image,
|
||||
1,//Erase background
|
||||
frameRateHistoryTotal,
|
||||
positionX-20,
|
||||
positionY+210,
|
||||
framerateWidgetWidth, //Have same size as NSDM matrix
|
||||
framerateWidgetHeight //Have same size as NSDM matrix
|
||||
);
|
||||
/*
|
||||
//Not enough space..
|
||||
plotFloatVector(
|
||||
image,
|
||||
0,//Erase background
|
||||
frameRateIKHistory,
|
||||
positionX-20,
|
||||
positionY+210,
|
||||
framerateWidgetWidth, //Have same size as NSDM matrix
|
||||
framerateWidgetHeight //Have same size as NSDM matrix
|
||||
);
|
||||
plotFloatVector(
|
||||
image,
|
||||
0,//Erase background
|
||||
frameRateMNET2History,
|
||||
positionX-20,
|
||||
positionY+210,
|
||||
framerateWidgetWidth, //Have same size as NSDM matrix
|
||||
framerateWidgetHeight //Have same size as NSDM matrix
|
||||
); */
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
float thickness=1.7;
|
||||
int fontUsed=cv::FONT_HERSHEY_SIMPLEX;
|
||||
cv::Scalar fontColor= cv::Scalar(255,255,255);
|
||||
cv::Point txtPosition(positionX,positionY+190);
|
||||
char fpsString[128];
|
||||
|
||||
snprintf(fpsString,128,"Framerate"); //2D->3D
|
||||
cv::putText(image,fpsString,txtPosition,fontUsed,0.6,fontColor,thickness,8);
|
||||
txtPosition.y+=30;
|
||||
txtPosition.x+=10;
|
||||
|
||||
snprintf(fpsString,128,"%0.2f fps",options->totalLoopFPS);
|
||||
cv::putText(image,fpsString,txtPosition,fontUsed,0.8,fontColor,thickness,8);
|
||||
|
||||
if (
|
||||
strlen(options->message)>0
|
||||
)
|
||||
{
|
||||
txtPosition.y=60;
|
||||
txtPosition.x=30;
|
||||
fontColor= cv::Scalar(0,0,0);
|
||||
cv::putText(image,options->message,txtPosition,fontUsed,1.8,fontColor,3.0,8);
|
||||
txtPosition.x+=3;
|
||||
txtPosition.y+=3;
|
||||
fontColor= cv::Scalar(255,255,255);
|
||||
cv::putText(image,options->message,txtPosition,fontUsed,1.8,fontColor,3.0,8);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(image.data!=0)
|
||||
{
|
||||
if ( image.size().height > image.size().width )
|
||||
{
|
||||
scale=(float) 720/image.size().height;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale=(float) 1024/image.size().width;
|
||||
}
|
||||
if (scale>1.0)
|
||||
{
|
||||
scale=1.0;
|
||||
}
|
||||
if (scale!=1.0)
|
||||
{
|
||||
cv::resize(image, image, cv::Size(0,0), scale, scale);
|
||||
}
|
||||
|
||||
//fprintf(stderr,"Image ( %u x %u )\n",image.size().width,image.size().height);
|
||||
success=1;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr," Could not load %s image, cannot proceed to visualize it\n",finalFilename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (saveVisualization)
|
||||
{
|
||||
char filename[512];
|
||||
snprintf(filename,512,"vis%05u.jpg",frameNumber) ;
|
||||
cv::imwrite(filename,image);
|
||||
}
|
||||
|
||||
cv::imshow(windowName,image); //
|
||||
//Did not find a file to show ..
|
||||
return success;
|
||||
#else
|
||||
fprintf(stderr,"OpenCV code not present in this build, cannot show visualization..\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
/** @file allInOne.hpp
|
||||
* @brief Code that handles GUI output and visualization using OpenCV.
|
||||
* If OpenCV is not be available, CMake will not declare the USE_OPENCV compilation flag and the whole code will not be included.
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#if USE_OPENCV
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
|
||||
int visualizeAllInOne(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int saveVisualization,
|
||||
cv::Mat * alreadyLoadedImage,
|
||||
const char * path,
|
||||
const char * label,
|
||||
unsigned int serialLength,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
struct skeletonSerialized * skeleton,
|
||||
struct MocapNET2 * mnet,
|
||||
struct MocapNET2Options * options,
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedView,
|
||||
unsigned int numberOfMissingJoints
|
||||
);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,447 @@
|
||||
#include "camera_ready.hpp"
|
||||
#include "visualization.hpp"
|
||||
#include "drawSkeleton.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
#include "../IO/jsonRead.hpp"
|
||||
#include "../IO/bvh.hpp"
|
||||
#include "../tools.hpp"
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
|
||||
Mat getPaddedROI(const Mat &input, int top_left_x, int top_left_y, int width, int height, Scalar paddingColor)
|
||||
{
|
||||
int bottom_right_x = top_left_x + width;
|
||||
int bottom_right_y = top_left_y + height;
|
||||
|
||||
Mat output;
|
||||
if (top_left_x < 0 || top_left_y < 0 || bottom_right_x > input.cols || bottom_right_y > input.rows)
|
||||
{
|
||||
// border padding will be required
|
||||
int border_left = 0, border_right = 0, border_top = 0, border_bottom = 0;
|
||||
|
||||
if (top_left_x < 0)
|
||||
{
|
||||
width = width + top_left_x;
|
||||
border_left = -1 * top_left_x;
|
||||
top_left_x = 0;
|
||||
}
|
||||
if (top_left_y < 0)
|
||||
{
|
||||
height = height + top_left_y;
|
||||
border_top = -1 * top_left_y;
|
||||
top_left_y = 0;
|
||||
}
|
||||
if (bottom_right_x > input.cols)
|
||||
{
|
||||
width = width - (bottom_right_x - input.cols);
|
||||
border_right = bottom_right_x - input.cols;
|
||||
}
|
||||
if (bottom_right_y > input.rows)
|
||||
{
|
||||
height = height - (bottom_right_y - input.rows);
|
||||
border_bottom = bottom_right_y - input.rows;
|
||||
}
|
||||
|
||||
Rect R(top_left_x, top_left_y, width, height);
|
||||
copyMakeBorder(input(R), output, border_top, border_bottom, border_left, border_right, BORDER_CONSTANT, paddingColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no border padding required
|
||||
Rect R(top_left_x, top_left_y, width, height);
|
||||
output = input(R);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
int getBoundingBox(struct skeletonSerialized * skeleton,cv::Point & pointMinimum,cv::Point & pointMaximum,unsigned int x,unsigned int y,unsigned int width,unsigned int height)
|
||||
{
|
||||
if (skeleton==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (skeleton->skeletonBodyElements==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int jID = 3*3 ;
|
||||
|
||||
float xNormalized = (float) skeleton->skeletonBody[jID+0].value / skeleton->width;
|
||||
float yNormalized = (float) skeleton->skeletonBody[jID+1].value / skeleton->height;
|
||||
|
||||
int performedUpdate=0;
|
||||
pointMinimum.x = width;//x+xNormalized*width;
|
||||
pointMinimum.y = height;//y+yNormalized*height;
|
||||
pointMaximum.x = 0;//x+xNormalized*width;
|
||||
pointMaximum.y = 0;//y+yNormalized*height;
|
||||
|
||||
for (int jointID=3; jointID<skeleton->skeletonBodyElements/3; jointID++)
|
||||
{
|
||||
jID = jointID*3 ;
|
||||
|
||||
xNormalized = (float) skeleton->skeletonBody[jID+0].value / skeleton->width;
|
||||
yNormalized = (float) skeleton->skeletonBody[jID+1].value / skeleton->height;
|
||||
|
||||
if ( (xNormalized>0.0) && (yNormalized>0.0) )
|
||||
{
|
||||
unsigned int fX = x+xNormalized*width;
|
||||
unsigned int fY = y+yNormalized*height;
|
||||
|
||||
if (fX<pointMinimum.x)
|
||||
{
|
||||
pointMinimum.x = fX;
|
||||
performedUpdate=1;
|
||||
}
|
||||
if (fY<pointMinimum.y)
|
||||
{
|
||||
pointMinimum.y = fY;
|
||||
performedUpdate=1;
|
||||
}
|
||||
|
||||
if (fX>pointMaximum.x)
|
||||
{
|
||||
pointMaximum.x = fX;
|
||||
performedUpdate=1;
|
||||
}
|
||||
if (fY>pointMaximum.y)
|
||||
{
|
||||
pointMaximum.y = fY;
|
||||
performedUpdate=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return performedUpdate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int visualizeCameraReady(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int saveVisualization,
|
||||
cv::Mat * alreadyLoadedImage,
|
||||
const char * path,
|
||||
const char * label,
|
||||
unsigned int serialLength,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
struct skeletonSerialized * skeleton,
|
||||
struct MocapNET2 * mnet,
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedViewSide,
|
||||
unsigned int numberOfMissingJoints
|
||||
)
|
||||
{
|
||||
if (points2DOutputGUIRealView.size()==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (points2DOutputGUIForcedView.size()==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (points2DOutputGUIForcedViewSide.size()==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (path==0)
|
||||
{
|
||||
fprintf(stderr,"Can't visualize input without path to RGB images\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if USE_OPENCV
|
||||
int success=0;
|
||||
char finalFilename[2048]= {0};
|
||||
cv::Mat raytraced;
|
||||
|
||||
|
||||
snprintf(finalFilename,256,"%s/raytraced2/%04u.png",path,frameNumber);
|
||||
raytraced = imread(finalFilename,cv::IMREAD_COLOR); // older versions might want the CV_LOAD_IMAGE_COLOR flag
|
||||
|
||||
if (alreadyLoadedImage==0)
|
||||
{
|
||||
|
||||
char formatString[256]= {0};
|
||||
snprintf(formatString,256,"%%s/%%s%%0%uu.jpg",serialLength);
|
||||
|
||||
//colorFrame_0_00001.jpg
|
||||
snprintf(finalFilename,2048,formatString,path,label,frameNumber/*Frame ID*/);
|
||||
//snprintf(finalFilename,2048,"%s/colorFrame_0_%05d.jpg",path,frameNumber+1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
float scale=1.0;
|
||||
cv::Mat image;
|
||||
cv::Rect roi;
|
||||
cv::Mat destinationROI;
|
||||
|
||||
if ( (fileExists(finalFilename) ) || (alreadyLoadedImage!=0) )
|
||||
{
|
||||
if (alreadyLoadedImage!=0)
|
||||
{
|
||||
image = *alreadyLoadedImage;
|
||||
|
||||
if (
|
||||
( image.size().width < 640 ) ||
|
||||
( image.size().height < 480 )
|
||||
)
|
||||
{
|
||||
fprintf(stderr,"Very small given frame ( %ux%u..\n",image.size().width,image.size().height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//cv::imshow(windowName,image); //
|
||||
//cv::waitKey(0);
|
||||
}
|
||||
else
|
||||
if (fileExists(finalFilename) )
|
||||
{
|
||||
image = imread(finalFilename,cv::IMREAD_COLOR); // older versions might want the CV_LOAD_IMAGE_COLOR flag
|
||||
}
|
||||
|
||||
|
||||
if(image.data!=0)
|
||||
{
|
||||
if ( image.size().height > image.size().width )
|
||||
{
|
||||
scale=(float) 720/image.size().height;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale=(float) 1024/image.size().width;
|
||||
}
|
||||
if (scale>1.0)
|
||||
{
|
||||
scale=1.0;
|
||||
}
|
||||
if (scale!=1.0)
|
||||
{
|
||||
cv::resize(image, image, cv::Size(0,0), scale, scale);
|
||||
}
|
||||
|
||||
//fprintf(stderr,"Image ( %u x %u )\n",image.size().width,image.size().height);
|
||||
success=1;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr," Could not load %s image, cannot proceed to visualize it\n",finalFilename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (image.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//int offsetX=950;
|
||||
int offsetX=650;
|
||||
//cv::Mat visualization(image.size().height,offsetX+image.size().width, CV_8UC3, Scalar(0,0,0));
|
||||
cv::Mat visualization(1080,1920, CV_8UC3, Scalar(255,255,255));
|
||||
|
||||
//fprintf(stderr,"Visualization will be ( %u x %u )\n",visualization.size().width,visualization.size().height);
|
||||
roi = cv::Rect( cv::Point(offsetX,0 ), cv::Size( image.size().width, image.size().height ));
|
||||
destinationROI = visualization( roi );
|
||||
//image.copyTo( destinationROI );
|
||||
|
||||
|
||||
|
||||
//visualizeInput2DSkeletonFromSkeletonSerialized(visualization,skeleton,offsetX,0, image.size().width,image.size().height);
|
||||
|
||||
//==================================================================================
|
||||
unsigned int bbSizeWidth = 700;
|
||||
unsigned int bbSizeHeight = 800;
|
||||
|
||||
visualizeSkeletonSerialized(
|
||||
image,
|
||||
skeleton,
|
||||
(mnet->leftHand.loadedModels>0),
|
||||
(mnet->rightHand.loadedModels>0),
|
||||
mnet->options->doFace,
|
||||
0,0,
|
||||
image.size().width,
|
||||
image.size().height
|
||||
);
|
||||
|
||||
cv::Point ptMin(0,0),ptMax(0,0);
|
||||
if ( getBoundingBox(skeleton,ptMin,ptMax,offsetX,0, image.size().width,image.size().height) )
|
||||
{
|
||||
//cv::rectangle(visualization,pt1,pt2,cv::Scalar(0,0,0),-1,8,0);
|
||||
ptMin.x -= offsetX;
|
||||
ptMax.x -= offsetX;
|
||||
|
||||
if (ptMin.x >= 20)
|
||||
{
|
||||
ptMin.x-=20;
|
||||
}
|
||||
if (ptMin.y >= 20)
|
||||
{
|
||||
ptMin.y-=20;
|
||||
}
|
||||
if (ptMax.x <= image.size().width+20)
|
||||
{
|
||||
ptMax.x+=20;
|
||||
}
|
||||
if (ptMax.y <= image.size().height+20)
|
||||
{
|
||||
ptMax.y+=20;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ptMin.x=0;
|
||||
ptMax.x=image.size().width-1;
|
||||
ptMin.y=0;
|
||||
ptMax.y=image.size().height-1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
roi = cv::Rect(ptMin, cv::Size(ptMax.x-ptMin.x,ptMax.y-ptMin.y));
|
||||
//cv::Mat imageROI = image( roi );
|
||||
cv::Mat imageROI = getPaddedROI(image,ptMin.x,ptMin.y,ptMax.x-ptMin.x,ptMax.y-ptMin.y,cv::Scalar(123,123,123));
|
||||
|
||||
/*
|
||||
float ratio = (float) imageROI.size().height / 800;
|
||||
unsigned int originalImageWidth=(unsigned int) imageROI.size().width * ratio;
|
||||
unsigned int originalImageHeight=(unsigned int) imageROI.size().height * ratio;
|
||||
cv::resize(imageROI,imageROI,cv::Size(originalImageWidth,originalImageHeight));
|
||||
*/
|
||||
|
||||
unsigned int tX = offsetX + 820 - ((unsigned int) ptMax.x-ptMin.x / 2);
|
||||
unsigned int tY = 600 - ( (unsigned int) ptMax.y-ptMin.y / 2 );
|
||||
|
||||
if (tX + ptMax.x-ptMin.x > 1920 )
|
||||
{
|
||||
tX=0;
|
||||
}
|
||||
if (tY + ptMax.y-ptMin.y > 1920 )
|
||||
{
|
||||
tY=0;
|
||||
}
|
||||
|
||||
fprintf(stderr,"tx=%u,ty=%u\n",tX,tY);
|
||||
cv::Point targetPosition(tX,tY);
|
||||
roi = cv::Rect(targetPosition, cv::Size(ptMax.x-ptMin.x,ptMax.y-ptMin.y));
|
||||
|
||||
//destinationROI = visualization( roi );
|
||||
destinationROI = getPaddedROI(visualization,roi.x,roi.y,ptMax.x-ptMin.x,ptMax.y-ptMin.y,cv::Scalar(255,255,255));
|
||||
cv::addWeighted(destinationROI,0.0, imageROI, 1.0, 0.0, destinationROI);
|
||||
//==================================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cv::Point pt1(offsetX,0);
|
||||
cv::Point pt2(offsetX+00,image.size().height);
|
||||
//cv::rectangle(visualization,pt1,pt2,cv::Scalar(0,0,0),-1,8,0);
|
||||
|
||||
cv::Scalar color= cv::Scalar(123,123,123,123 /*Transparency here , although if the cv::Mat does not have an alpha channel it is useless*/);
|
||||
cv::Scalar black= cv::Scalar(0,0,0,0 /*Transparency here , although if the cv::Mat does not have an alpha channel it is useless*/);
|
||||
cv::Point txtPosition;
|
||||
txtPosition.y=30;
|
||||
float thickness=2.2;
|
||||
int fontUsed=cv::FONT_HERSHEY_SIMPLEX;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//FORCE VIEW..!
|
||||
//numberOfMissingJoints=0;
|
||||
|
||||
if (numberOfMissingJoints>40)
|
||||
{
|
||||
txtPosition.x=60;
|
||||
txtPosition.y=350;
|
||||
cv::putText(visualization,"Incomplete Data..!",txtPosition,fontUsed,1.8,color,thickness,8);
|
||||
}
|
||||
else
|
||||
{
|
||||
txtPosition.x=100;
|
||||
//cv::putText(visualization,"Front View",txtPosition,fontUsed,1.1,color,thickness,8);
|
||||
|
||||
txtPosition.x=400;
|
||||
//cv::putText(visualization,"Side View",txtPosition,fontUsed,1.1,color,thickness,8);
|
||||
|
||||
|
||||
drawSkeleton(visualization,points2DOutputGUIForcedView,-730,-230,0);
|
||||
drawSkeleton(visualization,points2DOutputGUIForcedViewSide,-450,-230,0);
|
||||
}
|
||||
|
||||
|
||||
scaleSkeleton(points2DOutputGUIRealView,scale,scale);
|
||||
//drawSkeleton(visualization,points2DOutputGUIRealView,offsetX-100,0,0);
|
||||
|
||||
|
||||
if (!raytraced.empty())
|
||||
{
|
||||
unsigned int clipSizeWidth = 700;
|
||||
unsigned int clipSizeHeight = 800;
|
||||
cv::Mat clippedRaytraced;
|
||||
roi = cv::Rect( cv::Point(600,150),cv::Size(clipSizeWidth,clipSizeHeight));
|
||||
clippedRaytraced = raytraced(roi);
|
||||
|
||||
clipSizeWidth=(unsigned int) clipSizeWidth*0.6;
|
||||
clipSizeHeight=(unsigned int) clipSizeHeight*0.6;
|
||||
cv::resize(clippedRaytraced,clippedRaytraced,cv::Size(clipSizeWidth,clipSizeHeight));
|
||||
|
||||
cv::Mat clippedVisualization;
|
||||
roi = cv::Rect( cv::Point(1380,100),cv::Size(clipSizeWidth,clipSizeHeight));
|
||||
clippedVisualization = visualization(roi);
|
||||
|
||||
cv::addWeighted(clippedVisualization,0.0, clippedRaytraced, 1.0, 0.0, clippedVisualization);
|
||||
}
|
||||
|
||||
|
||||
int NSDMWidth=160; //body leftHand rightHand
|
||||
int NSDMHeight=160;
|
||||
|
||||
int positionY = 80;
|
||||
visualizeNSDM(visualization,"Upper Body",mnet->upperBody.NSDM,1 /*angles*/,770,positionY,NSDMWidth,NSDMHeight);
|
||||
positionY+=200;
|
||||
visualizeNSDM(visualization,"Lower Body",mnet->lowerBody.NSDM,1 /*angles*/,770,positionY,NSDMWidth,NSDMHeight);
|
||||
positionY+=200;
|
||||
|
||||
visualizeOrientation(
|
||||
visualization,"Orientation",
|
||||
mnet->currentSolution[4], //Orientation value
|
||||
mnet->orientationClassifications[0],
|
||||
mnet->orientationClassifications[1],
|
||||
mnet->orientationClassifications[2],
|
||||
mnet->orientationClassifications[3],
|
||||
770,
|
||||
positionY,
|
||||
NSDMWidth,
|
||||
NSDMHeight
|
||||
);
|
||||
|
||||
|
||||
cv::imshow(windowName,visualization); //
|
||||
|
||||
if (saveVisualization)
|
||||
{
|
||||
char filename[1024];
|
||||
snprintf(filename,1024,"cr%05u.jpg",frameNumber);
|
||||
imwrite(filename,visualization);
|
||||
}
|
||||
|
||||
//Did not find a file to show ..
|
||||
return success;
|
||||
#else
|
||||
fprintf(stderr,"OpenCV code not present in this build, cannot show visualization..\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
/** @file camera_ready.hpp
|
||||
* @brief Code that handles GUI output and visualization using OpenCV.
|
||||
* If OpenCV is not be available, CMake will not declare the USE_OPENCV compilation flag and the whole code will not be included.
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#if USE_OPENCV
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
|
||||
int visualizeCameraReady(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int saveVisualization,
|
||||
cv::Mat * alreadyLoadedImage,
|
||||
const char * path,
|
||||
const char * label,
|
||||
unsigned int serialLength,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
struct skeletonSerialized * skeleton,
|
||||
struct MocapNET2 * mnet,
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedViewSide,
|
||||
unsigned int numberOfMissingJoints
|
||||
);
|
||||
#endif
|
||||
@@ -0,0 +1,851 @@
|
||||
#include "drawSkeleton.hpp"
|
||||
|
||||
|
||||
#if USE_OPENCV
|
||||
#if USE_BVH
|
||||
#include "../IO/bvh.hpp"
|
||||
|
||||
#define GOOFY_EYES 0
|
||||
|
||||
|
||||
void drawCircleIfPointsExist(cv::Mat &outputMat,cv::Point point,float radious,cv::Scalar color,float thickness)
|
||||
{
|
||||
if ( (point.x!=0) || (point.y!=0) )
|
||||
{
|
||||
cv::circle(outputMat,point,radious,color,thickness,8,0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void drawLineIfPointsExist(cv::Mat &outputMat,cv::Point start,cv::Point finish,cv::Scalar color,float thickness)
|
||||
{
|
||||
if ( ( (start.x!=0) || (start.y!=0) ) && ( (finish.x!=0) || (finish.y!=0) ) )
|
||||
{
|
||||
cv::line(outputMat,start,finish,color,thickness);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int visualizeSkeletonSerialized(
|
||||
cv::Mat &outputMat,
|
||||
struct skeletonSerialized * skeleton,
|
||||
unsigned int drawLeftFingers,
|
||||
unsigned int drawRightFingers,
|
||||
unsigned int drawFace,
|
||||
unsigned int x,unsigned int y,
|
||||
unsigned int width,unsigned int height
|
||||
)
|
||||
{
|
||||
/*
|
||||
fprintf(stderr,"Visualize %u,%u - Skeleton ",skeletonWidth,skeletonHeight);
|
||||
fprintf(stderr,"Offset %u,%u - ",x,y);
|
||||
fprintf(stderr,"Joints %u - ",skeleton->skeletonBodyElements);
|
||||
fprintf(stderr,"Dimensions %u,%u \n ",width,height);
|
||||
char filename[512];
|
||||
*/
|
||||
|
||||
#if USE_TRANSPARENCY
|
||||
cv::Mat base;
|
||||
cv::Mat overlay(outputMat.size().height,outputMat.size().width, CV_8UC3, Scalar(0,0,0));
|
||||
outputMat.copyTo(base);
|
||||
cv::Mat * baseP = &base;
|
||||
cv::Mat * overlayP = &overlay ;
|
||||
cv::Mat * outputP = &outputMat;
|
||||
#else
|
||||
//Not using transparency you just write everything on output
|
||||
//and get rid of the add weighted last step that takes 6% of CPU time
|
||||
cv::Mat * baseP = &outputMat;
|
||||
cv::Mat * overlayP = &outputMat ;
|
||||
cv::Mat * outputP = &outputMat;
|
||||
#endif
|
||||
|
||||
cv::Scalar color = cv::Scalar(0,255,255);
|
||||
cv::Point pt1 = cv::Point(x,y);
|
||||
cv::Point pt2 = cv::Point(x+width,y+height);
|
||||
cv::rectangle(*overlayP, pt1, pt2, color);
|
||||
|
||||
float thickness=1.0;
|
||||
int fontUsed=cv::FONT_HERSHEY_SIMPLEX;
|
||||
|
||||
unsigned int pointsThatExist=0;
|
||||
unsigned int pointsThatSeemToBeWronglyNormalized=0;
|
||||
|
||||
|
||||
//Uncomment for a string to jID match
|
||||
//for (int jointID=3; jointID<skeleton->skeletonBodyElements; jointID++)
|
||||
// {
|
||||
// fprintf(stderr,"skeleton[%u]=%s\n",jointID,skeleton->skeletonHeader[jointID].str);
|
||||
// }
|
||||
|
||||
cv::Scalar faceColor(255,255,0);
|
||||
cv::Scalar rightColor(0,255,0);
|
||||
cv::Scalar leftColor(0,0,255);
|
||||
|
||||
float faceThickness=2.0;
|
||||
float fingerThickness=2.0;
|
||||
float bodyThickness=2.0;
|
||||
|
||||
|
||||
for (int jointID=3; jointID<skeleton->skeletonBodyElements/3; jointID++)
|
||||
{
|
||||
unsigned int jID = jointID*3;
|
||||
|
||||
float pointExists = skeleton->skeletonBody[jID+2].value;
|
||||
|
||||
if (pointExists>0.0)
|
||||
{
|
||||
float xNormalized = (float) skeleton->skeletonBody[jID+0].value / skeleton->width;
|
||||
float yNormalized = (float) skeleton->skeletonBody[jID+1].value / skeleton->height;
|
||||
|
||||
if ( (xNormalized!=0.0) || (yNormalized!=0.0) )
|
||||
{
|
||||
//First of all bring output point to the range of our mini
|
||||
//screen
|
||||
pt1.x = (unsigned int) (xNormalized * width);
|
||||
pt1.y = (unsigned int) (yNormalized * height);
|
||||
|
||||
//Check if we have a normalization error..!
|
||||
if ( (pt1.x>width) || (pt1.y>height) )
|
||||
{
|
||||
++pointsThatSeemToBeWronglyNormalized;
|
||||
}
|
||||
|
||||
|
||||
//Finally put the point in the target position on the overlay
|
||||
pt1.x += (unsigned int) x;
|
||||
pt1.y += (unsigned int) y;
|
||||
|
||||
//And draw it.
|
||||
cv::circle(*overlayP,pt1,1,color,1,8,0);
|
||||
++pointsThatExist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float xRatio = (float) width / skeleton->width;
|
||||
float yRatio = (float) height / skeleton->height;
|
||||
|
||||
unsigned int jID;
|
||||
|
||||
|
||||
jID=16 * 3;
|
||||
cv::Point reye(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=17 * 3;
|
||||
cv::Point leye(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=18 * 3;
|
||||
cv::Point rear(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=19 * 3;
|
||||
cv::Point lear(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
|
||||
|
||||
jID=1 * 3;
|
||||
cv::Point head(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=2 * 3;
|
||||
cv::Point neck(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
|
||||
jID=9 * 3;
|
||||
cv::Point hip(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
|
||||
jID=3 * 3;
|
||||
cv::Point rshoulder(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=4 * 3;
|
||||
cv::Point relbow(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=5 * 3;
|
||||
cv::Point rhand(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
|
||||
jID=6 * 3;
|
||||
cv::Point lshoulder(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=7 * 3;
|
||||
cv::Point lelbow(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=8 * 3;
|
||||
cv::Point lhand(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
|
||||
jID=10 * 3;
|
||||
cv::Point rhip(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=11 * 3;
|
||||
cv::Point rknee(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=12 * 3;
|
||||
cv::Point rfoot(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=25 * 3;
|
||||
cv::Point rheel(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=23 * 3;
|
||||
cv::Point rbigtoe(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=24 * 3;
|
||||
cv::Point rsmalltoe(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
|
||||
jID=13 * 3;
|
||||
cv::Point lhip(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=14 * 3;
|
||||
cv::Point lknee(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=15 * 3;
|
||||
cv::Point lfoot(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=22 * 3;
|
||||
cv::Point lheel(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=20 * 3;
|
||||
cv::Point lbigtoe(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=21 * 3;
|
||||
cv::Point lsmalltoe(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lshoulder,lelbow,leftColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,lhand,lelbow,leftColor,bodyThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rshoulder,relbow,rightColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,rhand,relbow,rightColor,bodyThickness);
|
||||
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lhip,hip,leftColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,lhip,lknee,leftColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,lknee,lfoot,leftColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,lfoot,lheel,leftColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,lfoot,lbigtoe,leftColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,lfoot,lsmalltoe,leftColor,bodyThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rhip,hip,rightColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,rhip,rknee,rightColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,rknee,rfoot,rightColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,rfoot,rheel,rightColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,rfoot,rbigtoe,rightColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,rfoot,rsmalltoe,rightColor,bodyThickness);
|
||||
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lshoulder,rshoulder,cv::Scalar(255,0,0),bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,hip,rshoulder,cv::Scalar(255,0,0),bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,hip,lshoulder,cv::Scalar(255,0,0),bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,neck,rshoulder,cv::Scalar(255,0,0),bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,neck,lshoulder,cv::Scalar(255,0,0),bodyThickness);
|
||||
|
||||
//Also draw joints
|
||||
drawCircleIfPointsExist(*overlayP,lhand,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
drawCircleIfPointsExist(*overlayP,rhand,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
drawCircleIfPointsExist(*overlayP,lshoulder,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
drawCircleIfPointsExist(*overlayP,rshoulder,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
drawCircleIfPointsExist(*overlayP,lelbow,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
drawCircleIfPointsExist(*overlayP,relbow,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
drawCircleIfPointsExist(*overlayP,lhip,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
drawCircleIfPointsExist(*overlayP,rhip,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
drawCircleIfPointsExist(*overlayP,lknee,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
drawCircleIfPointsExist(*overlayP,rknee,5,cv::Scalar(255,0,255),bodyThickness);
|
||||
|
||||
|
||||
if (drawLeftFingers)
|
||||
{
|
||||
//Left Hand
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=28 * 3;
|
||||
cv::Point lthumb(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=29 * 3;
|
||||
cv::Point lthumb1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=30 * 3;
|
||||
cv::Point lthumb2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=31 * 3;
|
||||
cv::Point lthumbES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=32 * 3;
|
||||
cv::Point lpointer(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=33 * 3;
|
||||
cv::Point lpointer1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=34 * 3;
|
||||
cv::Point lpointer2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=35 * 3;
|
||||
cv::Point lpointerES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=36 * 3;
|
||||
cv::Point lmiddle(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=37 * 3;
|
||||
cv::Point lmiddle1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=38 * 3;
|
||||
cv::Point lmiddle2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=39 * 3;
|
||||
cv::Point lmiddleES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=40 * 3;
|
||||
cv::Point lring(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=41 * 3;
|
||||
cv::Point lring1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=42 * 3;
|
||||
cv::Point lring2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=43 * 3;
|
||||
cv::Point lringES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=44 * 3;
|
||||
cv::Point lpinky(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=45 * 3;
|
||||
cv::Point lpinky1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=46 * 3;
|
||||
cv::Point lpinky2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=47 * 3;
|
||||
cv::Point lpinkyES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lhand,lthumb,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lhand,lpointer,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lhand,lmiddle,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lhand,lring,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lhand,lpinky,leftColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lthumb,lthumb1,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lthumb1,lthumb2,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lthumb2,lthumbES,leftColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lpointer,lpointer1,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lpointer1,lpointer2,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lpointer2,lpointerES,leftColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lmiddle,lmiddle1,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lmiddle1,lmiddle2,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lmiddle2,lmiddleES,leftColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lring,lring1,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lring1,lring2,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lring2,lringES,leftColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lpinky,lpinky1,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lpinky1,lpinky2,leftColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,lpinky2,lpinkyES,leftColor,fingerThickness);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (drawRightFingers)
|
||||
{
|
||||
//Right Hand
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=49 * 3;
|
||||
cv::Point rthumb(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=50 * 3;
|
||||
cv::Point rthumb1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=51 * 3;
|
||||
cv::Point rthumb2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=52 * 3;
|
||||
cv::Point rthumbES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=53 * 3;
|
||||
cv::Point rpointer(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=54 * 3;
|
||||
cv::Point rpointer1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=55 * 3;
|
||||
cv::Point rpointer2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=56 * 3;
|
||||
cv::Point rpointerES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=57 * 3;
|
||||
cv::Point rmiddle(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=58 * 3;
|
||||
cv::Point rmiddle1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=59 * 3;
|
||||
cv::Point rmiddle2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=60 * 3;
|
||||
cv::Point rmiddleES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=61 * 3;
|
||||
cv::Point rring(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=62 * 3;
|
||||
cv::Point rring1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=63 * 3;
|
||||
cv::Point rring2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=64 * 3;
|
||||
cv::Point rringES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=65 * 3;
|
||||
cv::Point rpinky(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=66 * 3;
|
||||
cv::Point rpinky1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=67 * 3;
|
||||
cv::Point rpinky2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=68 * 3;
|
||||
cv::Point rpinkyES(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value); //EndSite
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rhand,rthumb,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rhand,rpointer,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rhand,rmiddle,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rhand,rring,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rhand,rpinky,rightColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rthumb,rthumb1,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rthumb1,rthumb2,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rthumb2,rthumbES,rightColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rpointer,rpointer1,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rpointer1,rpointer2,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rpointer2,rpointerES,rightColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rmiddle,rmiddle1,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rmiddle1,rmiddle2,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rmiddle2,rmiddleES,rightColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rring,rring1,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rring1,rring2,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rring2,rringES,rightColor,fingerThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rpinky,rpinky1,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rpinky1,rpinky2,rightColor,fingerThickness);
|
||||
drawLineIfPointsExist(*overlayP,rpinky2,rpinkyES,rightColor,fingerThickness);
|
||||
}
|
||||
|
||||
|
||||
if (drawFace)
|
||||
{
|
||||
//Face
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=69 * 3;
|
||||
cv::Point rchin0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=70 * 3;
|
||||
cv::Point rchin1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=71 * 3;
|
||||
cv::Point rchin2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=72 * 3;
|
||||
cv::Point rchin3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=73 * 3;
|
||||
cv::Point rchin4(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=74 * 3;
|
||||
cv::Point rchin5(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=75 * 3;
|
||||
cv::Point rchin6(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=76 * 3;
|
||||
cv::Point rchin7(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=77 * 3;
|
||||
cv::Point rchin(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=78 * 3;
|
||||
cv::Point lchin7(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=79 * 3;
|
||||
cv::Point lchin6(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=80 * 3;
|
||||
cv::Point lchin5(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=81 * 3;
|
||||
cv::Point lchin4(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=82 * 3;
|
||||
cv::Point lchin3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=83 * 3;
|
||||
cv::Point lchin2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=84 * 3;
|
||||
cv::Point lchin1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=85 * 3;
|
||||
cv::Point lchin0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rchin0,rchin1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,rchin1,rchin2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,rchin3,rchin4,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,rchin4,rchin5,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,rchin5,rchin6,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,rchin6,rchin7,faceColor,faceThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,rchin7,rchin,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,rchin,lchin7,faceColor,faceThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,lchin0,lchin1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,lchin1,lchin2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,lchin3,lchin4,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,lchin4,lchin5,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,lchin5,lchin6,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,lchin6,lchin7,faceColor,faceThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,neck,rchin,cv::Scalar(255,0,0),bodyThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,neck,rchin,cv::Scalar(255,0,0),bodyThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,neck,rchin,faceColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,rear,rchin2,faceColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,lear,lchin2,faceColor,bodyThickness);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=86 * 3;
|
||||
cv::Point reyebrow0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=87 * 3;
|
||||
cv::Point reyebrow1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=88 * 3;
|
||||
cv::Point reyebrow2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=89 * 3;
|
||||
cv::Point reyebrow3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=90 * 3;
|
||||
cv::Point reyebrow4(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=91 * 3;
|
||||
cv::Point leyebrow4(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=92 * 3;
|
||||
cv::Point leyebrow3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=93 * 3;
|
||||
cv::Point leyebrow2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=94 * 3;
|
||||
cv::Point leyebrow1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=95 * 3;
|
||||
cv::Point leyebrow0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
drawLineIfPointsExist(*overlayP,reyebrow0,reyebrow1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,reyebrow1,reyebrow2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,reyebrow2,reyebrow3,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,reyebrow3,reyebrow4,faceColor,faceThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,leyebrow0,leyebrow1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,leyebrow1,leyebrow2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,leyebrow2,leyebrow3,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,leyebrow3,leyebrow4,faceColor,faceThickness);
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=96 * 3;
|
||||
cv::Point nosebone0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=97 * 3;
|
||||
cv::Point nosebone1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=98 * 3;
|
||||
cv::Point nosebone2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=99 * 3;
|
||||
cv::Point nosebone3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=100 * 3;
|
||||
cv::Point nostrills0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=101 * 3;
|
||||
cv::Point nostrills1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=102 * 3;
|
||||
cv::Point nostrills2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=103 * 3;
|
||||
cv::Point nostrills3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=104 * 3;
|
||||
cv::Point nostrills4(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
|
||||
|
||||
drawLineIfPointsExist(*overlayP,nosebone0,nosebone1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,nosebone1,nosebone2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,nosebone2,nosebone3,faceColor,faceThickness);
|
||||
|
||||
drawLineIfPointsExist(*overlayP,nostrills0,nostrills1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,nostrills1,nostrills2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,nostrills2,nostrills3,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,nostrills3,nostrills4,faceColor,faceThickness);
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=105 * 3;
|
||||
cv::Point reye0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=106 * 3;
|
||||
cv::Point reye1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=107 * 3;
|
||||
cv::Point reye2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=108 * 3;
|
||||
cv::Point reye3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=109 * 3;
|
||||
cv::Point reye4(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=110 * 3;
|
||||
cv::Point reye5(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
drawLineIfPointsExist(*overlayP,reye0,reye1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,reye1,reye2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,reye2,reye3,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,reye3,reye4,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,reye4,reye5,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,reye0,reye5,faceColor,faceThickness);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=111 * 3;
|
||||
cv::Point leye0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=112 * 3;
|
||||
cv::Point leye1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=113 * 3;
|
||||
cv::Point leye2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=114 * 3;
|
||||
cv::Point leye3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=115 * 3;
|
||||
cv::Point leye4(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=116 * 3;
|
||||
cv::Point leye5(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
drawLineIfPointsExist(*overlayP,leye0,leye1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,leye1,leye2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,leye2,leye3,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,leye3,leye4,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,leye4,leye5,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,leye0,leye5,faceColor,faceThickness);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=117 * 3;
|
||||
cv::Point outmouth0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=118 * 3;
|
||||
cv::Point outmouth1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=119 * 3;
|
||||
cv::Point outmouth2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=120 * 3;
|
||||
cv::Point outmouth3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=121 * 3;
|
||||
cv::Point outmouth4(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=122 * 3;
|
||||
cv::Point outmouth5(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=123 * 3;
|
||||
cv::Point outmouth6(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=124 * 3;
|
||||
cv::Point outmouth7(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=125 * 3;
|
||||
cv::Point outmouth8(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=126 * 3;
|
||||
cv::Point outmouth9(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=127 * 3;
|
||||
cv::Point outmouth10(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=128 * 3;
|
||||
cv::Point outmouth11(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
drawLineIfPointsExist(*overlayP,outmouth0,outmouth1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth1,outmouth2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth2,outmouth3,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth3,outmouth4,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth4,outmouth5,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth5,outmouth6,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth6,outmouth7,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth7,outmouth8,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth8,outmouth9,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth9,outmouth10,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth10,outmouth11,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,outmouth11,outmouth0,faceColor,faceThickness);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
jID=129 * 3;
|
||||
cv::Point inmouth0(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=130 * 3;
|
||||
cv::Point inmouth1(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=131 * 3;
|
||||
cv::Point inmouth2(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=132 * 3;
|
||||
cv::Point inmouth3(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=133 * 3;
|
||||
cv::Point inmouth4(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=134 * 3;
|
||||
cv::Point inmouth5(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=135 * 3;
|
||||
cv::Point inmouth6(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
jID=136 * 3;
|
||||
cv::Point inmouth7(x+xRatio*skeleton->skeletonBody[jID+0].value,y+yRatio*skeleton->skeletonBody[jID+1].value);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
drawLineIfPointsExist(*overlayP,inmouth0,inmouth1,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,inmouth1,inmouth2,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,inmouth2,inmouth3,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,inmouth3,inmouth4,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,inmouth4,inmouth5,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,inmouth5,inmouth6,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,inmouth6,inmouth7,faceColor,faceThickness);
|
||||
drawLineIfPointsExist(*overlayP,inmouth7,inmouth0,faceColor,faceThickness);
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#if GOOFY_EYES
|
||||
cv::circle(*overlayP,reye,6,cv::Scalar(255,255,255),faceThickness,8,0);
|
||||
cv::circle(*overlayP,reye,3,cv::Scalar(0,0,0),faceThickness,8,0);
|
||||
cv::circle(*overlayP,leye,6,cv::Scalar(255,255,255),faceThickness,8,0);
|
||||
cv::circle(*overlayP,leye,3,cv::Scalar(0,0,0),faceThickness,8,0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
drawLineIfPointsExist(*overlayP,reye,head,faceColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,leye,head,faceColor,bodyThickness);
|
||||
drawLineIfPointsExist(*overlayP,neck,head,faceColor,bodyThickness);
|
||||
|
||||
#if GOOFY_EYES
|
||||
cv::circle(*overlayP,reye,6,cv::Scalar(255,255,255),faceThickness,8,0);
|
||||
cv::circle(*overlayP,reye,3,cv::Scalar(0,0,0),faceThickness,8,0);
|
||||
cv::circle(*overlayP,leye,6,cv::Scalar(255,255,255),faceThickness,8,0);
|
||||
cv::circle(*overlayP,leye,3,cv::Scalar(0,0,0),faceThickness,8,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
thickness=1.0;
|
||||
|
||||
if (pointsThatSeemToBeWronglyNormalized>0)
|
||||
{
|
||||
fprintf(stderr,"visualizeInput2DSkeletonFromSkeletonSerialized %u points seem to be incorrectly normalized\n",pointsThatSeemToBeWronglyNormalized);
|
||||
fprintf(stderr,"signaled units are %0.2f x %0.2f \n",skeleton->width,skeleton->height);
|
||||
}
|
||||
|
||||
|
||||
if (pointsThatExist==0)
|
||||
{
|
||||
pt1.x=x+10;
|
||||
pt1.y=y+10;
|
||||
cv::putText(*overlayP,"No Valid 2D Points available",pt1,fontUsed,0.4,color,thickness,8);
|
||||
}
|
||||
|
||||
if (pointsThatSeemToBeWronglyNormalized>0)
|
||||
{
|
||||
pt1.x=x+10;
|
||||
pt1.y=y+30;
|
||||
cv::putText(*overlayP,"Invalid Normalized Input Points",pt1,fontUsed,0.4,color,thickness,8);
|
||||
}
|
||||
|
||||
#if USE_TRANSPARENCY
|
||||
cv::addWeighted(*baseP,1.0, *overlayP, 0.5, 0.0, *outputMatP);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int drawSkeleton(cv::Mat &outputMat,std::vector<std::vector<float> > points2DOutputGUIForcedView,float offsetX,float offsetY,int labels)
|
||||
{
|
||||
if (points2DOutputGUIForcedView.size()==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
for (int jointID=0; jointID<points2DOutputGUIForcedView.size(); jointID++)
|
||||
{
|
||||
float jointPointX = points2DOutputGUIForcedView[jointID][0]+offsetX;
|
||||
float jointPointY = points2DOutputGUIForcedView[jointID][1]+offsetY;
|
||||
cv::Point jointPoint(jointPointX,jointPointY);
|
||||
//fprintf(stderr,"L x,y %0.2f,%0.2f \n",jointPointX,jointPointY);
|
||||
int isBasicBodyComponent=0;
|
||||
|
||||
if ( (jointPointX!=0) && (jointPointY!=0) )
|
||||
{
|
||||
//unsigned int parentID = Body25SkeletonJointsParentRelationMap[jointID];
|
||||
unsigned int parentID = getBVHParentJoint(jointID);
|
||||
if (parentID!=jointID)
|
||||
{
|
||||
if (parentID<points2DOutputGUIForcedView.size())
|
||||
{
|
||||
float parentPointX = points2DOutputGUIForcedView[parentID][0]+offsetX;
|
||||
float parentPointY = points2DOutputGUIForcedView[parentID][1]+offsetY;
|
||||
cv::Point parentPoint(parentPointX,parentPointY);
|
||||
|
||||
cv::Scalar color = cv::Scalar(255,0,0);
|
||||
const char * jointName = getBVHJointName(jointID);
|
||||
const char * parentName = getBVHJointName(parentID);
|
||||
if ( (parentName!=0) && (jointName!=0) )
|
||||
{
|
||||
/* //Default is Blue so don't need to spam strcmp..
|
||||
if (strcmp("hip",jointName)==0) { color = cv::Scalar(255,0,0); } else
|
||||
if (strcmp("head",jointName)==0) { color = cv::Scalar(255,0,0); } else
|
||||
if (strcmp("neck",jointName)==0) { color = cv::Scalar(255,0,0); } else
|
||||
if (strcmp("chest",jointName)==0) { color = cv::Scalar(255,0,0); } else
|
||||
if (strcmp("chest",parentName)==0) { color = cv::Scalar(255,0,0); } else
|
||||
if (strcmp("abdomen",jointName)==0) { color = cv::Scalar(255,0,0); } else
|
||||
if (strcmp("head",parentName)==0) { color = cv::Scalar(255,0,0); } else */
|
||||
//-------------------------------------------------------------------------
|
||||
if (strcmp("lShldr",jointName)==0) { color = cv::Scalar(0,0,255); } else
|
||||
if (strcmp("lForeArm",jointName)==0){ color = cv::Scalar(0,0,255); } else
|
||||
if (strcmp("lHand",jointName)==0) { color = cv::Scalar(0,0,255); } else
|
||||
if (strcmp("lHand",parentName)==0) { color = cv::Scalar(0,0,255); } else
|
||||
if (strcmp("lButtock",jointName)==0){ color = cv::Scalar(0,0,255); } else
|
||||
if (strcmp("lShin",jointName)==0) { color = cv::Scalar(0,0,255); } else
|
||||
if (strcmp("lFoot",jointName)==0) { color = cv::Scalar(0,0,255); } else
|
||||
if (strcmp("lFoot",parentName)==0) { color = cv::Scalar(0,0,255); } else
|
||||
//-------------------------------------------------------------------------
|
||||
if (strcmp("rShldr",jointName)==0) { color = cv::Scalar(0,255,0); } else
|
||||
if (strcmp("rForeArm",jointName)==0){ color = cv::Scalar(0,255,0); } else
|
||||
if (strcmp("rHand",jointName)==0) { color = cv::Scalar(0,255,0); } else
|
||||
if (strcmp("rHand",parentName)==0) { color = cv::Scalar(0,255,0); } else
|
||||
if (strcmp("rButtock",jointName)==0){ color = cv::Scalar(0,255,0); } else
|
||||
if (strcmp("rShin",jointName)==0) { color = cv::Scalar(0,255,0); } else
|
||||
if (strcmp("rFoot",jointName)==0) { color = cv::Scalar(0,255,0); } else
|
||||
if (strcmp("rFoot",parentName)==0) { color = cv::Scalar(0,255,0); }
|
||||
}
|
||||
|
||||
|
||||
if ( (parentPointX!=0) && (parentPointY!=0) )
|
||||
{
|
||||
cv::line(outputMat,jointPoint,parentPoint,color,5.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Joint Out Of Bounds..");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
char textInfo[512]={0};
|
||||
|
||||
//Just the points and text ( foreground )
|
||||
for (int jointID=0; jointID<points2DOutputGUIForcedView.size(); jointID++)
|
||||
{
|
||||
float jointPointX = points2DOutputGUIForcedView[jointID][0]+offsetX;
|
||||
float jointPointY = points2DOutputGUIForcedView[jointID][1]+offsetY;
|
||||
//fprintf(stderr,"P x,y %0.2f,%0.2f \n",jointPointX,jointPointY);
|
||||
|
||||
|
||||
if ( (jointPointX!=0) && (jointPointY!=0) )
|
||||
{
|
||||
cv::Point jointPoint(jointPointX,jointPointY);
|
||||
int thickness=-2;
|
||||
cv::circle(outputMat,jointPoint,3,cv::Scalar(255,0,255),thickness,8,0);
|
||||
|
||||
int highlight = 0;
|
||||
int filterOut = 1;
|
||||
const char * jointName = getBVHJointName(jointID);
|
||||
if (jointName!=0)
|
||||
{
|
||||
snprintf(textInfo,512,"%s",jointName);
|
||||
|
||||
|
||||
#if GOOFY_EYES
|
||||
if (strcmp("eye.l",jointName)==0) { filterOut = 1; highlight = 1; } else
|
||||
if (strcmp("eye.r",jointName)==0) { filterOut = 1; highlight = 1; } else
|
||||
#endif
|
||||
if (strcmp("head",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("neck",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("chest",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("lShldr",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("rShldr",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("rShin",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("lShin",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("rForeArm",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("lForeArm",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("rFoot",jointName)==0) { filterOut = 0; } else
|
||||
if (strcmp("lFoot",jointName)==0) { filterOut = 0; }
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(textInfo,512,"-(%u)",jointID);
|
||||
}
|
||||
|
||||
|
||||
jointPoint.x+=10;
|
||||
if ((!filterOut) && (labels))
|
||||
{ cv::putText(outputMat, textInfo , jointPoint, cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar::all(255), 0.2, 8 ); }
|
||||
|
||||
if (highlight)
|
||||
{
|
||||
cv::circle(outputMat,jointPoint,6,cv::Scalar(255,255,255),thickness,8,0);
|
||||
cv::circle(outputMat,jointPoint,3,cv::Scalar(0,0,0),thickness,8,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
/** @file visualization.hpp
|
||||
* @brief Code that handles GUI output and visualization using OpenCV.
|
||||
* If OpenCV is not be available, CMake will not declare the USE_OPENCV compilation flag and the whole code will not be included.
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
#include "../applicationLogic/parseCommandlineOptions.hpp"
|
||||
|
||||
#if USE_OPENCV
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
#endif
|
||||
|
||||
|
||||
#if USE_OPENCV
|
||||
#if USE_BVH
|
||||
|
||||
int visualizeSkeletonSerialized(
|
||||
cv::Mat &outputMat,
|
||||
struct skeletonSerialized * skeleton,
|
||||
unsigned int drawLeftFingers,
|
||||
unsigned int drawRightFingers,
|
||||
unsigned int drawFace,
|
||||
unsigned int x,unsigned int y,
|
||||
unsigned int width,unsigned int height
|
||||
);
|
||||
|
||||
int drawSkeleton(cv::Mat &outputMat,std::vector<std::vector<float> > points2DOutputGUIForcedView,float offsetX,float offsetY,int labels);
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,331 @@
|
||||
#include "map.hpp"
|
||||
#include "visualization.hpp"
|
||||
|
||||
#include "../applicationLogic/artifactRecognition.hpp"
|
||||
|
||||
#include "../IO/jsonRead.hpp"
|
||||
#include "../IO/bvh.hpp"
|
||||
#include "../IO/skeletonAbstraction.hpp"
|
||||
#include "../tools.hpp"
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
|
||||
std::vector<cv::Point> locationHistory;
|
||||
|
||||
int drawPerson(cv::Mat & img,float x,float y,float r)
|
||||
{
|
||||
int maxLocationHistory=15;
|
||||
cv::Scalar color= cv::Scalar(0,0,255);
|
||||
cv::Scalar colorLook= cv::Scalar(100,0,90);
|
||||
|
||||
unsigned int width = img.size().width;
|
||||
unsigned int height = img.size().height;
|
||||
|
||||
|
||||
cv::Point startPoint(0,0);
|
||||
cv::Point endPoint(0,0);
|
||||
|
||||
unsigned int x2D = x*2 + width/2;
|
||||
unsigned int y2D = -1*y*2 + height/2;
|
||||
|
||||
//Draw Cross
|
||||
//-----------------------------------------------
|
||||
startPoint.x = x2D - 10;
|
||||
startPoint.y = y2D;
|
||||
endPoint.x = x2D + 10;
|
||||
endPoint.y = y2D;
|
||||
cv::line(img,startPoint,endPoint,color,2.0);
|
||||
//-----------------------------------------------
|
||||
startPoint.x = x2D;
|
||||
startPoint.y = y2D - 10;
|
||||
endPoint.x = x2D;
|
||||
endPoint.y = y2D + 10;
|
||||
cv::line(img,startPoint,endPoint,color,2.0);
|
||||
//-----------------------------------------------
|
||||
|
||||
|
||||
float rad=((float) -1.0 * 3.1415/180*r);
|
||||
startPoint.x=x2D;
|
||||
startPoint.y=y2D;
|
||||
endPoint.x=x2D+cos(rad)* (width/5);
|
||||
endPoint.y=y2D+sin(rad)* (height/5);
|
||||
cv::line(img,startPoint,endPoint,colorLook,2.0);
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
cv::Point p(x2D,y2D);
|
||||
locationHistory.push_back(p);
|
||||
if (locationHistory.size()>maxLocationHistory)
|
||||
{
|
||||
locationHistory.erase(locationHistory.begin());
|
||||
}
|
||||
float stepColorD=(float) 255/maxLocationHistory;
|
||||
for (int step=0; step<locationHistory.size(); step++)
|
||||
{
|
||||
float stepColor = 255 - step*stepColorD;
|
||||
if (step>1)
|
||||
{
|
||||
cv::line(img,locationHistory[step],locationHistory[step-1], cv::Scalar(0,0,stepColor), 1.0);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int visualizeMap(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
struct skeletonSerialized * skeleton,
|
||||
struct MocapNET2 * mnet,
|
||||
std::vector<float> result,
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
unsigned int numberOfMissingJoints,
|
||||
unsigned int gestureDetected,
|
||||
const char * gestureName,
|
||||
unsigned int gestureFrame
|
||||
)
|
||||
{
|
||||
fprintf(stderr,"visualizeMap called with %lu\n",points2DOutputGUIRealView.size());
|
||||
if (points2DOutputGUIRealView.size()==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#if USE_OPENCV
|
||||
|
||||
unsigned int gridSpace=30;
|
||||
cv::Point startPoint(0,0);
|
||||
cv::Point endPoint(0,height);
|
||||
|
||||
|
||||
cv::Mat img(height,width, CV_8UC3, Scalar(60,30,30));
|
||||
|
||||
cv::Scalar lookingColor= cv::Scalar(255,255,0);
|
||||
cv::Scalar activeColor= cv::Scalar(0,123,255);
|
||||
cv::Scalar color= cv::Scalar(253,123,30);
|
||||
|
||||
for (unsigned int x=0; x<width; x+=gridSpace)
|
||||
{
|
||||
startPoint.x=x;
|
||||
endPoint.x=x;
|
||||
cv::line(img,startPoint,endPoint,color,1.0);
|
||||
}
|
||||
|
||||
startPoint.x=0;
|
||||
endPoint.x=width;
|
||||
for (unsigned int y=0; y<height; y+=gridSpace)
|
||||
{
|
||||
startPoint.y=y;
|
||||
endPoint.y=y;
|
||||
cv::line(img,startPoint,endPoint,color,1.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
float thickness=1.0;
|
||||
int fontUsed=cv::FONT_HERSHEY_SIMPLEX;
|
||||
char text[512];
|
||||
snprintf(text,512," Position X=%0.2f Y=%0.2f Z=%0.2f %0.2f|%0.2f|%0.2f",result[0],result[1],result[2],result[3],result[4],result[5]);
|
||||
|
||||
startPoint.x=50;
|
||||
startPoint.y=50;
|
||||
cv::putText(img,text,startPoint,fontUsed,0.4,color,thickness,8);
|
||||
|
||||
std::vector<float> points3DFlatOutput=convertBVHFrameToFlat3DPoints(result); //,width,height
|
||||
//writeCSVHeaderFromLabelsAndVectorOfVectors("out3DP.csv",MocapNETOutputArrayNames,MOCAPNET_OUTPUT_NUMBER,output3DPositions) )
|
||||
|
||||
float x = result[2];
|
||||
float y = result[0];
|
||||
float r = result[4];
|
||||
|
||||
float lElbowX = points3DFlatOutput[MOCAPNET_3DPOINT_LELBOWZ];
|
||||
float lElbowY = points3DFlatOutput[MOCAPNET_3DPOINT_LELBOWX];
|
||||
float lHandX = points3DFlatOutput[MOCAPNET_3DPOINT_LHANDZ];
|
||||
float lHandY = points3DFlatOutput[MOCAPNET_3DPOINT_LHANDX];
|
||||
|
||||
|
||||
float rElbowX = points3DFlatOutput[MOCAPNET_3DPOINT_RELBOWZ];
|
||||
float rElbowY = points3DFlatOutput[MOCAPNET_3DPOINT_RHANDX];
|
||||
float rHandX = points3DFlatOutput[MOCAPNET_3DPOINT_RHANDZ];
|
||||
float rHandY = points3DFlatOutput[MOCAPNET_3DPOINT_RHANDX];
|
||||
|
||||
float rad=((float) 1.0 * 3.1415/180*r);
|
||||
float x2=x+cos(rad)* (width/5);
|
||||
float y2=y+sin(rad)* (height/5);
|
||||
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// If gestures are enabled.. Draw them..
|
||||
//-------------------------------------------------------------------------------
|
||||
if (gestureName!=0)
|
||||
{//-------------------------------------------------------------------------------
|
||||
if(gestureDetected)
|
||||
{
|
||||
if (gestureFrame>25)
|
||||
{
|
||||
snprintf(text,512,"%s (%u)",gestureName,gestureDetected);
|
||||
cv::Point txtPosition(600,200);
|
||||
cv::putText(img,text,txtPosition,fontUsed,1.5,cv::Scalar(0,255,255),thickness,8);
|
||||
cv::circle(img,txtPosition,2*gestureFrame,cv::Scalar(0,255,255),3,8,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// If poses are enabled.. Draw them..
|
||||
//-------------------------------------------------------------------------------
|
||||
if(mnet->activePose>1)
|
||||
{
|
||||
snprintf(text,512,"%s (%u)",hardcodedPoseName[mnet->activePose],mnet->activePose);
|
||||
cv::Point txtPosition(600,200);
|
||||
cv::putText(img,text,txtPosition,fontUsed,1.5,cv::Scalar(0,255,255),thickness,8);
|
||||
cv::circle(img,txtPosition,2*gestureFrame,cv::Scalar(0,255,255),3,8,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (unsigned int artifactID=0; artifactID<mnet->artifacts.numberOfArtifacts; artifactID++)
|
||||
{
|
||||
startPoint.x= mnet->artifacts.artifact[artifactID].x1*2 + width/2;
|
||||
startPoint.y= mnet->artifacts.artifact[artifactID].y1*-2 + height/2;
|
||||
endPoint.x= mnet->artifacts.artifact[artifactID].x2*2 + width/2;
|
||||
endPoint.y= mnet->artifacts.artifact[artifactID].y2*-2 + height/2;
|
||||
|
||||
|
||||
if (check3DArtifactCollision(
|
||||
&mnet->artifacts.artifact[artifactID],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_LELBOWZ],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_LELBOWX],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_LELBOWY],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_LHANDZ],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_LHANDX],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_LHANDY]
|
||||
)
|
||||
)
|
||||
{
|
||||
fprintf(stderr,"Left Hand Collision %u\n",artifactID);
|
||||
} else
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
if (check3DArtifactCollision(
|
||||
&mnet->artifacts.artifact[artifactID],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_RELBOWZ],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_RELBOWX],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_RELBOWY],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_RHANDZ],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_RHANDX],
|
||||
points3DFlatOutput[MOCAPNET_3DPOINT_RHANDY]
|
||||
)
|
||||
)
|
||||
{
|
||||
fprintf(stderr,"Right Hand Collision %u\n",artifactID);
|
||||
} else
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
if (checkArtifactCollision(&mnet->artifacts.artifact[artifactID],x, y, r))
|
||||
{
|
||||
fprintf(stderr,"ARTIFACT %u (%s) is collided \n",artifactID,mnet->artifacts.artifact[artifactID].label);
|
||||
if ((mnet->artifacts.artifact[artifactID].activatesOnPosition) && (!mnet->artifacts.artifact[artifactID].active) )
|
||||
{
|
||||
mnet->artifacts.artifact[artifactID].active=1;
|
||||
int i=system(mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation);
|
||||
if (i==0) { fprintf(stderr,"Executed %s \n",mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation); } else
|
||||
{ fprintf(stderr,"Failed to execute %s \n",mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation); }
|
||||
}
|
||||
cv::rectangle(img,startPoint,endPoint,activeColor,-1,8,0);
|
||||
snprintf(text,512,"%s (aid=%u)",mnet->artifacts.artifact[artifactID].label,artifactID);
|
||||
startPoint.y+=10;
|
||||
cv::putText(img,text,startPoint,fontUsed,0.4,cv::Scalar(0,0,255),thickness,8);
|
||||
} else
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
if (checkArtifactDirection(&mnet->artifacts.artifact[artifactID],x, y,x2,y2))
|
||||
{
|
||||
fprintf(stderr,"ARTIFACT %u (%s) is looked at \n",artifactID,mnet->artifacts.artifact[artifactID].label);
|
||||
if ( (mnet->artifacts.artifact[artifactID].activateOnGesture) && (mnet->activePose>1) )
|
||||
{
|
||||
int i =system(mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation);
|
||||
if (i==0) { fprintf(stderr,"Executed Gesture %s \n",mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation); } else
|
||||
{ fprintf(stderr,"Failed to execute gesture %s \n",mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation); }
|
||||
} else
|
||||
if ((mnet->artifacts.artifact[artifactID].activatesOnLook) && (!mnet->artifacts.artifact[artifactID].active))
|
||||
{
|
||||
mnet->artifacts.artifact[artifactID].active=1;
|
||||
int i = system(mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation);
|
||||
if (i==0) { fprintf(stderr,"Executed %s \n",mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation); } else
|
||||
{ fprintf(stderr,"Failed to execute gesture %s \n",mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation); }
|
||||
}
|
||||
|
||||
cv::rectangle(img,startPoint,endPoint,lookingColor,-1,8,0);
|
||||
snprintf(text,512,"%s (aid=%u)",mnet->artifacts.artifact[artifactID].label,artifactID);
|
||||
startPoint.y+=10;
|
||||
cv::putText(img,text,startPoint,fontUsed,0.4,cv::Scalar(0,255,0),thickness,8);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"ARTIFACT %u (%s) is inactive \n",artifactID,mnet->artifacts.artifact[artifactID].label);
|
||||
if ((mnet->artifacts.artifact[artifactID].activatesOnPosition) && (mnet->artifacts.artifact[artifactID].active) )
|
||||
{
|
||||
mnet->artifacts.artifact[artifactID].active=0;
|
||||
int i = system(mnet->artifacts.artifact[artifactID].actionToExecuteOnDeactivation);
|
||||
if (i==0) { fprintf(stderr,"Executed %s \n",mnet->artifacts.artifact[artifactID].actionToExecuteOnDeactivation); } else
|
||||
{ fprintf(stderr,"Failed to execute %s \n",mnet->artifacts.artifact[artifactID].actionToExecuteOnActivation); }
|
||||
}
|
||||
cv::rectangle(img,startPoint,endPoint,color,-1,8,0);
|
||||
snprintf(text,512,"%s (aid=%u)",mnet->artifacts.artifact[artifactID].label,artifactID);
|
||||
startPoint.y+=10;
|
||||
cv::putText(img,text,startPoint,fontUsed,0.4,cv::Scalar(255,0,0),thickness,8);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
cv::Point leftHandStart(lElbowX*2 + width/2,-1* lElbowY*2 + height/2);
|
||||
cv::Point leftHandEnd(lHandX*2 + width/2,-1* lHandY*2 + height/2);
|
||||
cv::line(img,leftHandStart,leftHandEnd,cv::Scalar(0,0,255),2.0);
|
||||
|
||||
|
||||
cv::Point rightHandStart(rElbowX*2 + width/2,-1* rElbowY*2 + height/2);
|
||||
cv::Point rightHandEnd(rHandX*2 + width/2,-1* rHandY*2 + height/2);
|
||||
cv::line(img,rightHandStart,rightHandEnd,cv::Scalar(0,255,0),2.0);
|
||||
|
||||
|
||||
|
||||
drawPerson(img,x,y,r);
|
||||
drawSkeleton(img,points2DOutputGUIRealView,-730,0,0);
|
||||
|
||||
//Draw Camera -----------------------------------------------------
|
||||
startPoint.x = width - 50;
|
||||
startPoint.y = (height/2) - 20;
|
||||
endPoint.x = width - 100;
|
||||
endPoint.y = (height/2) + 20;
|
||||
cv::rectangle(img,startPoint,endPoint,color,2,8,0);
|
||||
endPoint.y = (height/2) ;
|
||||
startPoint.x = endPoint.x-30;
|
||||
startPoint.y = endPoint.y+20;
|
||||
cv::line(img,startPoint,endPoint,color,2.0);
|
||||
startPoint.x = endPoint.x-30;
|
||||
startPoint.y = endPoint.y-20;
|
||||
cv::line(img,startPoint,endPoint,color,2.0);
|
||||
endPoint.x = endPoint.x-30;
|
||||
endPoint.y = endPoint.y+20;
|
||||
cv::line(img,startPoint,endPoint,color,2.0);
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
cv::imshow(windowName,img);
|
||||
|
||||
return 1;
|
||||
#else
|
||||
fprintf(stderr,"OpenCV code not present in this build, cannot show visualization..\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
/** @file map.hpp
|
||||
* @brief Code that handles GUI output and visualization using OpenCV.
|
||||
* If OpenCV is not be available, CMake will not declare the USE_OPENCV compilation flag and the whole code will not be included.
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#if USE_OPENCV
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
|
||||
int visualizeMap(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
struct skeletonSerialized * skeleton,
|
||||
struct MocapNET2 * mnet,
|
||||
std::vector<float> result,
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
unsigned int numberOfMissingJoints,
|
||||
unsigned int gestureDetected,
|
||||
const char * gestureName,
|
||||
unsigned int gestureFrame
|
||||
);
|
||||
#endif
|
||||
@@ -0,0 +1,182 @@
|
||||
#include <stdio.h>
|
||||
#include "opengl.hpp"
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
#if USE_OPENGL
|
||||
int openGLHasInitialization=0;
|
||||
int openGLHasFailed=0;
|
||||
#include "../../../../dependencies/RGBDAcquisition/opengl_acquisition_shared_library/OpenGLAcquisition.h"
|
||||
#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 */
|
||||
|
||||
|
||||
int initializeOpenGLStuff(unsigned int openGLFrameWidth,unsigned int openGLFrameHeight)
|
||||
{
|
||||
#if USE_OPENGL
|
||||
if (openGLHasFailed)
|
||||
{
|
||||
fprintf(stderr,"visualizeOpenGL won't do anything because it has previously failed.. \n");
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
if (!openGLHasInitialization)
|
||||
{
|
||||
openGLHasInitialization=1;
|
||||
openGLHasFailed=1;
|
||||
if (startOpenGLModule(1,"")) //safe
|
||||
{
|
||||
if (
|
||||
createOpenGLDevice(
|
||||
0,
|
||||
"dataset/human3D.conf",
|
||||
openGLFrameWidth,
|
||||
openGLFrameHeight,
|
||||
30
|
||||
)
|
||||
)
|
||||
{
|
||||
fprintf(stderr,GREEN "Success creating an OpenGL context" NORMAL);
|
||||
fprintf(stderr,GREEN "Requested rendering resolution was %ux%u\n" NORMAL,openGLFrameWidth,openGLFrameHeight);
|
||||
openGLHasFailed=0;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Failed creating an OpenGL context");
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,"Failed initializing OpenGL context");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif // USE_OPENGL
|
||||
//------------------------------------------------------------------
|
||||
//------------------------------------------------------------------
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if USE_OPENGL
|
||||
#if USE_BVH
|
||||
int changeOpenGLCalibration(struct calibration * calib)
|
||||
{
|
||||
initializeOpenGLStuff(calib->width,calib->height);
|
||||
return ( (setOpenGLColorCalibration(0,calib)) && (setOpenGLDepthCalibration(0,calib) ) );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
char * visualizeOpenGL(unsigned int *openGLFrameWidth,unsigned int *openGLFrameHeight)
|
||||
{
|
||||
#if USE_OPENGL
|
||||
//fprintf(stderr,"visualizeOpenGL CALLED for %u x %u size \n",*openGLFrameWidth,*openGLFrameHeight);
|
||||
|
||||
if (openGLHasFailed)
|
||||
{
|
||||
fprintf(stderr,"visualizeOpenGL won't do anything because it has previously failed.. \n");
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
initializeOpenGLStuff(*openGLFrameWidth,*openGLFrameHeight);
|
||||
//------------------------------------------------------------------
|
||||
//------------------------------------------------------------------
|
||||
|
||||
fprintf(stderr,"Snap OpenGL frame..\n");
|
||||
snapOpenGLFrames(0);
|
||||
fprintf(stderr,"Returning OpenGL frame..\n");
|
||||
return getOpenGLColorPixels(0);
|
||||
#else
|
||||
fprintf(stderr,"OpenGL code not included in this build..\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int clickOpenGLView(unsigned int x,unsigned int y,unsigned int state)
|
||||
{
|
||||
#if USE_OPENGL
|
||||
fprintf(stderr,"clickOpenGLView @ %u,%u\n",x,y);
|
||||
return passUserInputOpenGL(0,0,state,x,y);
|
||||
#else
|
||||
fprintf(stderr,"OpenGL code not included in this build..\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int updateOpenGLView(std::vector<float> bvhFrame)
|
||||
{
|
||||
if (bvhFrame.size()<MOCAPNET_OUTPUT_NUMBER)
|
||||
{
|
||||
fprintf(stderr,"Cannot update OpenGL view without a full bvh frame\n");
|
||||
return 0;
|
||||
}
|
||||
#if USE_OPENGL
|
||||
float xDirection=1.0;
|
||||
float yDirection=1.0;
|
||||
float zDirection=1.0;
|
||||
unsigned int rotationOrder = OPENGL_ACQUISITION_JOINT_ROTATION_NEGATIVE_XYZ; //Check
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Uncomment to check OpenGL/BVH associations....
|
||||
*
|
||||
fprintf(stderr,"Associtations BVH joint | OpenCollada ");
|
||||
for (int i=1; i<(MOCAPNET_OUTPUT_NUMBER-1)/3; i++)
|
||||
{
|
||||
if ((OpenCOLLADANames[i][0]!='-') && (OpenCOLLADANames[i][0]!='_'))
|
||||
{
|
||||
fprintf(stderr,"%s | %s \n",MocapNETOutputArrayNames[i*3],OpenCOLLADANames[i]);
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
*/
|
||||
|
||||
//Position/Rotation is common for automatic/manual setting..
|
||||
controlOpenGLScene(
|
||||
"human",
|
||||
"position",
|
||||
OPENGL_ACQUISITION_POSITION_XYZ,
|
||||
-0.1*bvhFrame[MOCAPNET_OUTPUT_HIP_XPOSITION],//If the position of the OpenGL overlay is wrong
|
||||
0.1*bvhFrame[MOCAPNET_OUTPUT_HIP_YPOSITION]-7.7,// It means that you
|
||||
-0.1*bvhFrame[MOCAPNET_OUTPUT_HIP_ZPOSITION]+2.4 //Need to supply correct intrinsics to OGL..
|
||||
);
|
||||
|
||||
controlOpenGLScene(
|
||||
"human",
|
||||
"Hips",
|
||||
OPENGL_ACQUISITION_JOINT_ROTATION_ZYX, //OPENGL_ACQUISITION_JOINT_ROTATION_XYZ <- this uses a different rotation scheme..
|
||||
-1.0*xDirection*bvhFrame[MOCAPNET_OUTPUT_HIP_ZROTATION],
|
||||
-1.0*yDirection*bvhFrame[MOCAPNET_OUTPUT_HIP_YROTATION],
|
||||
-1.0*zDirection*bvhFrame[MOCAPNET_OUTPUT_HIP_XROTATION]
|
||||
);
|
||||
|
||||
unsigned int iterationsToPerform = (unsigned int) (MOCAPNET_OUTPUT_NUMBER-1)/3;
|
||||
for (int i=2; i<iterationsToPerform; i++)
|
||||
{
|
||||
if ((OpenCOLLADANames[i][0]!='-') && (OpenCOLLADANames[i][0]!='_'))
|
||||
{
|
||||
//fprintf(stderr,"%s | %s \n",MocapNETOutputArrayNames[i*3],OpenCOLLADANames[i]);
|
||||
|
||||
controlOpenGLScene(
|
||||
"human",OpenCOLLADANames[i], rotationOrder,
|
||||
xDirection*bvhFrame[(i*3)+1],
|
||||
yDirection*bvhFrame[(i*3)+2],
|
||||
zDirection*bvhFrame[(i*3)+0]
|
||||
);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
#pragma once
|
||||
/** @file opengl.hpp
|
||||
* @brief Code that handles the OpenGL visualization. Adding an OpenGL visualization on top of this OpenCV based demo would require a pretty big
|
||||
* code base that handles all the context data, as well as model loading, rendering etc.
|
||||
* Instead of all these this program uses this OpenGL Sandbox
|
||||
* https://github.com/AmmarkoV/RGBDAcquisition/tree/master/opengl_acquisition_shared_library/opengl_depth_and_color_renderer/
|
||||
* A text file stored in dataset/human3D.conf controls all of the visualization details for the OpenGL window
|
||||
* this code just has to initialize the sandbox and update the OpenGL view with the current state of the human skeleton.
|
||||
* Then for each visualization call we get back a pointer to an RGB frame which can be viewed as a cv::mat after casting it to one
|
||||
* It is the easiest possible way to integrate the functionality
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
/**
|
||||
* @brief This is a list of joints from the BVH file to an OpenCOLLADA model created using makehuman and this target armature -> ( http://www.makehumancommunity.org/content/cmu_plus_face.html )
|
||||
* There is a 1:1 correspondance of this array and the BVH output joints (see MocapNETOutputJointNames ). Joints on this array that are marked as `-` or start with underscore ( _ ) are not active and are ignored
|
||||
* This list must also be in sync with the human3D.conf file that holds the 3D scene that gets rendered..
|
||||
* To check it do : cat human3D.conf | grep Bone | cut -d':' -f2 | tr '\n' '~' | tr -d '[:blank:]' | sed -e 's/\~/"\n\"/g'
|
||||
* To also check if the BVH header used is in sync as well with the names here you can do : cat dataset/headerWithHeadAndOneMotion.bvh | grep JOINT
|
||||
*/
|
||||
static const char * OpenCOLLADANames[]=
|
||||
{
|
||||
"Hips", // 0 "hip",
|
||||
"Hips", // 3 "hip",
|
||||
"Spine", // 6 "abdomen",
|
||||
"Spine1", // 9 "chest",
|
||||
"Neck", // 12 "neck",
|
||||
"Neck1", // 15 "neck1",
|
||||
"Head", // 18 "head",
|
||||
"-", // 21 "__jaw",
|
||||
"jaw", // 24 "jaw",
|
||||
"special04", // 27 "special04",
|
||||
"oris02", // 30 "oris02",
|
||||
"oris01", // 33 "oris01",
|
||||
"oris06_L", // 36 "oris06.l",
|
||||
"oris07_L", // 39 "oris07.l",
|
||||
"oris06_R", // 42 "oris06.r",
|
||||
"oris07_R", // 45 "oris07.r",
|
||||
"tongue00", // 48 "tongue00",
|
||||
"tongue01", // 51 "tongue01",
|
||||
"tongue02", // 54 "tongue02",
|
||||
"tongue03", // 57 "tongue03",
|
||||
"-", // 60 "__tongue04",
|
||||
"tongue04", // 63 "tongue04",
|
||||
"tongue07_L", // 66 "tongue07.l",
|
||||
"tongue07_R", // 69 "tongue07.r",
|
||||
"tongue06_L", // 72 "tongue06.l",
|
||||
"tongue06_R", // 75 "tongue06.r",
|
||||
"tongue05_L", // 78 "tongue05.l",
|
||||
"tongue05_R", // 81 "tongue05.r",
|
||||
"-", // 84 "__levator02.l",
|
||||
"levator02_L", // 87 "levator02.l",
|
||||
"levator03_L", // 90 "levator03.l",
|
||||
"levator04_L", // 93 "levator04.l",
|
||||
"levator05_L", // 96 "levator05.l",
|
||||
"-", // 99 "__levator02.r",
|
||||
"levator02_R", // 102 "levator02.r",
|
||||
"levator03_R", // 105 "levator03.r",
|
||||
"levator04_R", // 108 "levator04.r",
|
||||
"levator05_R", // 111 "levator05.r",
|
||||
"-", // 114 "__special01",
|
||||
"special01", // 117 "special01",
|
||||
"oris04_L", // 120 "oris04.l",
|
||||
"oris03_L", // 123 "oris03.l",
|
||||
"oris04_R", // 126 "oris04.r",
|
||||
"oris03_R", // 129 "oris03.r",
|
||||
"oris06", // 132 "oris06",
|
||||
"oris05", // 135 "oris05",
|
||||
"-", // 138 "__special03",
|
||||
"special03", // 141 "special03",
|
||||
"-", // 144 "__levator06.l",
|
||||
"levator06_L", // 147 "levator06.l",
|
||||
"-", // 150 "__levator06.r",
|
||||
"levator06_R", // 153 "levator06.r",
|
||||
"special06_L", // 156 "special06.l",
|
||||
"special05_L", // 159 "special05.l",
|
||||
"eye_L", // 162 "eye.l",
|
||||
"orbicularis03_L", // 165 "orbicularis03.l",
|
||||
"orbicularis04_L", // 168 "orbicularis04.l",
|
||||
"special06_R", // 171 "special06.r",
|
||||
"special05_R", // 174 "special05.r",
|
||||
"eye_R", // 177 "eye.r",
|
||||
"orbicularis03_R", // 180 "orbicularis03.r",
|
||||
"orbicularis04_R", // 183 "orbicularis04.r",
|
||||
"-", // 186 "__temporalis01.l",
|
||||
"temporalis01_L", // 189 "temporalis01.l",
|
||||
"oculi02_L", // 192 "oculi02.l",
|
||||
"oculi01_L", // 195 "oculi01.l",
|
||||
"__temporalis01_R", // 198 "__temporalis01.r",
|
||||
"temporalis01_R", // 201 "temporalis01.r",
|
||||
"oculi02_R", // 204 "oculi02.r",
|
||||
"oculi01_R", // 207 "oculi01.r",
|
||||
"__temporalis02_L", // 210 "__temporalis02.l",
|
||||
"temporalis02_L", // 213 "temporalis02.l",
|
||||
"risorius02_L", // 216 "risorius02.l",
|
||||
"risorius03_L", // 219 "risorius03.l",
|
||||
"__temporalis02_R", // 222 "__temporalis02.r",
|
||||
"temporalis02_R", // 225 "temporalis02.r",
|
||||
"risorius02_R", // 228 "risorius02.r",
|
||||
"risorius03_R", // 231 "risorius03.r",
|
||||
"RightShoulder", // 234 "rCollar",
|
||||
"RightArm", // 237 "rShldr",
|
||||
"RightForeArm", // 240 "rForeArm",
|
||||
"RightHand", // 243"rHand",
|
||||
"metacarpal1_R", // 246 "metacarpal1.r",
|
||||
"finger2-1_R", // 249 "finger2-1.r",
|
||||
"finger2-2_R", // 252 "finger2-2.r",
|
||||
"finger2-3_R", // 255 "finger2-3.r",
|
||||
"metacarpal2_R", // 258 "metacarpal2.r",
|
||||
"finger3-1_R", // 261 "finger3-1.r",
|
||||
"finger3-2_R", // 264 "finger3-2.r",
|
||||
"finger3-3_R", // 267 "finger3-3.r",
|
||||
"__metacarpal3_R", // 270 "__metacarpal3.r",
|
||||
"metacarpal3_R", // 273 "metacarpal3.r",
|
||||
"finger4-1_R", // 276 "finger4-1.r",
|
||||
"finger4-2_R", // 279 "finger4-2.r",
|
||||
"finger4-3_R", // 282 "finger4-3.r",
|
||||
"__metacarpal4_R", // 285 "__metacarpal4.r",
|
||||
"metacarpal4_R", // 288 "metacarpal4.r",
|
||||
"finger5-1_R", // 291 "finger5-1.r",
|
||||
"finger5-2_R", // 294 "finger5-2.r",
|
||||
"finger5-3_R", // 297 "finger5-3.r",
|
||||
"__rthumb", // 300 "__rthumb",
|
||||
"RThumb", // 303 "rthumb",
|
||||
"finger1-2_R", // 306 "finger1-2.r",
|
||||
"finger1-3_R", // 309 "finger1-3.r",
|
||||
"LeftShoulder", // 312 "lCollar",
|
||||
"LeftArm", // 315 "lShldr",
|
||||
"LeftForeArm", // 318 "lForeArm",
|
||||
"LeftHand", // 321 "lHand",
|
||||
"metacarpal1_L", // 324 "metacarpal1.l",
|
||||
"finger2-1_L", // 327 "finger2-1.l",
|
||||
"finger2-2_L", // 330 "finger2-2.l",
|
||||
"finger2-3_L", // 333 "finger2-3.l",
|
||||
"metacarpal2_L", // 336 "metacarpal2.l",
|
||||
"finger3-1_L", // 339 "finger3-1.l",
|
||||
"finger3-2_L", // 342 "finger3-2.l",
|
||||
"finger3-3_L", // 345 "finger3-3.l",
|
||||
"__metacarpal3_L", // 348 "__metacarpal3.l",
|
||||
"metacarpal3_L", // 351 "metacarpal3.l",
|
||||
"finger4-1_L", // 354 "finger4-1.l",
|
||||
"finger4-2_L", // 357 "finger4-2.l",
|
||||
"finger4-3_L", // 360 "finger4-3.l",
|
||||
"__metacarpal4_L", // 363 "__metacarpal4.l",
|
||||
"metacarpal4_L", // 366 "metacarpal4.l",
|
||||
"finger5-1_L", // 369 "finger5-1.l",
|
||||
"finger5-2_L", // 372 "finger5-2.l",
|
||||
"finger5-3_L", // 375 "finger5-3.l",
|
||||
"__lthumb", // 378 "__lthumb",
|
||||
"LThumb", // 381 "lthumb",
|
||||
"finger1-2_L", // 384 "finger1-2.l",
|
||||
"finger1-3_L", // 387 "finger1-3.l",
|
||||
"RHipJoint", // 390 "rButtock",
|
||||
"RightUpLeg", // 393 "rThigh",
|
||||
"RightLeg", // 396 "rShin",
|
||||
"RightFoot", // 399 "rFoot",
|
||||
"_toe1-1_R", // 402 "toe1-1.R", <- This does not currently exist in the makehuman model
|
||||
"_toe1-2_R", // 405 "toe1-2.R", <- This does not currently exist in the makehuman model
|
||||
"_toe2-1_R", // 408 "toe2-1.R", <- This does not currently exist in the makehuman model
|
||||
"_toe2-2_R", // 411 "toe2-2.R", <- This does not currently exist in the makehuman model
|
||||
"_toe2-3_R", // 414 "toe2-3.R", <- This does not currently exist in the makehuman model
|
||||
"_toe3-1_R", // 417 "toe3-1.R", <- This does not currently exist in the makehuman model
|
||||
"_toe3-2_R", // 420 "toe3-2.R", <- This does not currently exist in the makehuman model
|
||||
"_toe3-3_R", // 423 "toe3-3.R", <- This does not currently exist in the makehuman model
|
||||
"_toe4-1_R", // 426 "toe4-1.R", <- This does not currently exist in the makehuman model
|
||||
"_toe4-2_R", // 429 "toe4-2.R", <- This does not currently exist in the makehuman model
|
||||
"_toe4-3_R", // 432 "toe4-3.R", <- This does not currently exist in the makehuman model
|
||||
"_toe5-1_R", // 435 "toe5-1.R", <- This does not currently exist in the makehuman model
|
||||
"_toe5-2_R", // 438 "toe5-2.R", <- This does not currently exist in the makehuman model
|
||||
"_toe5-3_R", // 441 "toe5-3.R", <- This does not currently exist in the makehuman model
|
||||
"LHipJoint", // 444 "lButtock",
|
||||
"LeftUpLeg", // 447 "lThigh",
|
||||
"LeftLeg", // 450 "lShin",
|
||||
"LeftFoot", // 453 "lFoot",
|
||||
"_toe1-1_L", // 456 "toe1-1.L", <- This does not currently exist in the makehuman model
|
||||
"_toe1-2_L", // 459 "toe1-2.L", <- This does not currently exist in the makehuman model
|
||||
"_toe2-1_L", // 462 "toe2-1.L", <- This does not currently exist in the makehuman model
|
||||
"_toe2-2_L", // 465 "toe2-2.L", <- This does not currently exist in the makehuman model
|
||||
"_toe2-3_L", // 468 "toe2-3.L", <- This does not currently exist in the makehuman model
|
||||
"_toe3-1_L", // 471 "toe3-1.L", <- This does not currently exist in the makehuman model
|
||||
"_toe3-2_L", // 474 "toe3-2.L", <- This does not currently exist in the makehuman model
|
||||
"_toe3-3_L", // 477 "toe3-3.L", <- This does not currently exist in the makehuman model
|
||||
"_toe4-1_L", // 480 "toe4-1.L", <- This does not currently exist in the makehuman model
|
||||
"_toe4-2_L", // 483 "toe4-2.L", <- This does not currently exist in the makehuman model
|
||||
"_toe4-3_L", // 486 "toe4-3.L", <- This does not currently exist in the makehuman model
|
||||
"_toe5-1_L", // 489 "toe5-1.L", <- This does not currently exist in the makehuman model
|
||||
"_toe5-2_L", // 492 "toe5-2.L", <- This does not currently exist in the makehuman model
|
||||
"_toe5-3_L", // 495 "toe5-3.L" <- This does not currently exist in the makehuman model
|
||||
};
|
||||
|
||||
|
||||
#if USE_BVH
|
||||
#include "../../../../dependencies/RGBDAcquisition/tools/Calibration/calibration.h"
|
||||
int changeOpenGLCalibration(struct calibration * calib);
|
||||
#endif
|
||||
|
||||
|
||||
int clickOpenGLView(unsigned int x,unsigned int y,unsigned int state);
|
||||
|
||||
|
||||
int initializeOpenGLStuff(unsigned int openGLFrameWidth,unsigned int openGLFrameHeight);
|
||||
|
||||
/**
|
||||
* @brief This function uses the file dataset/human3D.conf and the current scene state as updated using updateOpenGLView
|
||||
* @param Pointer to a value that is both input and output width of the OpenGL frame. The renderer will try to use the provided width but it might not be exactly the same.
|
||||
* @param Pointer to a value that is both input and output height of the OpenGL frame. The renderer will try to use the provided height but it might not be exactly the same.
|
||||
* @ingroup tools
|
||||
* @retval 0=Failure else a pointer to an RGB image that holds the OpenGL rendering
|
||||
*/
|
||||
char * visualizeOpenGL(unsigned int *openGLFrameWidth,unsigned int *openGLFrameHeight);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function provides the 3D pose extracted to the OpenGL context so that the armature will be rendered accordingly
|
||||
* @param MocapNET BVH output
|
||||
* @ingroup tools
|
||||
* @retval 1=Success/0=Failure
|
||||
*/
|
||||
int updateOpenGLView(std::vector<float> bvhFrame);
|
||||
@@ -0,0 +1,186 @@
|
||||
|
||||
#if USE_OPENCV
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
|
||||
int visualizeCameraIntensities(const char* windowName, cv::Mat &imgOriginal,int forceColors)
|
||||
{
|
||||
float fontSize = 0.3;
|
||||
unsigned int verticalSpace=25;
|
||||
unsigned int horizontalSpace=10;
|
||||
|
||||
unsigned int x=0,y=10;
|
||||
char text[512];
|
||||
if ( (imgOriginal.rows!=0) && (imgOriginal.cols!=0) )
|
||||
{
|
||||
cv::Mat img(32,32, CV_8UC3, cv::Scalar(0,0,0));
|
||||
cv::resize(imgOriginal, img, img.size() ,0,0,INTER_NEAREST);
|
||||
//cv::imshow(windowName,img);
|
||||
cv::Mat imgV((3+img.cols) * horizontalSpace *3 ,img.rows * verticalSpace, CV_8UC3,cv::Scalar(0,0,0));
|
||||
for(int r=0; r<img.rows; ++r)
|
||||
{
|
||||
x=0;
|
||||
for(int c=0; c<img.cols; ++c)
|
||||
{
|
||||
unsigned char * p = img.ptr(r,c); // Y first, X after
|
||||
cv::Point jointPoint(x,y);
|
||||
snprintf(text,512,"%u",p[0]);
|
||||
if (forceColors) p[0]=255;
|
||||
cv::putText(imgV, text , jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(p[0],0,0), 0.2, cv::LINE_4 );
|
||||
x=x+horizontalSpace;
|
||||
jointPoint.x=x;
|
||||
snprintf(text,512,"%u",p[1]);
|
||||
if (forceColors) p[1]=255;
|
||||
cv::putText(imgV, text , jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(0,p[1],0), 0.2, cv::LINE_4 );
|
||||
x=x+horizontalSpace;
|
||||
jointPoint.x=x;
|
||||
snprintf(text,512,"%u",p[2]);
|
||||
if (forceColors) p[2]=255;
|
||||
cv::putText(imgV, text , jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(0,0,p[2]), 0.2, cv::LINE_4 );
|
||||
x=x+horizontalSpace;
|
||||
jointPoint.x=x;
|
||||
}
|
||||
y=y+verticalSpace;
|
||||
}
|
||||
|
||||
|
||||
cv::Point jointPoint(10,10);
|
||||
fontSize = 0.5;
|
||||
cv::putText(imgV,"Raw RGB Image Data", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(255,255,255), 0.2, cv::LINE_8);
|
||||
cv::imshow(windowName,imgV);
|
||||
cv::waitKey(1);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int visualizeCameraChannels(const char* windowName,cv::Mat &img,int channelNumber)
|
||||
{
|
||||
if ( (img.rows!=0) && (img.cols!=0) )
|
||||
{
|
||||
|
||||
Mat channel[3];
|
||||
// The actual splitting.
|
||||
split(img, channel);
|
||||
|
||||
cv::Point jointPoint(10,10);
|
||||
float fontSize = 0.5;
|
||||
|
||||
|
||||
if (channelNumber<3)
|
||||
{
|
||||
if (channelNumber==0)
|
||||
{
|
||||
cv::putText(channel[channelNumber],"Blue channel", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(255,0,0), 0.2, cv::LINE_8);
|
||||
}
|
||||
else if (channelNumber==1)
|
||||
{
|
||||
cv::putText(channel[channelNumber],"Green channel", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(0,255,0), 0.2, cv::LINE_8);
|
||||
}
|
||||
else if (channelNumber==2)
|
||||
{
|
||||
cv::putText(channel[channelNumber],"Red channel", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(0,0,255), 0.2, cv::LINE_8);
|
||||
}
|
||||
cv::imshow(windowName, channel[channelNumber]);
|
||||
}
|
||||
else // if (channelNumber>=3)
|
||||
{
|
||||
cv::Mat imageMerged;
|
||||
|
||||
if (channelNumber==3)
|
||||
{
|
||||
channel[0]=cv::Mat::zeros(img.rows, img.cols, CV_8UC1);
|
||||
cv::merge(channel,3,imageMerged);
|
||||
cv::putText(imageMerged,"Green + Red channel", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(0,255,255), 0.2, cv::LINE_8);
|
||||
}
|
||||
else //Set blue channel to 0
|
||||
if (channelNumber==4)
|
||||
{
|
||||
channel[1]=cv::Mat::zeros(img.rows, img.cols, CV_8UC1);
|
||||
cv::merge(channel,3,imageMerged);
|
||||
cv::putText(imageMerged,"Blue + Red channel", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(255,0,255), 0.2, cv::LINE_8);
|
||||
}
|
||||
else //Set blue channel to 0
|
||||
if (channelNumber==5)
|
||||
{
|
||||
channel[2]=cv::Mat::zeros(img.rows, img.cols, CV_8UC1);
|
||||
cv::merge(channel,3,imageMerged);
|
||||
cv::putText(imageMerged,"Green + Blue channel", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(255,255,0), 0.2, cv::LINE_8);
|
||||
}
|
||||
else //Set blue channel to 0
|
||||
{
|
||||
cv::merge(channel,3,imageMerged);
|
||||
cv::putText(imageMerged,"Red + Green + Blue channel", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(255,255,255), 0.2, cv::LINE_8);
|
||||
}
|
||||
|
||||
cv::imshow(windowName,imageMerged);
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int visualizeCameraEdges(const char* windowName,cv::Mat &img)
|
||||
{
|
||||
cv::Mat edges;
|
||||
//cv::cvtColor(img, edges,BGR2GRAY);
|
||||
|
||||
cv::Canny(edges, edges, 30, 60);
|
||||
|
||||
cv::Point jointPoint(10,10);
|
||||
float fontSize = 0.5;
|
||||
cv::putText(edges,"Edges", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(255,255,255), 0.2, cv::LINE_8);
|
||||
cv::imshow(windowName, edges);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int visualizeCameraFeatures(const char* windowName,cv::Mat &img)
|
||||
{
|
||||
std::vector<cv::KeyPoint> keypoints;
|
||||
|
||||
cv::Mat imgCopy; //= img.clone();
|
||||
cv::resize(img, imgCopy, img.size() ,0,0,INTER_NEAREST);
|
||||
cv::FAST(imgCopy,keypoints,100.0,false);
|
||||
char coordinates[256];
|
||||
|
||||
|
||||
for (int i=0; i<keypoints.size(); i++)
|
||||
{
|
||||
cv::circle(imgCopy,keypoints[i].pt,5,cv::Scalar(0,255,0),3,8,0);
|
||||
cv::Point jointPoint(keypoints[i].pt.x,keypoints[i].pt.y);
|
||||
snprintf(coordinates,256,"%0.1f,%0.1f",keypoints[i].pt.x,keypoints[i].pt.y);
|
||||
cv::putText(imgCopy,coordinates, jointPoint, cv::FONT_HERSHEY_DUPLEX,0.4, cv::Scalar(0,255,255), 0.2, cv::LINE_4);
|
||||
}
|
||||
|
||||
|
||||
cv::Point jointPoint(10,10);
|
||||
float fontSize = 0.5;
|
||||
cv::putText(imgCopy,"Features", jointPoint, cv::FONT_HERSHEY_DUPLEX,fontSize, cv::Scalar(255,255,255), 0.2, cv::LINE_8);
|
||||
cv::imshow(windowName,imgCopy);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int visualizeFigure(const char* windowName,cv::Mat &img)
|
||||
{
|
||||
if ( (img.rows!=0) && (img.cols!=0) )
|
||||
{
|
||||
cv::imshow(windowName, img);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
/** @file rgb.hpp
|
||||
* @brief Code that handles GUI output and visualization using OpenCV.
|
||||
* If OpenCV is not be available, CMake will not declare the USE_OPENCV compilation flag and the whole code will not be included.
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#if USE_OPENCV
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
|
||||
int visualizeCameraIntensities(const char* windowName, cv::Mat &imgOriginal,int forceColors);
|
||||
int visualizeCameraChannels(const char* windowName,cv::Mat &img,int channelNumber);
|
||||
int visualizeCameraEdges(const char* windowName,cv::Mat &img);
|
||||
int visualizeCameraFeatures(const char* windowName,cv::Mat &img);
|
||||
int visualizeFigure(const char* windowName,cv::Mat &img);
|
||||
#endif
|
||||
@@ -0,0 +1,184 @@
|
||||
#include "template.hpp"
|
||||
#include "visualization.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
#include "drawSkeleton.hpp"
|
||||
|
||||
#include "../IO/jsonRead.hpp"
|
||||
#include "../IO/bvh.hpp"
|
||||
#include "../tools.hpp"
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
|
||||
|
||||
|
||||
int visualizeTemplate(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int saveVisualization,
|
||||
cv::Mat * alreadyLoadedImage,
|
||||
const char * path,
|
||||
const char * label,
|
||||
unsigned int serialLength,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
struct skeletonSerialized * skeleton,
|
||||
struct MocapNET2 * mnet,
|
||||
struct MocapNET2Options * options,
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedView,
|
||||
unsigned int numberOfMissingJoints
|
||||
)
|
||||
{
|
||||
|
||||
#if USE_OPENCV
|
||||
int success=0;
|
||||
char finalFilename[2048]= {0};
|
||||
cv::Mat raytraced;
|
||||
|
||||
|
||||
snprintf(finalFilename,256,"%s/raytraced2/%04u.png",path,frameNumber);
|
||||
raytraced = imread(finalFilename,cv::IMREAD_COLOR); // older versions might want the CV_LOAD_IMAGE_COLOR flag
|
||||
|
||||
if (alreadyLoadedImage==0)
|
||||
{
|
||||
|
||||
char formatString[256]= {0};
|
||||
snprintf(formatString,256,"%%s/%%s%%0%uu.jpg",serialLength);
|
||||
|
||||
//colorFrame_0_00001.jpg
|
||||
snprintf(finalFilename,2048,formatString,path,label,frameNumber/*Frame ID*/);
|
||||
//snprintf(finalFilename,2048,"%s/colorFrame_0_%05d.jpg",path,frameNumber+1);
|
||||
}
|
||||
|
||||
int showFramerate=30; //30 or 0
|
||||
|
||||
float scale=1.0;
|
||||
cv::Mat image;
|
||||
cv::Rect roi;
|
||||
cv::Mat destinationROI;
|
||||
|
||||
if ( (fileExists(finalFilename) ) || (alreadyLoadedImage!=0) )
|
||||
{
|
||||
if (alreadyLoadedImage!=0)
|
||||
{
|
||||
image = *alreadyLoadedImage;
|
||||
|
||||
if (
|
||||
( image.size().width < 640 ) ||
|
||||
( image.size().height < 480 )
|
||||
)
|
||||
{
|
||||
fprintf(stderr,"Very small given frame ( %ux%u..\n",image.size().width,image.size().height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//cv::imshow(windowName,image); //
|
||||
//cv::waitKey(0);
|
||||
}
|
||||
else
|
||||
if (fileExists(finalFilename) )
|
||||
{
|
||||
image = imread(finalFilename,cv::IMREAD_COLOR); // older versions might want the CV_LOAD_IMAGE_COLOR flag
|
||||
}
|
||||
|
||||
|
||||
|
||||
visualizeSkeletonSerialized(
|
||||
image,
|
||||
skeleton,
|
||||
1,//Show left hand
|
||||
1,//Show right hand
|
||||
1,//Show face
|
||||
0,0,
|
||||
image.size().width,
|
||||
image.size().height
|
||||
);
|
||||
drawSkeleton(image,points2DOutputGUIRealView,-330,-0,0);
|
||||
|
||||
|
||||
int NSDMWidth=160; //body leftHand rightHand
|
||||
int NSDMHeight=160;
|
||||
|
||||
int positionX = image.size().width - NSDMWidth - 100;
|
||||
int positionY = 240;
|
||||
|
||||
cv::rectangle(image,cv::Rect(positionX-20,positionY-40,NSDMWidth+40,620+showFramerate),cv::Scalar(0,0,0),-1);
|
||||
|
||||
visualizeNSDM(image,"Upper Body",mnet->upperBody.NSDM,1 /*angles*/,positionX,positionY,NSDMWidth,NSDMHeight);
|
||||
positionY+=200;
|
||||
visualizeNSDM(image,"Lower Body",mnet->lowerBody.NSDM,1 /*angles*/,positionX,positionY,NSDMWidth,NSDMHeight);
|
||||
positionY+=200;
|
||||
|
||||
visualizeOrientation(
|
||||
image,"Orientation",
|
||||
mnet->currentSolution[4], //Orientation value
|
||||
mnet->orientationClassifications[0],
|
||||
mnet->orientationClassifications[1],
|
||||
mnet->orientationClassifications[2],
|
||||
mnet->orientationClassifications[3],
|
||||
positionX,
|
||||
positionY,
|
||||
NSDMWidth,
|
||||
NSDMHeight
|
||||
);
|
||||
|
||||
|
||||
if (showFramerate>0)
|
||||
{
|
||||
//-----------------------------------------------------------------
|
||||
float thickness=1.7;
|
||||
int fontUsed=cv::FONT_HERSHEY_SIMPLEX;
|
||||
cv::Scalar fontColor= cv::Scalar(255,255,255);
|
||||
cv::Point txtPosition(positionX+10,positionY+190);
|
||||
char fpsString[128];
|
||||
snprintf(fpsString,128,"%0.2f fps",options->totalLoopFPS);
|
||||
cv::putText(image,fpsString,txtPosition,fontUsed,0.8,fontColor,thickness,8);
|
||||
//-----------------------------------------------------------------
|
||||
}
|
||||
|
||||
if(image.data!=0)
|
||||
{
|
||||
if ( image.size().height > image.size().width )
|
||||
{
|
||||
scale=(float) 720/image.size().height;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale=(float) 1024/image.size().width;
|
||||
}
|
||||
if (scale>1.0)
|
||||
{
|
||||
scale=1.0;
|
||||
}
|
||||
if (scale!=1.0)
|
||||
{
|
||||
cv::resize(image, image, cv::Size(0,0), scale, scale);
|
||||
}
|
||||
|
||||
//fprintf(stderr,"Image ( %u x %u )\n",image.size().width,image.size().height);
|
||||
success=1;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr," Could not load %s image, cannot proceed to visualize it\n",finalFilename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (saveVisualization)
|
||||
{
|
||||
char filename[512];
|
||||
snprintf(filename,512,"vis%05u.jpg",frameNumber) ;
|
||||
cv::imwrite(filename,image);
|
||||
}
|
||||
|
||||
cv::imshow(windowName,image); //
|
||||
//Did not find a file to show ..
|
||||
return success;
|
||||
#else
|
||||
fprintf(stderr,"OpenCV code not present in this build, cannot show visualization..\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
/** @file allInOne.hpp
|
||||
* @brief Code that handles GUI output and visualization using OpenCV.
|
||||
* If OpenCV is not be available, CMake will not declare the USE_OPENCV compilation flag and the whole code will not be included.
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#if USE_OPENCV
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
|
||||
int visualizeTemplate(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int saveVisualization,
|
||||
cv::Mat * alreadyLoadedImage,
|
||||
const char * path,
|
||||
const char * label,
|
||||
unsigned int serialLength,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
struct skeletonSerialized * skeleton,
|
||||
struct MocapNET2 * mnet,
|
||||
struct MocapNET2Options * options,
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedView,
|
||||
unsigned int numberOfMissingJoints
|
||||
);
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,262 @@
|
||||
#pragma once
|
||||
/** @file visualization.hpp
|
||||
* @brief Code that handles GUI output and visualization using OpenCV.
|
||||
* If OpenCV is not be available, CMake will not declare the USE_OPENCV compilation flag and the whole code will not be included.
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
#include "../applicationLogic/parseCommandlineOptions.hpp"
|
||||
|
||||
#if USE_OPENCV
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
#endif
|
||||
|
||||
int debug2DPointAlignment(
|
||||
const char * windowName,
|
||||
std::vector<float> original2DPoints,
|
||||
std::vector<float> rotated2DPoints,
|
||||
unsigned int pivotPoint,
|
||||
unsigned int referencePoint,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
);
|
||||
|
||||
|
||||
//Using transparency penalizes performance taking 12% of live webcam demo looptime
|
||||
//when tested using scripts/profile.sh
|
||||
#define USE_TRANSPARENCY 0
|
||||
|
||||
|
||||
int visualizeHandleMessages();
|
||||
int visualizeMotionHistory(const char* windowName, std::vector<std::vector<float> > history, std::vector<std::vector<float> > skeleton2D);
|
||||
|
||||
static const int lineColorIndex[] =
|
||||
{
|
||||
247,252,253,
|
||||
224,236,244,
|
||||
191,211,230,
|
||||
158,188,218,
|
||||
140,150,198,
|
||||
140,107,177,
|
||||
136,65,157,
|
||||
129,15,124,
|
||||
77,0,75,
|
||||
247,252,253,
|
||||
229,245,249,
|
||||
204,236,230,
|
||||
153,216,201,
|
||||
102,194,164,
|
||||
65,174,118,
|
||||
35,139,69,
|
||||
0,109,44,
|
||||
0,68,27,
|
||||
247,252,240,
|
||||
224,243,219,
|
||||
204,235,197,
|
||||
168,221,181,
|
||||
123,204,196,
|
||||
78,179,211,
|
||||
43,140,190,
|
||||
8,104,172,
|
||||
8,64,129,
|
||||
255,247,236,
|
||||
254,232,200,
|
||||
253,212,158,
|
||||
253,187,132,
|
||||
252,141,89,
|
||||
239,101,72,
|
||||
215,48,31,
|
||||
179,0,0,
|
||||
127,0,0,
|
||||
255,247,251,
|
||||
236,231,242,
|
||||
208,209,230,
|
||||
166,189,219,
|
||||
116,169,207,
|
||||
54,144,192,
|
||||
5,112,176,
|
||||
4,90,141,
|
||||
2,56,88,
|
||||
255,247,251,
|
||||
236,226,240,
|
||||
208,209,230,
|
||||
166,189,219,
|
||||
103,169,207,
|
||||
54,144,192,
|
||||
2,129,138,
|
||||
1,108,89,
|
||||
1,70,54,
|
||||
247,244,249,
|
||||
231,225,239,
|
||||
212,185,218,
|
||||
201,148,199,
|
||||
223,101,176,
|
||||
231,41,138,
|
||||
206,18,86,
|
||||
152,0,67,
|
||||
103,0,31,
|
||||
255,247,243,
|
||||
253,224,221,
|
||||
252,197,192,
|
||||
250,159,181,
|
||||
247,104,161,
|
||||
221,52,151,
|
||||
174,1,126,
|
||||
122,1,119,
|
||||
73,0,106,
|
||||
255,255,229,
|
||||
247,252,185,
|
||||
217,240,163,
|
||||
173,221,142,
|
||||
120,198,121,
|
||||
65,171,93,
|
||||
35,132,67,
|
||||
0,104,55,
|
||||
0,69,41,
|
||||
255,255,217,
|
||||
237,248,177,
|
||||
199,233,180,
|
||||
127,205,187,
|
||||
65,182,196,
|
||||
29,145,192,
|
||||
34,94,168,
|
||||
37,52,148,
|
||||
8,29,88,
|
||||
255,255,229,
|
||||
255,247,188,
|
||||
254,227,145,
|
||||
254,196,79,
|
||||
254,153,41,
|
||||
236,112,20,
|
||||
204,76,2,
|
||||
153,52,4,
|
||||
102,37,6,
|
||||
255,255,204,
|
||||
255,237,160,
|
||||
254,217,118,
|
||||
254,178,76,
|
||||
253,141,60,
|
||||
252,78,42,
|
||||
227,26,28,
|
||||
189,0,38,
|
||||
128,0,38
|
||||
};
|
||||
|
||||
|
||||
#if USE_OPENCV
|
||||
|
||||
int visualizeNSDM(
|
||||
cv::Mat &img,
|
||||
const char * label,
|
||||
std::vector<float> NSDM,
|
||||
unsigned int channelsPerNSDMElement,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
);
|
||||
|
||||
|
||||
int visualizeInput2DSkeletonFromSkeletonSerialized(
|
||||
cv::Mat &outputMat,
|
||||
struct skeletonSerialized * skeleton,
|
||||
unsigned int x,unsigned int y,
|
||||
unsigned int width,unsigned int height
|
||||
);
|
||||
|
||||
|
||||
int scaleSkeleton( std::vector<std::vector<float> > &sk, float scaleX,float scaleY);
|
||||
int drawSkeleton(cv::Mat &outputMat,std::vector<std::vector<float> > points2DOutputGUIForcedView,float offsetX,float offsetY,int labels);
|
||||
#endif
|
||||
|
||||
int doReprojectionCheck(struct skeletonSerialized * input,struct skeletonSerialized * result);
|
||||
|
||||
int visualizeInput(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int saveVisualization,
|
||||
cv::Mat * alreadyLoadedImage,
|
||||
const char * path,
|
||||
const char * label,
|
||||
unsigned int serialLength,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
struct skeletonSerialized * skeleton,
|
||||
struct MocapNET2 * mnet,
|
||||
std::vector<std::vector<float> > points2DOutputGUIRealView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedView,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedViewSide,
|
||||
unsigned int numberOfMissingJoints
|
||||
);
|
||||
|
||||
|
||||
|
||||
void spawnVisualizationWindow(const char* windowName,unsigned int width,unsigned int height);
|
||||
|
||||
/**
|
||||
* @brief Visualize MocapNET BVH output on a window
|
||||
* @ingroup visualization
|
||||
* @param CString with title of window
|
||||
* @param Current frame number
|
||||
* @param Framerate of Acquisition
|
||||
* @param Framerate of 2D Joint estimator
|
||||
* @param Framerate of MocapNET 3D Pose estimator
|
||||
* @param Output window width
|
||||
* @param Output window height
|
||||
* @param MocapNET output BVH frame that we want to visualize
|
||||
* @retval 1 = Success loading the files , 0 = Failure
|
||||
*/
|
||||
int visualizePoints(
|
||||
const char* windowName,
|
||||
unsigned int frameNumber,
|
||||
unsigned int skippedFrames,
|
||||
signed int totalNumberOfFrames,
|
||||
unsigned int numberOfFramesToGrab,
|
||||
const char * CPUName,
|
||||
const char * GPUName,
|
||||
int drawFloor,
|
||||
int drawNSDM,
|
||||
float fpsTotal,
|
||||
float fpsAcquisition,
|
||||
float fpsInverseKinematics,
|
||||
float fpsJoint2DEstimator,
|
||||
float fpsMocapNET,
|
||||
unsigned int mocapNETMode,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int handleMessages,
|
||||
unsigned int deadInputPoints,
|
||||
unsigned int gestureDetected,
|
||||
const char * gestureName,
|
||||
unsigned int gestureFrame,
|
||||
float originalOrientation,
|
||||
struct MocapNET2 * mnet,
|
||||
struct skeletonSerialized * skeleton,
|
||||
std::vector<float> mocapNETInput,
|
||||
std::vector<float> mocapNETOutput,
|
||||
std::vector<float> mocapNETOutputWithGUIForcedView,
|
||||
std::vector<std::vector<float> > points2DInput,
|
||||
std::vector<std::vector<float> > points2DOutput,
|
||||
std::vector<std::vector<float> > points2DOutputGUIForcedView,
|
||||
int useOpenGLVisualization,
|
||||
unsigned int save3DVisualization
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
int visualizationCommander(
|
||||
struct MocapNET2 * mnet,
|
||||
struct MocapNET2Options * options,
|
||||
struct skeletonSerialized * skeleton,
|
||||
cv::Mat * frame,
|
||||
std::vector<float> result,
|
||||
std::vector<std::vector<float> > exactMocapNET2DOutput,
|
||||
unsigned int frameID,
|
||||
unsigned int callingProcessPromisesToHandleMessages
|
||||
);
|
||||
@@ -0,0 +1,594 @@
|
||||
#include "widgets.hpp"
|
||||
|
||||
#if USE_OPENCV
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
|
||||
#include "../IO/bvh.hpp"
|
||||
#include "../tools.hpp"
|
||||
#include "../mocapnet2.hpp"
|
||||
|
||||
|
||||
cv::Mat overlay(cv::Mat base,cv::Mat overlay)
|
||||
{
|
||||
//--------------------------------------
|
||||
if ( (base.size().width==overlay.size().width) && (base.size().height==overlay.size().height) )
|
||||
{
|
||||
if ( ( base.channels()==3 ) && ( base.channels()==overlay.channels() ) )
|
||||
{
|
||||
for (unsigned int y=0; y<base.size().height; y++)
|
||||
{
|
||||
unsigned char * baseP = base.ptr<uchar>(y);
|
||||
unsigned char * overlayP = overlay.ptr<uchar>(y);
|
||||
|
||||
for (unsigned int x=0; x<base.size().width; x++)
|
||||
{
|
||||
unsigned char bO = *overlayP; ++overlayP;
|
||||
unsigned char gO = *overlayP; ++overlayP;
|
||||
unsigned char rO = *overlayP; ++overlayP;
|
||||
|
||||
if ( (rO!=0) || (gO!=0) || (bO!=0) )
|
||||
{
|
||||
*baseP = bO; ++baseP;
|
||||
*baseP = gO; ++baseP;
|
||||
*baseP = rO; ++baseP;
|
||||
} else
|
||||
{
|
||||
baseP+=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
||||
return cv::max(overlay,base);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int drawScale(cv::Mat &outputMat,const char * description,float x,float y,float value,float minimum,float maximum)
|
||||
{
|
||||
cv::Point startPoint(x,y);
|
||||
cv::Point endPoint(x,y+200);
|
||||
|
||||
|
||||
cv::Scalar color = cv::Scalar(123,123,123);
|
||||
cv::line(outputMat,startPoint,endPoint, color , 3.0);
|
||||
//
|
||||
|
||||
float fraction = (float) value/(maximum-minimum);
|
||||
|
||||
float yPos = y + 200 * fraction;
|
||||
|
||||
//Don't let it get out of range..
|
||||
if (yPos<y) { yPos=y; }
|
||||
if (yPos>y+200) { yPos=y+200; }
|
||||
|
||||
cv::Point distancePos(x,yPos);
|
||||
cv::circle(outputMat,distancePos,1,cv::Scalar(0,255,0),3,8,0);
|
||||
|
||||
|
||||
char label[64];
|
||||
|
||||
snprintf(label,64,"%s",description);
|
||||
startPoint.x=startPoint.x-20;
|
||||
startPoint.y=startPoint.y-10;
|
||||
cv::putText(outputMat,label, startPoint, cv::FONT_HERSHEY_DUPLEX, 0.3, cv::Scalar::all(255), 0.2, 8 );
|
||||
|
||||
if (value<0) { snprintf(label,64,"Negative!"); } else
|
||||
if (value>maximum) { snprintf(label,64,"Too Large!"); } else
|
||||
{ snprintf(label,64,"%0.2f",value); }
|
||||
distancePos.x=distancePos.x-20;
|
||||
distancePos.y=distancePos.y-10;
|
||||
cv::putText(outputMat,label, distancePos, cv::FONT_HERSHEY_DUPLEX, 0.3, cv::Scalar::all(255), 0.2, 8 );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int plotFloatVector(
|
||||
cv::Mat & img,
|
||||
char cleanBackground,
|
||||
std::vector<float> history,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
)
|
||||
{
|
||||
#if USE_OPENCV
|
||||
if (history.size()<2) { return 0; }
|
||||
|
||||
|
||||
unsigned int plotPosX=x;
|
||||
unsigned int plotPosY=y;
|
||||
unsigned int widthOfGraphs=width;
|
||||
unsigned int heightOfGraphs=height;
|
||||
unsigned int i=0,joint=0;
|
||||
|
||||
if (cleanBackground)
|
||||
{ cv::rectangle(img,cv::Rect(x,y,width,height),cv::Scalar(0,0,0),-1); }
|
||||
|
||||
float resolution = 2.0;
|
||||
float speed=2.0;
|
||||
unsigned int plotStart = 1;
|
||||
unsigned int plotEnd = history.size();
|
||||
|
||||
if (speed!=1.0)
|
||||
{
|
||||
plotStart = (unsigned int ) history.size() / speed;
|
||||
}
|
||||
|
||||
for (i=plotStart; i<plotEnd; i++)
|
||||
{
|
||||
cv::Point jointPointPrev(plotPosX+ ((unsigned int) (i-plotStart) * speed), plotPosY+heightOfGraphs-(unsigned int) history[i-1]/resolution);
|
||||
cv::Point jointPointNext(plotPosX+ ((unsigned int) (i-plotStart+1) * speed), plotPosY+heightOfGraphs-(unsigned int) history[i]/resolution );
|
||||
|
||||
|
||||
cv::Scalar usedColor = cv::Scalar(0,0,255);
|
||||
float lastRecordedFramerate = history.back();
|
||||
if (lastRecordedFramerate >= 60) { usedColor = cv::Scalar(0,255,0); } else
|
||||
if (lastRecordedFramerate >30) { usedColor = cv::Scalar(0,255,255); }
|
||||
|
||||
|
||||
cv::line(img,jointPointPrev,jointPointNext,usedColor,2.0);
|
||||
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
fprintf(stderr,"plotFloatVector cannot be compiled without OpenCV\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int visualizeOrientation(
|
||||
cv::Mat &img,
|
||||
const char * label,
|
||||
float orientationDegrees,
|
||||
float frontClass,
|
||||
float backClass,
|
||||
float leftClass,
|
||||
float rightClass,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
)
|
||||
{
|
||||
float thickness=2.5;
|
||||
cv::Point startPoint(x,y);
|
||||
cv::Point endPoint(x+width,y+height);
|
||||
|
||||
int addSyntheticPoints=1;
|
||||
int doScaleCompensation=0;
|
||||
|
||||
thickness=1;
|
||||
int fontUsed=cv::FONT_HERSHEY_SIMPLEX;
|
||||
cv::Scalar fontColor= cv::Scalar(255,255,255);
|
||||
cv::Point txtPosition(x,y-15);
|
||||
cv::putText(img,label,txtPosition,fontUsed,0.6,fontColor,thickness,8);
|
||||
txtPosition.y+=10;
|
||||
|
||||
|
||||
cv::Scalar color= cv::Scalar(0,0,255);
|
||||
|
||||
|
||||
unsigned int cX = x + width / 2;
|
||||
unsigned int cY = y + height / 2;
|
||||
|
||||
startPoint.x=cX;
|
||||
startPoint.y=cY;
|
||||
|
||||
cv::Scalar color0 = cv::Scalar(0,0,255);
|
||||
cv::Scalar color45 = cv::Scalar(0,0,255);
|
||||
cv::Scalar color135 = cv::Scalar(0,0,255);
|
||||
cv::Scalar color225 = cv::Scalar(0,0,255);
|
||||
cv::Scalar color315 = cv::Scalar(0,0,255);
|
||||
|
||||
cv::Scalar font0 = cv::Scalar(255,255,0);
|
||||
cv::Scalar font45 = cv::Scalar(255,255,0);
|
||||
cv::Scalar font135 = cv::Scalar(255,255,0);
|
||||
cv::Scalar font225 = cv::Scalar(255,255,0);
|
||||
cv::Scalar font315 = cv::Scalar(255,255,0);
|
||||
|
||||
|
||||
if ( (frontClass>backClass) && (frontClass>leftClass) && (frontClass>rightClass) )
|
||||
{
|
||||
color45=cv::Scalar(0,255,0);
|
||||
font45=cv::Scalar(255,0,255);
|
||||
}
|
||||
else if ( (backClass>frontClass) && (backClass>leftClass) && (backClass>rightClass) )
|
||||
{
|
||||
color225=cv::Scalar(0,255,0);
|
||||
font225=cv::Scalar(255,0,255);
|
||||
}
|
||||
else if ( (leftClass>backClass) && (leftClass>frontClass) && (leftClass>rightClass) )
|
||||
{
|
||||
color135=cv::Scalar(0,255,0);
|
||||
font135=cv::Scalar(255,0,255);
|
||||
}
|
||||
else if ( (rightClass>backClass) && (rightClass>frontClass) && (rightClass>leftClass) )
|
||||
{
|
||||
color0=cv::Scalar(0,255,0);
|
||||
color315=color0;
|
||||
font0=cv::Scalar(255,0,255);
|
||||
font315=cv::Scalar(255,0,255);
|
||||
}
|
||||
|
||||
for (unsigned int i=0; i<360; i++)
|
||||
{
|
||||
float rad=((float) 3.1415/180*i);
|
||||
endPoint.x=cX+cos(rad)* (width/2);
|
||||
endPoint.y=cY+sin(rad)* (height/2);
|
||||
|
||||
if (i==0)
|
||||
{
|
||||
color=color0;
|
||||
}
|
||||
else if (i==45)
|
||||
{
|
||||
color=color45;
|
||||
}
|
||||
else if (i==135)
|
||||
{
|
||||
color=color135;
|
||||
}
|
||||
else if (i==225)
|
||||
{
|
||||
color=color225;
|
||||
}
|
||||
else if (i==315)
|
||||
{
|
||||
color=color315;
|
||||
}
|
||||
|
||||
cv::line(
|
||||
img,
|
||||
startPoint,
|
||||
endPoint,
|
||||
color,
|
||||
2.0
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Draw an arrow in our orientation..
|
||||
unsigned int rad = height/2;
|
||||
|
||||
int lineStyle = 0; // https://github.com/FORTH-ModelBasedTracker/MocapNET/issues/30 has problems with CV_AA
|
||||
|
||||
cv::Point arrowPointing;
|
||||
arrowPointing.x = (int)(startPoint.x + (rad+10) * cos((90.0+orientationDegrees) * CV_PI / 180.0));
|
||||
arrowPointing.y = (int)(startPoint.y + (rad+10) * sin((90.0+orientationDegrees) * CV_PI / 180.0));
|
||||
cv::line(img,startPoint,arrowPointing,cv::Scalar(0,255,255),4,lineStyle,0);
|
||||
cv::Point arrowSide;
|
||||
arrowSide.x = (int)(startPoint.x + (rad) * cos((90.0+orientationDegrees-5) * CV_PI / 180.0));
|
||||
arrowSide.y = (int)(startPoint.y + (rad) * sin((90.0+orientationDegrees-5) * CV_PI / 180.0));
|
||||
cv::line(img,arrowSide,arrowPointing,cv::Scalar(0,255,255),4,lineStyle,0);
|
||||
arrowSide.x = (int)(startPoint.x + (rad) * cos((90.0+orientationDegrees+5) * CV_PI / 180.0));
|
||||
arrowSide.y = (int)(startPoint.y + (rad) * sin((90.0+orientationDegrees+5) * CV_PI / 180.0));
|
||||
cv::line(img,arrowSide,arrowPointing,cv::Scalar(0,255,255),4,lineStyle,0);
|
||||
|
||||
thickness=2;
|
||||
startPoint.x-= width / 7;
|
||||
|
||||
char str[512];
|
||||
snprintf(str,512,"%0.2f",frontClass);
|
||||
txtPosition = startPoint;
|
||||
txtPosition.y += 5+height/4;
|
||||
cv::putText(img,str,txtPosition,fontUsed,0.6,font45,thickness,8);
|
||||
|
||||
snprintf(str,512,"%0.2f",backClass);
|
||||
txtPosition = startPoint;
|
||||
txtPosition.y -= height/4;
|
||||
cv::putText(img,str,txtPosition,fontUsed,0.6,font225,thickness,8);
|
||||
|
||||
snprintf(str,512,"%0.2f",rightClass);
|
||||
txtPosition = startPoint;
|
||||
txtPosition.x += width/4;
|
||||
cv::putText(img,str,txtPosition,fontUsed,0.6,font0,thickness,8);
|
||||
|
||||
snprintf(str,512,"%0.2f",leftClass);
|
||||
txtPosition = startPoint;
|
||||
txtPosition.x -= width/4;
|
||||
cv::putText(img,str,txtPosition,fontUsed,0.6,font135,thickness,8);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int visualizeNSDM(
|
||||
cv::Mat &img,
|
||||
const char * label,
|
||||
std::vector<float> NSDM,
|
||||
unsigned int channelsPerNSDMElement,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
)
|
||||
{
|
||||
float thickness=2.5;
|
||||
//cv::Point topLeft(x,y);
|
||||
//cv::Point bottomRight(x+width,y+height);
|
||||
//cv::line(img,topLeft,bottomRight, cv::Scalar(0,255,0),thickness);
|
||||
//cv::rectangle(img, topLeft,bottomRight, cv::Scalar(0,255,0),thickness, 8, 0);
|
||||
|
||||
int addSyntheticPoints=1;
|
||||
int doScaleCompensation=0;
|
||||
|
||||
thickness=1.5;
|
||||
int fontUsed=cv::FONT_HERSHEY_SIMPLEX;
|
||||
cv::Scalar color= cv::Scalar(255,255,255,0 /*Transparency here , although if the cv::Mat does not have an alpha channel it is useless*/);
|
||||
cv::Point txtPosition(x,y-15);
|
||||
cv::putText(img,label,txtPosition,fontUsed,0.8,color,thickness,8);
|
||||
txtPosition.y+=10;
|
||||
|
||||
if (channelsPerNSDMElement==2)
|
||||
{
|
||||
cv::putText(img,"NSDM",txtPosition,fontUsed,0.3,color,thickness,8);
|
||||
}
|
||||
else if (channelsPerNSDMElement==1)
|
||||
{
|
||||
cv::putText(img,"NSRM",txtPosition,fontUsed,0.3,color,thickness,8);
|
||||
}
|
||||
|
||||
|
||||
if (NSDM.size()==0)
|
||||
{
|
||||
txtPosition.x+=(width/2)-30;
|
||||
txtPosition.y+=height/2;
|
||||
cv::putText(img,"N/A",txtPosition,fontUsed,0.8,cv::Scalar(0,0,255),thickness,8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (NSDM.size()>0)
|
||||
{
|
||||
unsigned int xI,yI,item=0,dim=sqrt(NSDM.size()/channelsPerNSDMElement);
|
||||
unsigned int boxX=width/dim,boxY=height/dim;
|
||||
for (yI=0; yI<dim; yI++)
|
||||
{
|
||||
for (xI=0; xI<dim; xI++)
|
||||
{
|
||||
cv::Point topLeft(x+xI*boxX,y+yI*boxY);
|
||||
cv::Point bottomRight(x+xI*boxX+boxX,y+yI*boxY+boxY);
|
||||
|
||||
float xVal=1.0;
|
||||
float yVal=1.0;
|
||||
|
||||
float blueChannel = 0;
|
||||
float greenChannel= 0;
|
||||
float redChannel = 0;
|
||||
|
||||
if (channelsPerNSDMElement==2)
|
||||
{
|
||||
xVal=NSDM[item];
|
||||
yVal=NSDM[item+1];
|
||||
|
||||
blueChannel = (float) xVal*255.0;
|
||||
greenChannel= (float) yVal*255.0;
|
||||
redChannel = (float) 255.0 * ( (xVal==0.0) && (yVal==0.0) );
|
||||
}
|
||||
else if (channelsPerNSDMElement==1)
|
||||
{
|
||||
yVal=0;
|
||||
xVal=0;
|
||||
if (NSDM[item]<0)
|
||||
{
|
||||
yVal=abs(NSDM[item]);
|
||||
}
|
||||
else
|
||||
{
|
||||
xVal=NSDM[item];
|
||||
}
|
||||
|
||||
//fprintf(stderr,"Item %u => %0.2f\n",item,NSDM[item]);
|
||||
greenChannel = (float) 255.0 * (float) xVal/2;// /180.0;
|
||||
blueChannel = (float) 255.0 * (float) yVal/2;// /180.0;
|
||||
redChannel = (float) 255.0 * ( (xVal==0.0) && (yVal==0.0) );
|
||||
}
|
||||
|
||||
|
||||
cv::rectangle(
|
||||
img,
|
||||
topLeft,
|
||||
bottomRight,
|
||||
cv::Scalar(
|
||||
blueChannel,
|
||||
greenChannel,
|
||||
redChannel
|
||||
),
|
||||
-1*thickness,
|
||||
8,
|
||||
0
|
||||
);
|
||||
|
||||
//Visualize error
|
||||
if ( ( (xVal>2.0) || (yVal>2.0) ) && (channelsPerNSDMElement==2) )
|
||||
{
|
||||
cv::Point topRight(x+xI*boxX+boxX,y+yI*boxY);
|
||||
cv::Point bottomLeft(x+xI*boxX,y+yI*boxY+boxY);
|
||||
cv::Point topMiddle(x+xI*boxX+boxX/2,y+yI*boxY);
|
||||
cv::Point bottomMiddle(x+xI*boxX+boxX/2,y+yI*boxY+boxY);
|
||||
cv::line(img,topLeft,bottomRight, cv::Scalar(0,0,255), 1.0);
|
||||
cv::line(img,topRight,bottomLeft, cv::Scalar(0,0,255), 1.0);
|
||||
cv::line(img,topMiddle,bottomMiddle, cv::Scalar(0,0,255), 1.0);
|
||||
}
|
||||
else if ( ( (xVal>1.5) || (yVal>1.5) ) && (channelsPerNSDMElement==2) )
|
||||
{
|
||||
cv::Point topRight(x+xI*boxX+boxX,y+yI*boxY);
|
||||
cv::Point bottomLeft(x+xI*boxX,y+yI*boxY+boxY);
|
||||
cv::line(img,topLeft,bottomRight, cv::Scalar(0,0,255), 1.0);
|
||||
cv::line(img,topRight,bottomLeft, cv::Scalar(0,0,255), 1.0);
|
||||
}
|
||||
else if ( ( (xVal>1.0) || (yVal>1.0) ) && (channelsPerNSDMElement==2) )
|
||||
{
|
||||
cv::Point topRight(x+xI*boxX+boxX,y+yI*boxY);
|
||||
cv::Point bottomLeft(x+xI*boxX,y+yI*boxY+boxY);
|
||||
cv::line(img,topLeft,bottomRight, cv::Scalar(0,0,255), 1.0);
|
||||
}
|
||||
|
||||
item+=channelsPerNSDMElement;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int visualizeNSDMAsBar(
|
||||
cv::Mat &img,
|
||||
std::vector<float> NSDM,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
)
|
||||
{
|
||||
float thickness=2.5;
|
||||
//cv::Point topLeft(x,y);
|
||||
//cv::Point bottomRight(x+width,y+height);
|
||||
//cv::line(img,topLeft,bottomRight, cv::Scalar(0,255,0),thickness);
|
||||
//cv::rectangle(img, topLeft,bottomRight, cv::Scalar(0,255,0),thickness, 8, 0);
|
||||
|
||||
int addSyntheticPoints=1;
|
||||
int doScaleCompensation=0;
|
||||
|
||||
if (NSDM.size()>0)
|
||||
{
|
||||
|
||||
float thickness=1;
|
||||
int fontUsed=cv::FONT_HERSHEY_SIMPLEX;
|
||||
|
||||
|
||||
unsigned int xI,yI,item=0,dim=sqrt(NSDM.size()/2);
|
||||
unsigned int errors=0;
|
||||
|
||||
for (yI=0; yI<dim; yI++)
|
||||
{
|
||||
for (xI=0; xI<dim; xI++)
|
||||
{
|
||||
if ( (NSDM[item]==0.0) && (NSDM[item+1]==0.0) )
|
||||
{
|
||||
++errors;
|
||||
}
|
||||
item+=2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cv::Scalar color;
|
||||
float qualityPercentage=(float) errors/(dim*dim*2);
|
||||
qualityPercentage=(1.0-qualityPercentage);
|
||||
|
||||
if (qualityPercentage>0.9)
|
||||
{
|
||||
color=cv::Scalar(0,255,0);
|
||||
}
|
||||
else if (qualityPercentage>0.8)
|
||||
{
|
||||
color=cv::Scalar(0,123,123);
|
||||
qualityPercentage-=0.2;
|
||||
}
|
||||
else
|
||||
{
|
||||
color=cv::Scalar(0,0,255);
|
||||
qualityPercentage-=0.6;
|
||||
}
|
||||
|
||||
if (qualityPercentage>1.0)
|
||||
{
|
||||
qualityPercentage=1.0;
|
||||
}
|
||||
if (qualityPercentage<0.0)
|
||||
{
|
||||
qualityPercentage=0.0;
|
||||
}
|
||||
|
||||
cv::Point topLeft(x,y);
|
||||
cv::Point bottomRight(x+(qualityPercentage*width),y+height);
|
||||
|
||||
|
||||
cv::rectangle(img, topLeft,bottomRight,color,-thickness, 8, 0);
|
||||
|
||||
cv::Point txtPosition(x,y-15);
|
||||
cv::putText(img,"Quality : ",txtPosition,fontUsed,0.8,color,thickness,8);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int drawFloorFromPrimitives(
|
||||
cv::Mat &img,
|
||||
float roll,
|
||||
float pitch,
|
||||
float yaw,
|
||||
unsigned int floorDimension
|
||||
)
|
||||
{
|
||||
std::vector<std::vector<float> > gridPoints2D = convert3DGridTo2DPoints(
|
||||
roll,
|
||||
pitch,
|
||||
yaw,
|
||||
floorDimension
|
||||
);
|
||||
|
||||
cv::Point parentPoint(gridPoints2D[0][0],gridPoints2D[0][1]);
|
||||
cv::Point verticalPoint(gridPoints2D[0][0],gridPoints2D[0][1]);
|
||||
float m=10.0; //Minimum
|
||||
|
||||
for (int jointID=0; jointID<gridPoints2D.size(); jointID++)
|
||||
{
|
||||
cv::Point jointPoint( gridPoints2D[jointID][0], gridPoints2D[jointID][1]);
|
||||
|
||||
if (jointID+floorDimension<gridPoints2D.size())
|
||||
{
|
||||
verticalPoint.x=gridPoints2D[jointID+floorDimension][0];
|
||||
verticalPoint.y=gridPoints2D[jointID+floorDimension][1];
|
||||
}
|
||||
else
|
||||
{
|
||||
verticalPoint.x=0.0;
|
||||
verticalPoint.y=0.0;
|
||||
}
|
||||
|
||||
|
||||
if ( (jointPoint.x>m) && (jointPoint.y>m) )
|
||||
{
|
||||
cv::circle(img,jointPoint,2,cv::Scalar(255,255,0),3,8,0);
|
||||
if ( (jointPoint.x>m) && (jointPoint.y>m) && (verticalPoint.x>m) && (verticalPoint.y>m) )
|
||||
{
|
||||
cv::line(img,jointPoint,verticalPoint, cv::Scalar(255,255,0), 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (jointID%floorDimension!=0)
|
||||
{
|
||||
if ( (jointPoint.x>m) && (jointPoint.y>m) && (parentPoint.x>m) && (parentPoint.y>m) )
|
||||
{
|
||||
cv::line(img,jointPoint,parentPoint, cv::Scalar(255,255,0), 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
parentPoint = jointPoint;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
/** @file widgets.hpp
|
||||
* @brief Code that handles GUI output and visualization using OpenCV.
|
||||
* If OpenCV is not be available, CMake will not declare the USE_OPENCV compilation flag and the whole code will not be included.
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
|
||||
#if USE_OPENCV
|
||||
#include "opencv2/opencv.hpp"
|
||||
using namespace cv;
|
||||
|
||||
cv::Mat overlay(cv::Mat base,cv::Mat overlay);
|
||||
|
||||
int drawScale(cv::Mat &outputMat,const char * description,float x,float y,float value,float minimum,float maximum);
|
||||
|
||||
int plotFloatVector(
|
||||
cv::Mat & img,
|
||||
char cleanBackground,
|
||||
std::vector<float> history,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
);
|
||||
|
||||
|
||||
int visualizeOrientation(
|
||||
cv::Mat &img,
|
||||
const char * label,
|
||||
float orientationDegrees,
|
||||
float frontClass,
|
||||
float backClass,
|
||||
float leftClass,
|
||||
float rightClass,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
);
|
||||
|
||||
|
||||
|
||||
int visualizeNSDM(
|
||||
cv::Mat &img,
|
||||
const char * label,
|
||||
std::vector<float> NSDM,
|
||||
unsigned int channelsPerNSDMElement,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
);
|
||||
|
||||
|
||||
|
||||
int visualizeNSDMAsBar(
|
||||
cv::Mat &img,
|
||||
std::vector<float> NSDM,
|
||||
unsigned int x,
|
||||
unsigned int y,
|
||||
unsigned int width,
|
||||
unsigned int height
|
||||
);
|
||||
|
||||
|
||||
int drawFloorFromPrimitives(
|
||||
cv::Mat &img,
|
||||
float roll,
|
||||
float pitch,
|
||||
float yaw,
|
||||
unsigned int floorDimension
|
||||
);
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
project( drawCSV )
|
||||
cmake_minimum_required( VERSION 2.8.13)
|
||||
#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})
|
||||
|
||||
|
||||
add_executable(drawCSV drawCSV.cpp )
|
||||
|
||||
target_link_libraries(drawCSV rt dl m ${OpenCV_LIBRARIES} ${OPENGL_LIBS} Tensorflow TensorflowFramework MocapNETLib2 ${NETWORK_CLIENT_LIBRARIES} ${PNG_Libs} ${JPG_Libs} )
|
||||
set_target_properties(drawCSV PROPERTIES DEBUG_POSTFIX "D")
|
||||
|
||||
|
||||
set_target_properties(drawCSV PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
#include "opencv2/opencv.hpp"
|
||||
/** @file bvhgui.cpp
|
||||
* @brief This is a simple test file to play with the BVH armature
|
||||
* #Hands up
|
||||
* // ./BVHGUI --set 241 290.0 --set 242 80 --set 284 117 --set 283 113
|
||||
* #Close up hands / face
|
||||
* // ./BVHGUI --set 1 -70 --set 2 -60 --set 241 290.0 --set 242 80 --set 282 187 --set 283 252 --set 284 112
|
||||
* @author Ammar Qammaz (AmmarkoV)
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "../../MocapNET2/MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/IO/bvh.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/visualization/visualization.hpp"
|
||||
#include "../../MocapNET2/MocapNETLib2/visualization/opengl.hpp"
|
||||
#include <vector>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
int visualizeOpenGLEnabled=0;
|
||||
|
||||
struct applicationState
|
||||
{
|
||||
std::vector<float>bvhConfiguration;
|
||||
std::vector<std::vector<float> > bvh2DPoints;
|
||||
int rotation;
|
||||
int selectedJoint,previousSelection;
|
||||
int visualizationType,previousVisualizationType;
|
||||
int stop;
|
||||
int save;
|
||||
int redraw;
|
||||
};
|
||||
|
||||
|
||||
int controls(cv::Mat & controlMat,struct applicationState * state)
|
||||
{
|
||||
cv::imshow("3D Control",controlMat);
|
||||
cv::createTrackbar("Stop Demo", "3D Control", &state->stop, 1);
|
||||
if (visualizeOpenGLEnabled)
|
||||
{ cv::createTrackbar("Visualization Type", "3D Control", &state->visualizationType, 1); }
|
||||
cv::createTrackbar("Save", "3D Control", &state->save, 1);
|
||||
cv::createTrackbar("Selected Joint", "3D Control", &state->selectedJoint,MOCAPNET_OUTPUT_NUMBER);
|
||||
cv::createTrackbar("Value ", "3D Control", &state->rotation, 360);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int visWidth=1024;
|
||||
unsigned int visHeight=768;
|
||||
|
||||
cv::Mat controlMat = Mat(Size(300,1),CV_8UC3, Scalar(0,0,0));
|
||||
memset(controlMat.data,255,300*1*3*sizeof(char));
|
||||
cv::Mat viewMat = Mat(Size(visWidth,visHeight),CV_8UC3, Scalar(0,0,0));
|
||||
struct applicationState state;
|
||||
state.rotation=0;
|
||||
state.previousSelection=0;
|
||||
state.selectedJoint=0;
|
||||
state.visualizationType=0;
|
||||
state.stop=0;
|
||||
state.save=0;
|
||||
state.previousVisualizationType=2;// <- force redraw on first loop
|
||||
state.redraw=1;
|
||||
|
||||
|
||||
for (int i=0; i<MOCAPNET_OUTPUT_NUMBER; i++)
|
||||
{
|
||||
state.bvhConfiguration.push_back(0.0);
|
||||
}
|
||||
state.bvhConfiguration[2]=(float) -150.0;
|
||||
|
||||
for (int i=0; i<argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i],"--set")==0)
|
||||
{
|
||||
if(argc>i+2)
|
||||
{
|
||||
unsigned int bvhJoint = atoi(argv[i+1]);
|
||||
float bvhValue = atof(argv[i+2]);
|
||||
if (bvhJoint<MOCAPNET_OUTPUT_NUMBER)
|
||||
{
|
||||
fprintf(stderr,"joint[%s]=%0.2f",MocapNETOutputArrayNames[bvhJoint],bvhValue);
|
||||
state.bvhConfiguration[bvhJoint]=bvhValue;
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (strcmp(argv[i],"--opengl")==0)
|
||||
{
|
||||
visualizeOpenGLEnabled=1;
|
||||
state.visualizationType=1;
|
||||
state.previousVisualizationType=state.visualizationType;
|
||||
}
|
||||
}
|
||||
|
||||
Mat edges;
|
||||
namedWindow("BVH",1);
|
||||
controls(controlMat,&state);
|
||||
cv::moveWindow("3D Control",0,0); //y=inputHeight2DJointDetector
|
||||
cv::moveWindow("BVH",300,0);
|
||||
|
||||
|
||||
initializeBVHConverter(0,visWidth,visHeight,1);
|
||||
|
||||
while(!state.stop)
|
||||
{
|
||||
if (state.save)
|
||||
{
|
||||
std::vector<std::vector<float> > bvhFrames;
|
||||
bvhFrames.push_back(state.bvhConfiguration);
|
||||
state.save=0;
|
||||
controls(controlMat,&state);
|
||||
writeBVHFile(
|
||||
"out.bvh",
|
||||
bvhHeader,
|
||||
0,// int prependTPose,
|
||||
bvhFrames
|
||||
);
|
||||
}
|
||||
|
||||
if (state.visualizationType!=state.previousVisualizationType)
|
||||
{
|
||||
state.redraw=1;
|
||||
state.previousVisualizationType=state.visualizationType;
|
||||
}
|
||||
|
||||
if (state.selectedJoint!=state.previousSelection)
|
||||
{
|
||||
state.previousSelection=state.selectedJoint;
|
||||
state.rotation=state.bvhConfiguration[state.selectedJoint];
|
||||
controls(controlMat,&state);
|
||||
state.redraw=1;
|
||||
}
|
||||
|
||||
if ( state.bvhConfiguration[state.selectedJoint]!=state.rotation )
|
||||
{
|
||||
state.bvhConfiguration[state.selectedJoint]=state.rotation;
|
||||
state.redraw=1;
|
||||
}
|
||||
|
||||
if (state.redraw)
|
||||
{
|
||||
memset(viewMat.data,0,1024*768*3*sizeof(char));
|
||||
|
||||
|
||||
//cv::Mat * openGLMatForVisualization = 0;
|
||||
if ( (visualizeOpenGLEnabled) && (state.visualizationType) )
|
||||
{
|
||||
//fprintf(stderr,"updateOpenGLView\n");
|
||||
updateOpenGLView(state.bvhConfiguration);
|
||||
|
||||
//fprintf(stderr,"visualizeOpenGL\n");
|
||||
unsigned int openGLFrameWidth=visWidth,openGLFrameHeight=visHeight;
|
||||
char * openGLFrame = visualizeOpenGL(&openGLFrameWidth,&openGLFrameHeight);
|
||||
//=====================================================================
|
||||
if (openGLFrame!=0)
|
||||
{
|
||||
fprintf(stderr,"Got Back an OpenGL frame..!\n");
|
||||
cv::Mat openGLMat(openGLFrameHeight, openGLFrameWidth, CV_8UC3);
|
||||
unsigned char * initialPointer = openGLMat.data;
|
||||
openGLMat.data=(unsigned char * ) openGLFrame;
|
||||
cv::cvtColor(openGLMat,viewMat,COLOR_RGB2BGR);
|
||||
openGLMat.data=initialPointer;
|
||||
}//=====================================================================
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"Failed getting an OpenGL frame..!\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state.bvhConfiguration.size()>0)
|
||||
{
|
||||
state.bvh2DPoints = convertBVHFrameTo2DPoints(state.bvhConfiguration); //visWidth,visHeight );
|
||||
}
|
||||
drawSkeleton(viewMat,state.bvh2DPoints,0,0,1);
|
||||
}
|
||||
|
||||
|
||||
cv::putText(viewMat,MocapNETOutputArrayNames[state.previousSelection], cv::Point(10,30), cv::FONT_HERSHEY_DUPLEX, 0.5, cv::Scalar::all(255), 0.2, 8 );
|
||||
|
||||
state.redraw=0;
|
||||
}
|
||||
|
||||
|
||||
imshow("BVH", viewMat);
|
||||
|
||||
waitKey(150);
|
||||
}
|
||||
// the camera will be deinitialized automatically in VideoCapture destructor
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
project( ReshapeCSV )
|
||||
cmake_minimum_required( VERSION 2.8.13 )
|
||||
#cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
#find_package(OpenCV REQUIRED)
|
||||
#INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
|
||||
|
||||
|
||||
|
||||
add_executable(ReshapeCSV reshapeCSV.cpp )
|
||||
target_link_libraries(ReshapeCSV rt dl m Tensorflow TensorflowFramework MocapNETLib2 )
|
||||
#set_target_properties(TestCSV PROPERTIES DEBUG_POSTFIX "D")
|
||||
|
||||
|
||||
set_target_properties(ReshapeCSV PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Utility to extract BVH files straight from OpenPose JSON output
|
||||
* Sample usage ./MocapNETCSV --from test.csv --visualize
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../MocapNETLib2/mocapnet2.hpp"
|
||||
#include "../MocapNETLib2/core/core.hpp"
|
||||
#include "../MocapNETLib2/IO/csvRead.hpp"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct MocapNET2 mnet;
|
||||
struct CSVFileContext csvT={0};
|
||||
unsigned long processedLines=0;
|
||||
|
||||
fprintf(stderr,"Run : \n");
|
||||
fprintf(stderr,"./createRandomizedDataset.sh\n");
|
||||
fprintf(stderr,"to update the dataset/bvh_body_all.csv to the latest version..\n\n");
|
||||
|
||||
fprintf(stdout,"Front,Back,Left,Right\n");
|
||||
|
||||
|
||||
char csvFileInput[1024];
|
||||
snprintf(csvFileInput,1024,"dataset/bvh_body_all.csv");
|
||||
|
||||
if (argc==2)
|
||||
{
|
||||
snprintf(csvFileInput,1024,"%s",argv[1]);
|
||||
} else
|
||||
{
|
||||
fprintf(stderr,"Please provide an argument i.e. \n ./reshapeCSV dataset/bvh_body_all.csv");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (openCSVFile(&csvT,csvFileInput))
|
||||
{
|
||||
fprintf(stderr,"CSV file had %u lines\n",csvT.lineNumber);
|
||||
//----------------------------------------------------
|
||||
struct skeletonSerialized skeletonS= {0};
|
||||
while ( parseNextCSVCOCOSkeleton(&csvT,&skeletonS) )
|
||||
//----------------------------------------------------
|
||||
{
|
||||
if (processedLines==0)
|
||||
{ initializeMocapNET2InputAssociation(&mnet,&skeletonS,1,1,1); }
|
||||
|
||||
unsigned int correspondingClass = getMocapNETOrientationFromAngle(skeletonS.skeletonBody[4].value);
|
||||
|
||||
if (processedLines%1000==0) { fprintf(stderr,"."); }
|
||||
//fprintf(stderr,".[%0.2f/%u]",skeletonS.skeletonBody[4].value,correspondingClass);
|
||||
|
||||
/*
|
||||
enum MOCAPNET_Orientation
|
||||
{
|
||||
MOCAPNET_ORIENTATION_NONE=0,
|
||||
MOCAPNET_ORIENTATION_FRONT,
|
||||
MOCAPNET_ORIENTATION_BACK,
|
||||
MOCAPNET_ORIENTATION_LEFT,
|
||||
MOCAPNET_ORIENTATION_RIGHT,
|
||||
//-----------------------------
|
||||
MOCAPNET_ORIENTATION_NUMBER
|
||||
};
|
||||
*/
|
||||
|
||||
switch(correspondingClass)
|
||||
{
|
||||
//The series here is important for MocapNETLib2/core.cpp:
|
||||
case MOCAPNET_ORIENTATION_NONE: fprintf(stdout,"0,0,0,0\n"); break; //Add erroneous categories to catch bugs
|
||||
case MOCAPNET_ORIENTATION_FRONT: fprintf(stdout,"1,0,0,0\n"); break;
|
||||
case MOCAPNET_ORIENTATION_BACK: fprintf(stdout,"0,1,0,0\n"); break;
|
||||
case MOCAPNET_ORIENTATION_LEFT: fprintf(stdout,"0,0,1,0\n"); break;
|
||||
case MOCAPNET_ORIENTATION_RIGHT: fprintf(stdout,"0,0,0,1\n"); break;
|
||||
default : fprintf(stdout,"0,0,0,0\n"); break; //Add erroneous categories to catch bugs
|
||||
};
|
||||
|
||||
++processedLines;
|
||||
}
|
||||
//----------------------------------------------------
|
||||
closeCSVFile(&csvT);
|
||||
}
|
||||
|
||||
|
||||
fprintf(stderr,"\nDon't forget, Run : \n");
|
||||
fprintf(stderr,"./createRandomizedDataset.sh\n");
|
||||
fprintf(stderr,"to update the dataset/bvh_body_all.csv to the latest version..\n\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
project( TestCSV )
|
||||
cmake_minimum_required( VERSION 2.8.13 )
|
||||
#cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
find_package(OpenCV REQUIRED)
|
||||
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
|
||||
|
||||
|
||||
|
||||
add_executable(TestCSV testCSV.cpp )
|
||||
target_link_libraries(TestCSV rt dl m Tensorflow TensorflowFramework MocapNETLib2 )
|
||||
#set_target_properties(TestCSV PROPERTIES DEBUG_POSTFIX "D")
|
||||
|
||||
|
||||
set_target_properties(TestCSV PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user