diff options
Diffstat (limited to 'src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw')
13 files changed, 10215 insertions, 0 deletions
diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTW.cpp b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTW.cpp new file mode 100644 index 00000000..bdbec8c2 --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTW.cpp @@ -0,0 +1,138 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies +* or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2011-01-18 15:41:43 +0530 (Tue, 18 Jan 2011) $ +* $Revision: 829 $ +* $Author: mnab $ +* +************************************************************************/ +/************************************************************************ +* FILE DESCR: Defines the entry for ActiveDTW dll application +* +* CONTENTS: +* +* AUTHOR: S Anand +* +w +* DATE: 3-MAR-2009 +* CHANGE HISTORY: +* Author Date Description of change +* Balaji MNA 18th Jan 2010 Receiving LTKShapeRecognizer as single pointer +* instead of double pointer in deleteShapeRecognizer +************************************************************************/ + + +#include "ActiveDTW.h" +#include "LTKShapeRecognizer.h" +#include "ActiveDTWShapeRecognizer.h" +#include "LTKException.h" +#include "LTKErrors.h" +#include "LTKOSUtilFactory.h" +#include "LTKOSUtil.h" + +#ifdef _WIN32 +#include <windows.h> + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} +#endif + +/** createShapeRecognizer **/ + +int createShapeRecognizer(const LTKControlInfo& controlInfo, + LTKShapeRecognizer** ptrObj ) +{ + try + { + *ptrObj = new ActiveDTWShapeRecognizer(controlInfo); + return SUCCESS; + } + catch(LTKException e) + { + LTKReturnError(e.getErrorCode()); + } +} + + +/**deleteShapeRecognizer **/ +int deleteShapeRecognizer(LTKShapeRecognizer *obj) +{ + try + { + if (obj != NULL ) + { + delete obj; + obj = NULL; + + //unloadDLLs(); + } + } + catch(LTKException e) + { + LTKReturnError(e.getErrorCode()); + } + + + return SUCCESS; +} + +/** unloadDLLs **/ +/* +void unloadDLLs() +{ +// Unload feature extractor DLL +if(m_libHandlerFE != NULL) +{ +//Unload the DLL +LTKUnloadDLL(m_libHandlerFE); +m_libHandlerFE = NULL; +} +}*/ + +/** getTraceGroups **/ +int getTraceGroups(LTKShapeRecognizer *obj, int shapeId, + int numberOfTraceGroups, + vector<LTKTraceGroup> &outTraceGroups) +{ + int errorCode = ((ActiveDTWShapeRecognizer*)obj)->getTraceGroups(shapeId, + numberOfTraceGroups, outTraceGroups); + + if ( errorCode != SUCCESS ) + { + LTKReturnError(errorCode); + } + + return SUCCESS; +} diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTW.def b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTW.def new file mode 100644 index 00000000..0a4f75c9 --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTW.def @@ -0,0 +1,4 @@ +EXPORTS + createShapeRecognizer @1 + deleteShapeRecognizer @2 + getTraceGroups @3
\ No newline at end of file diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTW.h b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTW.h new file mode 100644 index 00000000..854dc6da --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTW.h @@ -0,0 +1,95 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies +* or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2011-01-18 15:41:43 +0530 (Tue, 18 Jan 2011) $ +* $Revision: 829 $ +* $Author: mnab $ +* +************************************************************************/ +/************************************************************************ +* FILE DESCR: Declarations for ActiveDTW dll exporting functions. +* +* CONTENTS: +* +* AUTHOR: S Anand +* +w +* DATE: 3-MAR-2009 +* CHANGE HISTORY: +* Author Date Description of change +* Balaji MNA 18th Jan 2010 Receiving LTKShapeRecognizer as single pointer +* instead of double pointer in deleteShapeRecognizer +************************************************************************/ + +#ifndef __ACTIVEDTW_H__ +#define __ACTIVEDTW_H__ + +#include "LTKInc.h" +#include "LTKTypes.h" + +#ifdef _WIN32 +#ifdef ACTIVEDTW_EXPORTS +#define ACTIVEDTW_API __declspec(dllexport) +#else +#define ACTIVEDTW_API __declspec(dllimport) +#endif //#ifdef ACTIVEDTW_EXPORTS +#else +#define ACTIVEDTW_API +#endif //#ifdef _WIN32 + +class LTKTraceGroup; +class LTKShapeRecognizer; + + +/** @defgroup ActiveDTWShapeRecognizer ActiveDTWShapeRecognizer +*@brief The ActiveDTWShapeRecognizer +*/ + +/** +* @ingroup ActiveDTWShapeRecognizer +* @file ActiveDTW.cpp +*/ + +/** +* Crates instance of type ActiveDTWShapeRecognizer and returns of type +* LTKShpeRecognizer. (Acts as a Factory Method). +* +* @param none +* +* @return LTKShapeRecognizer - an instance of type LTKShapeRecognizer. +*/ +extern "C" ACTIVEDTW_API int createShapeRecognizer(const LTKControlInfo& controlInfo, + LTKShapeRecognizer** pReco ); + /** + * Destroy the instance by taking the address as its argument. + * + * @param obj - Address of LTKShapeRecognizer instance. + * + * @return 0 on Success +*/ +extern "C" ACTIVEDTW_API int deleteShapeRecognizer(LTKShapeRecognizer *obj); + +extern "C" ACTIVEDTW_API int getTraceGroups(LTKShapeRecognizer *obj, int shapeID, int numberOfTraceGroups,vector<LTKTraceGroup> &outTraceGroups); + +void unloadDLLs(); + +#endif //#ifndef __NN_H__ diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWAdapt.cpp b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWAdapt.cpp new file mode 100644 index 00000000..e0c36e6b --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWAdapt.cpp @@ -0,0 +1,1186 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies +* or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2009-04-06 11:55:15 +0530 (Mon, 06 Apr 2009) $ +* $Revision: 758 $ +* $Author: royva $ +* +************************************************************************/ +/********************************************************************************************* +* FILE DESCR: Definitions for ActiveDTW Adaptation module +* +* CONTENTS: +* +* AUTHOR: S Anand +* +w +* DATE:3-MAR-2009 +* CHANGE HISTORY: +* Author Date Description of change +***********************************************************************************************/ + +#include "ActiveDTWShapeRecognizer.h" +#include "ActiveDTWAdapt.h" +#include "LTKLoggerUtil.h" +#include "LTKConfigFileReader.h" +#include "LTKErrors.h" +#include "LTKErrorsList.h" +#include "LTKPreprocDefaults.h" + +LTKAdapt* LTKAdapt::adaptInstance = NULL; +int LTKAdapt::m_count = 0; + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : Constructor +* DESCRIPTION : +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +LTKAdapt::LTKAdapt(ActiveDTWShapeRecognizer* ptrActiveDTWShapeReco) +{ + m_activedtwShapeRecognizer = ptrActiveDTWShapeReco; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + << "Exit LTKAdapt::LTKAdapt()"<<endl; + + //Assign Default Values + + m_maxClusterSize = ADAPT_DEF_MAX_NUMBER_SAMPLES_PER_CLASS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : Destructor +* DESCRIPTION : +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +LTKAdapt::~LTKAdapt() +{ + +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : deleteInstance +* DESCRIPTION : delete AdaptInstance +* ARGUMENTS : +* RETURNS : None +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +void LTKAdapt::deleteInstance() +{ + m_count = 0; + if(adaptInstance) + { + delete adaptInstance; + adaptInstance = NULL; + } +} +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getInstance +* DESCRIPTION : +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +LTKAdapt* LTKAdapt::getInstance(ActiveDTWShapeRecognizer* ptrActiveDTWShapeReco) +{ + if(adaptInstance == NULL) + { + adaptInstance = new LTKAdapt(ptrActiveDTWShapeReco); + } + + return adaptInstance; + +} +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : Process +* DESCRIPTION : Performs adaptation +* ARGUMENTS : +* RETURNS : Success : If completed successfully +* Failure : Error Code +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int LTKAdapt::adapt(int shapeId) +{ + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + << "Enter LTKAdapt::adapt()"<<endl; + + int iErrorCode; + + //read config file values when first adapt sample is encountered + if(m_count==0) + { + m_count = 1; + + iErrorCode = readAdaptConfig(); + if(iErrorCode !=0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) + << "Error during LTKAdapt::readAdaptConfig()"<<endl; + LTKReturnError(FAILURE); + } + } + + + //Check if Cached variables are valid + if(m_activedtwShapeRecognizer->m_neighborInfoVec.size()==0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) + <<"DistanceIndexPair is empty"<<endl; + + LTKReturnError(ENEIGHBOR_INFO_VECTOR_EMPTY ); + } + + //check if test featureVector is empty + if(m_activedtwShapeRecognizer->m_cachedShapeFeature.size() <= 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) + <<"Features of input TraceGroup is empty"<<endl; + + LTKReturnError(ESHAPE_SAMPLE_FEATURES_EMPTY); + } + + //find out whether the test sample is close to a singleton or cluster + + //case of incorrect classification + if(m_activedtwShapeRecognizer->m_vecRecoResult.size() == 0 || + m_activedtwShapeRecognizer->m_vecRecoResult.at(0).getShapeId() != shapeId) + { + + int index = 0; + //iterating through neighborInfoVec to retrieve information about the true + //shape model of class + while(shapeId != m_activedtwShapeRecognizer->m_neighborInfoVec[index].classId ) + index++; + + if(m_activedtwShapeRecognizer->m_neighborInfoVec[index].typeId == CLUSTER) + { + int clusterId = m_activedtwShapeRecognizer->m_neighborInfoVec[index].sampleId; + + //adapting the cluster + iErrorCode = adaptCluster(m_activedtwShapeRecognizer->m_cachedShapeFeature,clusterId,shapeId); + + if(iErrorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<iErrorCode<< + " LTKAdapt::adapt" << endl; + LTKReturnError(iErrorCode); + } + } + else + { + //adapting the singleton set + iErrorCode = adaptSingleton(m_activedtwShapeRecognizer->m_cachedShapeFeature,shapeId); + if(iErrorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<iErrorCode<< + " LTKAdapt::adapt" << endl; + LTKReturnError(iErrorCode); + } + } + } + else + { + //case of correct classification + if(m_activedtwShapeRecognizer->m_neighborInfoVec[0].typeId == CLUSTER) + { + int clusterId = m_activedtwShapeRecognizer->m_neighborInfoVec[0].sampleId; + int iterator = 0; + while(m_activedtwShapeRecognizer->m_prototypeShapes[iterator].getShapeId() != shapeId) + iterator++; + + ActiveDTWShapeModel shapeModelToAdapt = m_activedtwShapeRecognizer->m_prototypeShapes[iterator]; + + vector<ActiveDTWClusterModel> currentClusterModelVector = shapeModelToAdapt.getClusterModelVector(); + + //adapt the model only if number of samples seen by the model is less than the threshold m_maxClustersize + if(currentClusterModelVector[clusterId].getNumSamples() < m_maxClusterSize) + { + iErrorCode = adaptCluster(m_activedtwShapeRecognizer->m_cachedShapeFeature,clusterId,shapeId); + + if(iErrorCode != SUCCESS) + { + currentClusterModelVector.clear(); + + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<iErrorCode<< + " LTKAdapt::adapt" << endl; + LTKReturnError(iErrorCode); + } + } + currentClusterModelVector.clear(); + } + else + { + //adapt singleton set + iErrorCode = adaptSingleton(m_activedtwShapeRecognizer->m_cachedShapeFeature,shapeId); + if(iErrorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<iErrorCode<< + " LTKAdapt::adapt" << endl; + LTKReturnError(iErrorCode); + } + } + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + << "Exit LTKAdapt::adapt()"<<endl; + + return(SUCCESS); +} + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : readAdaptConfig +* DESCRIPTION : Reads configuration info for adaptation +* ARGUMENTS : NONE +* RETURNS : NONE +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ +int LTKAdapt::readAdaptConfig() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + <<"Enter Adapt::readAdaptConfig" + <<endl; + + + LTKConfigFileReader *adaptConfigReader = NULL; + + adaptConfigReader = new LTKConfigFileReader(m_activedtwShapeRecognizer->m_activedtwCfgFilePath); + + + //Don't throw Error as ShapeRecognizer might not support ADAPT + string tempStringVar = ""; + int tempIntegerVar; + + int errorCode = adaptConfigReader->getConfigValue(MAXCLUSTERSIZE,tempStringVar); + + if(errorCode == SUCCESS) + { + if(LTKStringUtil::isInteger(tempStringVar)) + { + tempIntegerVar = atoi((tempStringVar).c_str()); + + if(tempIntegerVar > 1) + { + if(tempIntegerVar < m_activedtwShapeRecognizer->m_minClusterSize) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: "<< ECONFIG_FILE_RANGE << m_maxClusterSize << + " is out of permitted range MAXCUSTERSIZE < MINCLUSTERSIZE" << + " LTKAdapt::readAdaptConfig"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + else + { + m_maxClusterSize = tempIntegerVar; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + MAXCLUSTERSIZE << " = " <<m_maxClusterSize<<endl; + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: "<< ECONFIG_FILE_RANGE << m_maxClusterSize << + " is out of permitted range" << + " LTKAdapt::readAdaptConfig"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: "<< ECONFIG_FILE_RANGE << MAXCLUSTERSIZE << + " is out of permitted range" << + " LTKAdapt::readAdaptConfig"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << MAXCLUSTERSIZE << " : " << m_maxClusterSize << endl; + } + + + if(adaptConfigReader) + delete adaptConfigReader; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + <<"Exit LTKAdapt::readAdaptConfig" + <<endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : adaptCluster +* DESCRIPTION : This method adapts the cluster with the new featureVector. Implementation of method described in paper: +"Incremental eigenanalysis for classifiation, published in British Machine Vision Conference-2008" +* +* ARGUMENTS : INPUT +featureVecToAdapt shapeFeature +clusterId int +shapeId int +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ +int LTKAdapt::adaptCluster(shapeFeature& featureVecToAdapt,int clusterId,int shapeId) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "LTKAdapt::adaptCluster()" << endl; + + int errorCode; + + //validating input arguments + if(m_activedtwShapeRecognizer->m_shapeIDNumPrototypesMap.find(shapeId) == m_activedtwShapeRecognizer->m_shapeIDNumPrototypesMap.end()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_SHAPEID << " " << + " LTKAdapt::adaptCluster()" << endl; + LTKReturnError(EINVALID_SHAPEID); + } + + //finding the prototypeShape + int index = 0; + + int i = 0; + int j = 0; + + while(m_activedtwShapeRecognizer->m_prototypeShapes[index].getShapeId() != shapeId) + index++; + + ActiveDTWShapeModel shapeModelToAdapt = m_activedtwShapeRecognizer->m_prototypeShapes[index]; + + vector<ActiveDTWClusterModel> currentClusterModelVector = shapeModelToAdapt.getClusterModelVector(); + + if(clusterId < 0 || clusterId >= currentClusterModelVector.size()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_CLUSTER_ID << " " << + " LTKAdapt::adaptCluster()" << endl; + + LTKReturnError(EINVALID_CLUSTER_ID); + } + + + ActiveDTWClusterModel clusterToAdapt = currentClusterModelVector[clusterId]; + + //obtaining data of cluster + doubleVector oldEigenValues = clusterToAdapt.getEigenValues(); + + double2DVector oldEigenVectors = clusterToAdapt.getEigenVectors(); + + doubleVector oldClusterMean = clusterToAdapt.getClusterMean(); + + int numClusterSamples = clusterToAdapt.getNumSamples(); + + //convert the shapefeature to double vector + floatVector floatFeatureVector; + + doubleVector doubleFeatureVector; + + errorCode = m_activedtwShapeRecognizer->m_shapeRecUtil.shapeFeatureVectorToFloatVector(featureVecToAdapt,floatFeatureVector); + + if( errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + "LTKAdapt::adaptCluster" <<endl; + LTKReturnError(errorCode); + } + + int featureSize = floatFeatureVector.size(); + + for(i = 0; i < featureSize; i++) + doubleFeatureVector.push_back(floatFeatureVector[i]); + + floatFeatureVector.clear(); + + //the difference vector + //refers to y - x(mean) + doubleVector diffVector; + + //refers to g in the paper (Eqn 2) + //g = unp*(y - x(mean)) + doubleVector projectedTestSample; + + //refers to h in the paper (Eqn 3) + //h = (y - x(mean)) - (unp * g) + doubleVector residueVector; + + //refers to unp*g + doubleVector reverseProjection; + + int numEigenVectors = oldEigenVectors.size(); + + //calculating diffVector + for(i = 0; i < featureSize; i++) + diffVector.push_back(doubleFeatureVector[i] - oldClusterMean[i]); + + //constructing the projected test sample i.e g + for(i = 0; i < numEigenVectors; i++) + { + double tempValue = 0; + for(j = 0; j < featureSize; j++) + { + tempValue += (oldEigenVectors[i][j] * diffVector[j]); + } + projectedTestSample.push_back(tempValue); + } + + //constructing reverse projection + for(i = 0; i < featureSize; i++) + { + double tempValue = 0; + for(j = 0; j < numEigenVectors;j++) + { + tempValue += oldEigenVectors[j][i] * projectedTestSample[j]; + } + reverseProjection.push_back(tempValue); + } + + //construct residue vector + for(i = 0; i < featureSize; i++) + residueVector.push_back(diffVector[i] - reverseProjection[i]); + + //magnitude of residue vector + double residueMagnitude = 0; + + for(i = 0; i < featureSize; i++) + residueMagnitude = residueMagnitude + (residueVector[i] * residueVector[i]); + + residueMagnitude = sqrt(residueMagnitude); + + //determining the recomputed eigenValues and eigenVectors + //case 1 residueMagnitude is 0 + if(residueMagnitude == 0) + { + //construct the matrix whose eigen values and eigen vectors are to be calculated + doubleVector tempVector; + + //corresponds to matrix in eqn 10 + double2DVector coeff1; + + tempVector.assign(numEigenVectors,0.0); + + coeff1.assign(numEigenVectors,tempVector); + + for(i = 0; i < numEigenVectors; i++) + { + for(j = 0; j < numEigenVectors; j++) + { + if(i == j) + coeff1[i][j] = oldEigenValues[j]; + } + } + + for(i = 0; i < numEigenVectors; i++) + { + for(j = 0; j < numEigenVectors; j++) + coeff1[i][j] = (coeff1[i][j] * numClusterSamples)/(numClusterSamples + 1); + } + + //refers to eqn 11 in paper + double2DVector coeff2; + + coeff2.assign(numEigenVectors,tempVector); + + //constructing g*g(transpose) + for(i = 0; i < numEigenVectors; i++) + { + for(j = 0; j < numEigenVectors; j++) + coeff2[i][j] = projectedTestSample[i] * projectedTestSample[j]; + } + + for(i = 0; i < numEigenVectors; i++) + { + for(j = 0; j < numEigenVectors; j++) + coeff2[i][j] = (coeff2[i][j] * numClusterSamples) / ((numClusterSamples + 1) * (numClusterSamples + 1)); + } + + //final matrix + for(i = 0; i < numEigenVectors; i++) + { + for(j = 0; j < numEigenVectors; j++) + coeff1[i][j] += coeff2[i][j]; + } + + //solving the intermediate eigen value problem + //refers to eigenValue problem in eqn 12 + double2DVector intermediateEigenVectors; + doubleVector eigenValues; + int nrot = 0; + + intermediateEigenVectors.assign(numEigenVectors,tempVector); + + errorCode = m_activedtwShapeRecognizer->computeEigenVectors(coeff1,coeff1.size(),eigenValues,intermediateEigenVectors,nrot); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::adaptCluster()" << endl; + LTKReturnError(errorCode); + } + + //the new eigen vectors + double2DVector eigenVectors; + + eigenVectors.assign(featureSize,tempVector); + + tempVector.clear(); + + //calculating the new eigen vectors from the intermediateEigenVectors and oldEigenVectors + //refers to eqn 8 + for( i = 0; i < featureSize; i++) + { + for(j = 0; j < numEigenVectors; j++) + { + for(int k = 0; k < numEigenVectors;k++) + { + eigenVectors[i][j] += (oldEigenVectors[k][i] * intermediateEigenVectors[k][j]); + } + } + } + + //now converting the eigen vectors to row format + //this makes it easy to write the eigen vectors to the mdt file and read from it + double2DVector newEigenVectors; + + tempVector.assign(featureSize,0.0); + + newEigenVectors.assign(numEigenVectors,tempVector); + + for(i = 0; i < numEigenVectors; i++) + { + for(j = 0; j < featureSize; j++) + newEigenVectors[i][j] = eigenVectors[j][i]; + } + + numEigenVectors = 0; + double eigenEnergy = 0; + for( i = 0; i < eigenValues.size(); i++) + { + eigenEnergy += eigenValues[i]; + } + + double tempEigenEnergy = 0; + + while(tempEigenEnergy <= ((m_activedtwShapeRecognizer->m_percentEigenEnergy * eigenEnergy)/100)) + tempEigenEnergy += eigenValues[numEigenVectors++]; + + doubleVector selectedEigenValues; + double2DVector selectedEigenVectors; + for( i = 0; i < numEigenVectors; i++) + { + selectedEigenValues.push_back(eigenValues[i]); + selectedEigenVectors.push_back(newEigenVectors[i]); + } + + doubleVector newClusterMean; + + for( i = 0; i < featureSize; i++) + { + double tempValue = ((numClusterSamples * oldClusterMean[i]) + doubleFeatureVector[i])/(numClusterSamples + 1); + newClusterMean.push_back(tempValue); + } + + //updating the cluster model + errorCode = clusterToAdapt.setNumSamples(numClusterSamples + 1); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::adaptCluster()" << endl; + + LTKReturnError(errorCode); + } + + + clusterToAdapt.setEigenValues(selectedEigenValues); + selectedEigenValues.clear(); + + clusterToAdapt.setEigenVectors(selectedEigenVectors); + selectedEigenVectors.clear(); + + clusterToAdapt.setClusterMean(newClusterMean); + + currentClusterModelVector[clusterId] = clusterToAdapt; + + shapeModelToAdapt.setClusterModelVector(currentClusterModelVector); + + m_activedtwShapeRecognizer->m_prototypeShapes[index] = shapeModelToAdapt; + + //clearing vectors + tempVector.clear(); + coeff1.clear(); + coeff2.clear(); + eigenValues.clear(); + newEigenVectors.clear(); + intermediateEigenVectors.clear(); + newClusterMean.clear(); + eigenVectors.clear(); + } + else + { + //case residueMagnitude is not 0; + doubleVector unitResidueVector; + + for(i = 0; i < featureSize; i++) + unitResidueVector.push_back(residueVector[i]/residueMagnitude); + + //construct the matrix whose eigen values and eigen vectors are to be calculated + doubleVector tempVector; + + //refer to eqn 10 + double2DVector coeff1; + + tempVector.assign(numEigenVectors + 1,0.0); + + coeff1.assign(numEigenVectors + 1,tempVector); + + for( i = 0; i < numEigenVectors; i++) + { + for(j = 0; j < numEigenVectors; j++) + { + if(i == j) + { + coeff1[i][j] = oldEigenValues[j]; + } + } + } + + for( i = 0; i < (numEigenVectors + 1 ); i++) + { + for(j = 0; j < (numEigenVectors + 1); j++) + coeff1[i][j] = (coeff1[i][j] * numClusterSamples)/(numClusterSamples + 1); + } + + //refers to unith(transpose)*diffVector + double gamma = 0; + + for( i = 0; i < featureSize; i++) + gamma = gamma + (unitResidueVector[i] * diffVector[i]); + + //refers to eqn 11 + double2DVector coeff2; + + coeff2.assign(numEigenVectors + 1,tempVector); + + //constructing g*g(transpose) + for( i = 0; i < numEigenVectors; i++) + { + for(j = 0; j < numEigenVectors; j++) + coeff2[i][j] = projectedTestSample[i] * projectedTestSample[j]; + } + + //calculating gamma * projectedTestSample i.e gamma * g + doubleVector gammaProjTestSample; + + for( i = 0; i < numEigenVectors; i++) + gammaProjTestSample.push_back(projectedTestSample[i]*gamma); + + for( i = 0; i < numEigenVectors; i++) + { + coeff2[i][numEigenVectors] = gammaProjTestSample[i]; + coeff2[numEigenVectors][i] = gammaProjTestSample[i]; + } + + coeff2[numEigenVectors][numEigenVectors] = gamma * gamma; + + for( i = 0; i < numEigenVectors + 1; i++) + { + for(j = 0; j < numEigenVectors + 1; j++) + coeff2[i][j] = (coeff2[i][j] * numClusterSamples) / ((numClusterSamples + 1) * (numClusterSamples + 1)); + } + + //final matrix + for( i = 0; i < numEigenVectors + 1; i++) + { + for(j = 0; j < numEigenVectors + 1; j++) + coeff1[i][j] = coeff1[i][j] + coeff2[i][j]; + } + + //solving the intermediate eigen value problem + //refers to eqn 12 + double2DVector intermediateEigenVectors; + doubleVector eigenValues; + int nrot = 0; + + intermediateEigenVectors.assign(numEigenVectors + 1,tempVector); + + errorCode = m_activedtwShapeRecognizer->computeEigenVectors(coeff1,coeff1.size(),eigenValues,intermediateEigenVectors,nrot); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::adaptCluster()" << endl; + LTKReturnError(errorCode); + } + + //the new eigen vectors + double2DVector eigenVectors; + + //adding unith to the old set of eigen vectors + oldEigenVectors.push_back(unitResidueVector); + + eigenVectors.assign(featureSize,tempVector); + + tempVector.clear(); + + //calculating the new eigen vectors from the oldEigenVectors + //refers to eqn 8 + for( i = 0; i < featureSize; i++) + { + for(j = 0; j < (numEigenVectors + 1); j++) + { + for(int k = 0; k < (numEigenVectors + 1);k++) + { + eigenVectors[i][j] = eigenVectors[i][j] + (oldEigenVectors[k][i] * intermediateEigenVectors[k][j]); + } + } + } + + //now converting the eigen vectors to row format + //this makes it easy to write the eigen vectors to the mdt file and read from it + double2DVector newEigenVectors; + + tempVector.assign(featureSize,0.0); + + newEigenVectors.assign(numEigenVectors + 1,tempVector); + + for( i = 0; i < numEigenVectors + 1; i++) + { + for(j = 0; j < featureSize; j++) + newEigenVectors[i][j] = eigenVectors[j][i]; + } + + doubleVector newClusterMean; + + for( i = 0; i < featureSize; i++) + { + double tempValue = ((numClusterSamples * oldClusterMean[i]) + doubleFeatureVector[i])/(numClusterSamples + 1); + newClusterMean.push_back(tempValue); + } + + numEigenVectors = 0; + double eigenEnergy = 0; + for( i = 0; i < eigenValues.size(); i++) + { + eigenEnergy += eigenValues[i]; + } + + double tempEigenEnergy = 0; + + while(tempEigenEnergy <= ((m_activedtwShapeRecognizer->m_percentEigenEnergy * eigenEnergy)/100)) + tempEigenEnergy += eigenValues[numEigenVectors++]; + + + doubleVector selectedEigenValues; + double2DVector selectedEigenVectors; + for( i = 0; i < numEigenVectors; i++) + { + selectedEigenValues.push_back(eigenValues[i]); + selectedEigenVectors.push_back(newEigenVectors[i]); + } + + //updating the cluster model + + errorCode = clusterToAdapt.setNumSamples(numClusterSamples + 1); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::adaptCluster()" << endl; + + LTKReturnError(errorCode); + } + + clusterToAdapt.setEigenValues(selectedEigenValues); + selectedEigenValues.clear(); + clusterToAdapt.setEigenVectors(selectedEigenVectors); + selectedEigenVectors.clear(); + + clusterToAdapt.setClusterMean(newClusterMean); + + currentClusterModelVector[clusterId] = clusterToAdapt; + + shapeModelToAdapt.setClusterModelVector(currentClusterModelVector); + + m_activedtwShapeRecognizer->m_prototypeShapes[index] = shapeModelToAdapt; + + //clearing vectors + tempVector.clear(); + coeff1.clear(); + coeff2.clear(); + gammaProjTestSample.clear(); + eigenValues.clear(); + newEigenVectors.clear(); + intermediateEigenVectors.clear(); + newClusterMean.clear(); + eigenVectors.clear(); + unitResidueVector.clear(); + } + + //clearing vectors + oldEigenValues.clear(); + oldEigenVectors.clear(); + oldClusterMean.clear(); + doubleFeatureVector.clear(); + projectedTestSample.clear(); + residueVector.clear(); + reverseProjection.clear(); + diffVector.clear(); + currentClusterModelVector.clear(); + + errorCode = m_activedtwShapeRecognizer->writePrototypeShapesToMDTFile(); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::adaptCluster()" << endl; + LTKReturnError(errorCode); + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "LTKAdapt::adaptCluster()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : adaptSingleton +* DESCRIPTION : This method adapts the singleton sey with the +new featureVector and trains the singleton set if the +number of singletons exceeds a certain number +* ARGUMENTS : INPUT +featureVecToAdapt shapeFeature +shapeId int +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ +int LTKAdapt::adaptSingleton(shapeFeature& featureVecToAdapt,int shapeId) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "LTKAdapt::adaptSingleton()" << endl; + + //validating input parameters + if(m_activedtwShapeRecognizer->m_shapeIDNumPrototypesMap.find(shapeId) == m_activedtwShapeRecognizer->m_shapeIDNumPrototypesMap.end()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_SHAPEID << " " << + " LTKAdapt::adaptCluster()" << endl; + LTKReturnError(EINVALID_SHAPEID); + } + + int errorCode; + + int index = 0; + + //iterating prototypeShapes to find the shapeModel To Adapt + while(m_activedtwShapeRecognizer->m_prototypeShapes[index].getShapeId() != shapeId) + index++; + + shapeMatrix currentSingletonVectors = m_activedtwShapeRecognizer->m_prototypeShapes[index].getSingletonVector(); + + currentSingletonVectors.push_back(featureVecToAdapt); + + m_activedtwShapeRecognizer->m_prototypeShapes[index].setSingletonVector(currentSingletonVectors); + + int singletonSize = currentSingletonVectors.size(); + + //train the singletons only if their number is above some threshold + if(singletonSize > (TRAINSINGLETONFACTOR * m_activedtwShapeRecognizer->m_minClusterSize) ) + { + errorCode = trainSingletons(currentSingletonVectors,shapeId,index); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::adaptSingleton()" << endl; + LTKReturnError(errorCode); + } + } + + currentSingletonVectors.clear(); + + //updating the mdt file + errorCode = m_activedtwShapeRecognizer->writePrototypeShapesToMDTFile(); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::adaptCluster()" << endl; + LTKReturnError(errorCode); + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "LTKAdapt::adaptSingleton()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : trainSingletons +* DESCRIPTION : This method trains the featureVectors in the singleton set +* ARGUMENTS : INPUT +singletons shapeMatrix +shapeId int +index int +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ +int LTKAdapt::trainSingletons(const shapeMatrix &singletons,int shapeId,int index) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "LTKAdapt::trainSingletons()" << endl; + + //validating input arguments + if(m_activedtwShapeRecognizer->m_shapeIDNumPrototypesMap.find(shapeId) == m_activedtwShapeRecognizer->m_shapeIDNumPrototypesMap.end()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_SHAPEID << " " << + " LTKAdapt::adaptCluster()" << endl; + LTKReturnError(EINVALID_SHAPEID); + } + + if(index < 0 || index >= m_activedtwShapeRecognizer->m_prototypeShapes.size()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EPROTOYPESHAPE_INDEX_OUT_OF_BOUND << " " << + " LTKAdapt::adaptSingleton()" << endl; + + LTKReturnError(EPROTOYPESHAPE_INDEX_OUT_OF_BOUND); + } + + int errorCode; + + LTKShapeSample tempShape; + + vector<LTKShapeSample> shapesToTrain; + + int singletonSize = singletons.size(); + + int2DVector clusterOutput; + + shapeMatrix newSingletons; + + vector<ActiveDTWClusterModel> currentClusterModelVector = m_activedtwShapeRecognizer->m_prototypeShapes[index].getClusterModelVector(); + + int i = 0; + + for(i = 0; i < singletonSize; i++) + { + tempShape.setFeatureVector(singletons[i]); + shapesToTrain.push_back(tempShape); + } + + //perform clustering + errorCode = m_activedtwShapeRecognizer->performClustering(shapesToTrain,clusterOutput); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::trainSingletons()" << endl; + LTKReturnError(errorCode); + } + + int2DVector::iterator iter = clusterOutput.begin(); + int2DVector::iterator iEnd = clusterOutput.end(); + intVector cluster; + + /**ITERATING THROUGH THE VARIOUS CLUSTERS **/ + for(;iter != iEnd; ++iter) + { + cluster = (*iter); + + /** SINGLETON VECTORS **/ + if(cluster.size() < m_activedtwShapeRecognizer->m_minClusterSize) + { + for(i = 0; i < cluster.size(); i++) + newSingletons.push_back(shapesToTrain[cluster[i]].getFeatureVector()); + } + + /** CLUSTER PROCESSING **/ + else + { + //creating new clusters + doubleVector tempFeature; + + double2DVector featureMatrix; + + double2DVector covarianceMatrix; + + doubleVector clusterMean; + + double2DVector intermediateEigenVectors; + + double2DVector eigenVectors; + + doubleVector eigenValues; + + ActiveDTWClusterModel clusterModel; + + //gather all the shape samples pertaining to a particular cluster + int clusterSize = cluster.size(); + for(i = 0; i < clusterSize; i++) + { + floatVector floatFeatureVector; + + errorCode = m_activedtwShapeRecognizer->m_shapeRecUtil.shapeFeatureVectorToFloatVector(shapesToTrain[cluster[i]].getFeatureVector(), + floatFeatureVector); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::trainSingletons()" << endl; + + LTKReturnError(errorCode); + } + + int floatFeatureVectorSize = floatFeatureVector.size(); + for(int i = 0; i < floatFeatureVectorSize; i++) + tempFeature.push_back(floatFeatureVector[i]); + + featureMatrix.push_back(tempFeature); + tempFeature.clear(); + floatFeatureVector.clear(); + } + + /** COMPUTING COVARIANCE MATRIX **/ + errorCode = m_activedtwShapeRecognizer->computeCovarianceMatrix(featureMatrix,covarianceMatrix,clusterMean); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::trainSingletons()" << endl; + + LTKReturnError(errorCode); + } + + clusterModel.setClusterMean(clusterMean); + + errorCode = m_activedtwShapeRecognizer->computeEigenVectorsForLargeDimension(featureMatrix,covarianceMatrix,intermediateEigenVectors,eigenValues); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::trainSingletons()" << endl; + + LTKReturnError(errorCode); + } + + doubleVector tempEigenVector; + int eigenVectorDimension = intermediateEigenVectors.size(); + if(eigenVectorDimension <= 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EEMPTY_EIGENVECTORS << " " << + " LTKAdapt::trainSingletons()" << endl; + + LTKReturnError(EEMPTY_EIGENVECTORS); + } + + int numEigenVectors = intermediateEigenVectors[0].size(); + + if(numEigenVectors <= 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_NUM_OF_EIGENVECTORS << " " << + " LTKAdapt::trainSingletons()" << endl; + + LTKReturnError(EINVALID_NUM_OF_EIGENVECTORS); + } + + for(i = 0; i < numEigenVectors; i++) + { + for(int j = 0; j < eigenVectorDimension; j++) + tempEigenVector.push_back(intermediateEigenVectors[j][i]); + + eigenVectors.push_back(tempEigenVector); + tempEigenVector.clear(); + } + + /**CONSTRUCTING CLUSTER MODEL **/ + + errorCode = clusterModel.setNumSamples(cluster.size()); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " LTKAdapt::trainSingletons()" << endl; + + LTKReturnError(errorCode); + } + + clusterModel.setEigenValues(eigenValues); + + clusterModel.setEigenVectors(eigenVectors); + + currentClusterModelVector.push_back(clusterModel); + + //clearing vectors + featureMatrix.clear(); + covarianceMatrix.clear(); + clusterMean.clear(); + intermediateEigenVectors.clear(); + eigenVectors.clear(); + eigenValues.clear(); + + } + } + + //updating the shape model + (m_activedtwShapeRecognizer->m_prototypeShapes[index]).setClusterModelVector(currentClusterModelVector); + m_activedtwShapeRecognizer->m_prototypeShapes[index].setSingletonVector(newSingletons); + + //clearing vectors + currentClusterModelVector.clear(); + clusterOutput.clear(); + shapesToTrain.clear(); + newSingletons.clear(); + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "LTKAdapt::trainSingletons()" << endl; + + return SUCCESS; +} diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWAdapt.h b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWAdapt.h new file mode 100644 index 00000000..276eeb24 --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWAdapt.h @@ -0,0 +1,194 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ + +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2009-04-06 11:55:15 +0530 (Mon, 06 Apr 2009) $ +* $Revision: 758 $ +* $Author: royva $ +* +************************************************************************/ + +/************************************************************************ +* FILE DESCR: Implements ActiveDTWShapeRecognizer::Adapt +* +* CONTENTS: +* +* AUTHOR: S Anand +* +* DATE: 3-MAR-2009 +* CHANGE HISTORY: +* Author Date Description +************************************************************************/ +#pragma once + +#include "ActiveDTWShapeRecognizer.h" +#include "LTKLoggerUtil.h" +#include "LTKConfigFileReader.h" +#include "LTKErrors.h" +#include "LTKErrorsList.h" +#include "LTKPreprocDefaults.h" + +#define TRAINSINGLETONFACTOR 2 + +class ActiveDTWShapeRecognizer; + +class LTKAdapt +{ +private: + /** @name Constructor */ + LTKAdapt(ActiveDTWShapeRecognizer* ptrActiveDTWShapeReco); + + + static LTKAdapt* adaptInstance; + + static int m_count; + /**< @brief + * <p> + * Initially m_count = 0, when adapt is called on first sample + * it checks if m_count = 0, if yes it calls readAdaptConfig and then increments m_count to 1 + * Thus readAdaptConfig is called only once + * </p> + */ + +public: + static LTKAdapt* getInstance(ActiveDTWShapeRecognizer* ptrActiveDTWShapeReco); + + /** + * Adapts the shapeId + * + * Semantics + * + * - Reads the internal classifier config information incase of first sample to be adapted + + - Checks if the sample to be adapted was correctly classified or incorrectly classified + + - Incase of correct classification + --Check if the shape was closest to the cluster or singletons + --If sample to be adapted was closest to the clusters, and cluster size does not exceed + m_maxClusterSize, then call adaptCluster + --It sample to be adapted was closest to the singleton, call adaptSingleton + + -Incase of incorrect classification + --If the sample to be adapted was closest to a cluster, call adaptCluster + --If the sample to be adapted was closest to a singleton, call adaptSingleton + * + * @param shapeId : shape to be adapted + * @return SUCCESS : if the shapeId was adapted successfully + * ErrorCode: if some error occurs + * @exception ENEIGHBOR_INFO_VECTOR_EMPTY : ActiveDTWShapeRecognizer::m_neighbofInfoVec is empty + * @exception ESHAPE_SAMPLE_FEATURES_EMPTY : ActiveDTWShapeRecognizer::m_cachedShapeFeature is empty + */ + int adapt(int shapeId); + + /** @name Destructor */ + ~LTKAdapt(); + + void deleteInstance(); + +private: + +/**< @brief Pointer to ActiveDTWShapeRecognizer +* <p> +* +* </p> + */ + ActiveDTWShapeRecognizer* m_activedtwShapeRecognizer; + + //the maximum number of samples in a cluster + int m_maxClusterSize; + /**< @brief Maximum Cluster Size + * <p> + * Specifies the maximum number of samples that can be present in a cluster + * It must be >= the ActiveDTWShapeRecognizer::m_minClusterSize + * </p> + */ + + + /** + * This method reads Config variables related to Adapt from CFG + * + * Semantics + * + * + * @param none + * + * @return SUCCESS: + * FAILURE: return ErrorCode + * @exception none + */ + int readAdaptConfig(); + + /** + * Adapts the cluster with the new shapeFeature + * + * Semantics + * + * - Recomputes the eigen values, eigen vectors and cluster mean, + * using the old values and the new shape feature + * + * @param featureVecToAdapt : shapeFeature + * @param clusterId : cluster to be adapted + * @param shapeId : shape to be adapted + * @return SUCCESS : if the shapeId was adapted successfully + * ErrorCode: if some error occurs + * @exception EINVALID_SHAPEID + * @exception EINVALID_CLUSTER_ID + */ + int adaptCluster(shapeFeature& featureVecToAdapt,int clusterId,int shapeId); + + /** + * Adapts the set of singletons with the new shapeFeature + * + * Semantics + * + * - Adds the new shapeFeature to the current set of singletons + * + * - If the number of singletons exceeds a certain threshold train the singletons + * + * @param featureVecToAdapt : shapeFeature + * @param shapeId : shape to be adapted + * @return SUCCESS : if the shapeId was adapted successfully + * ErrorCode: if some error occurs + * @exception EINVALID_SHAPEID + */ + int adaptSingleton(shapeFeature& featureVecToAdapt,int shapeId); + + /** + * Performs training on the set of singletons + * + * Semantics + * + * - performs clustering on the singletons, resulting in new clusters and singleton set + * + * - cluster and singleton information are added to the shape model + * + * @param singletons : shapeMatrix + * @param shapeId : shape to be adapted + * @param index : index in ActiveDTWShapeRecognizer::m_prototypeShapes which holds the shapeModel information + * @return SUCCESS : if the shapeId was adapted successfully + * ErrorCode: if some error occurs + * @exception EINVALID_SHAPEID : shapeId specified is Invalid + * @exception EPROTOYPESHAPE_INDEX_OUT_OF_BOUND ; index value specified is Invalid + * @exception EEMPTY_EIGENVECTORS ; eigen vector dimension is < 0 + * @exception EINVALID_NUM_OF_EIGENVECTORS : number of eigen vectors < 0 + */ + int trainSingletons(const shapeMatrix &singletons,int shapeId,int index); +}; diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWClusterModel.cpp b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWClusterModel.cpp new file mode 100644 index 00000000..34886d32 --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWClusterModel.cpp @@ -0,0 +1,211 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies +* or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2009-04-06 11:55:15 +0530 (Mon, 06 Apr 2009) $ +* $Revision: 758 $ +* $Author: royva $ +* +************************************************************************/ +/********************************************************************************************* +* FILE DESCR: Implementation for ActiveDTW Cluster Model. Used to store cluster model information +* +* CONTENTS: +* +* AUTHOR: S Anand +* +w +* DATE:3-MAR-2009 +* CHANGE HISTORY: +* Author Date Description of change +***********************************************************************************************/ + +#include "ActiveDTWClusterModel.h" + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : ActiveDTWClusterModel +* DESCRIPTION : Default Constructor +* ARGUMENTS : none +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +ActiveDTWClusterModel::ActiveDTWClusterModel() +{ + +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : setNumSamples +* DESCRIPTION : sets the number of samples in the cluster +* ARGUMENTS : INPUT: numSamples +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWClusterModel::setNumSamples(int numSamples) +{ + if(numSamples > 0) + { + m_numberOfSamples = numSamples; + } + else + { + LTKReturnError(EINVALID_NUM_SAMPLES); + } + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getNumSamples +* DESCRIPTION : returns the number of samples in a cluster +* ARGUMENTS : none +* RETURNS : number of samples +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWClusterModel::getNumSamples() const +{ + return m_numberOfSamples; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : setEigenValues +* DESCRIPTION : sets the eigen values of the cluster +* ARGUMENTS : INPUT: eigen values +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +void ActiveDTWClusterModel::setEigenValues(const doubleVector& eigVal) +{ + m_eigenValues = eigVal; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : setClusterMean +* DESCRIPTION : sets the cluster mean of the cluster +* ARGUMENTS : INPUT: clusterMean +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +void ActiveDTWClusterModel::setClusterMean(const doubleVector& clusterMean) +{ + m_clusterMean = clusterMean; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getEigenValues +* DESCRIPTION : returns the eigen values of the cluster +* ARGUMENTS : none +* RETURNS : eigen values +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +const doubleVector& ActiveDTWClusterModel::getEigenValues() const +{ + return m_eigenValues; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : setEigenVectors +* DESCRIPTION : sets the eigen vectors of the cluster +* ARGUMENTS : eigen vectors +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +void ActiveDTWClusterModel::setEigenVectors(const double2DVector& eigVec) +{ + m_eigenVectors = eigVec; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getEigenVectors +* DESCRIPTION : returns the eigen vectors of the cluster +* ARGUMENTS : none +* RETURNS : eigen vectors +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +const double2DVector& ActiveDTWClusterModel::getEigenVectors() const +{ + return m_eigenVectors; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getClusterMean +* DESCRIPTION : returns the cluster mean of the cluster +* ARGUMENTS : none +* RETURNS : cluster mean +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +const doubleVector& ActiveDTWClusterModel::getClusterMean() const +{ + return m_clusterMean; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : ~ActiveDTWClusterModel +* DESCRIPTION : Default Destructor +* ARGUMENTS : none +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +ActiveDTWClusterModel::~ActiveDTWClusterModel() +{ + +} + diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWClusterModel.h b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWClusterModel.h new file mode 100644 index 00000000..4d183487 --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWClusterModel.h @@ -0,0 +1,161 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies +* or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2011-01-11 13:48:17 +0530 (Tue, 11 Jan 2011) $ +* $Revision: 827 $ +* $Author: mnab $ +* +************************************************************************/ +/********************************************************************************************* +* FILE DESCR: Definitions for ActiveDTWClusterModel Class +* +* CONTENTS: +* +* AUTHOR: S Anand +* DATE:3-MAR-2009 +* CHANGE HISTORY: +* Author Date Description of change +***********************************************************************************************/ + + +#ifndef ACTIVEDTWCLUSTERMODEL_H +#define ACTIVEDTWCLUSTERMODEL_H + +#include <iostream> +#include "LTKTypes.h" +#include "LTKInc.h" +#include "LTKMacros.h" +#include "LTKErrors.h" +#include "LTKErrorsList.h" + +using namespace std; + +typedef vector<double> doubleVector; +typedef vector<doubleVector> double2DVector; + +/** +* @ingroup ActiveDTWShapeModel.h +* @brief The Header file for the ActiveDTWShapeModel +* @class ActiveDTWShapeModel +*<p> <p> +*/ +class ActiveDTWClusterModel +{ +private: + int m_numberOfSamples; + /** @brief Number of samples in the cluster + * <p> + * Specifies the number of samples in the cluster + * </p> + */ + + doubleVector m_eigenValues; + /** @brief Eigen Values + * <p> + * Eigen values of the cluster covariance matrix + * </p> + */ + + double2DVector m_eigenVectors; + /** @brief Eigen Vectors + * <p> + * Eigen vectors of the cluster covariance matrix + * </p> + */ + + doubleVector m_clusterMean; + /** @brief Cluster mean + * <p> + * Mean of all the samples forming the cluster + * </p> + */ + +public: + + /** @name Constructors and Destructor */ + ActiveDTWClusterModel(); + + ~ActiveDTWClusterModel(); + + /** + * Sets the number of samples in the cluster + * @param numSamples + * @return SUCCESS : if the number of samples was set successfully + * @exception EINVALID_SHAPEID + */ + int setNumSamples(int numSamples); + + /** + * Sets the eigen values of the cluser + * @param eigVal + * @return SUCCESS : if the number of samples was set successfully + * @exception EINVALID_SHAPEID + */ + void setEigenValues(const doubleVector& eigVal); + + /** + * Sets the eigen vectors of the cluster + * @param eigVec + * @return SUCCESS : if the number of samples was set successfully + * @exception EINVALID_SHAPEID + */ + void setEigenVectors(const double2DVector& eigVec); + + /** + * Sets the mean of the cluster + * @param clusterMean + * @return SUCCESS : if the number of samples was set successfully + * @exception EINVALID_SHAPEID + */ + void setClusterMean(const doubleVector& clusterMean); + + /** + * Returns the number of samples in the cluster + * @return number of samples + * @exception EINVALID_SHAPEID + */ + int getNumSamples() const; + + /** + * Returns the eigen values of the cluster + * @return eigen values + * @exception EINVALID_SHAPEID + */ + const doubleVector& getEigenValues() const; + + /** + * Returns the eigen vectors of the cluster + * @return eigen vectors + * @exception EINVALID_SHAPEID + */ + const double2DVector& getEigenVectors() const; + + /** + * Returns the mean of the cluster + * @return cluster mean + * @exception EINVALID_SHAPEID + */ + const doubleVector& getClusterMean() const; + + +}; +#endif diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeModel.cpp b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeModel.cpp new file mode 100644 index 00000000..2514a626 --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeModel.cpp @@ -0,0 +1,178 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies +* or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2009-04-06 11:55:15 +0530 (Mon, 06 Apr 2009) $ +* $Revision: 758 $ +* $Author: royva $ +* +************************************************************************/ +/********************************************************************************************* +* FILE DESCR: Implementation for ActiveDTW Shape Model. Used to store shape model information +* +* CONTENTS: +* +* AUTHOR: S Anand +* +* DATE:3-MAR-2009 +* CHANGE HISTORY: +* Author Date Description of change +***********************************************************************************************/ + +#include "ActiveDTWShapeModel.h" + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : ActiveDTWShapeModel +* DESCRIPTION : Default Constructor +* ARGUMENTS : none +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +ActiveDTWShapeModel::ActiveDTWShapeModel() +{ + +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : setShapeId +* DESCRIPTION : sets the shape id for the shape model +* ARGUMENTS : INPUT: shapeId +* RETURNS : SUCCESS - on successfully setting the shape id +: ErrorCode - otherwise +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeModel::setShapeId(const int shapeId) +{ + if(shapeId >= 0) + { + m_shapeId = shapeId; + } + else + { + LTKReturnError(EINVALID_SHAPEID); + } + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : setClusterModelVector +* DESCRIPTION : sets the vector of clusters for the ActiveDTWShapeModel +* ARGUMENTS : INPUT: clusterModelVector +* RETURNS : NONE +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +void ActiveDTWShapeModel::setClusterModelVector(const vector<ActiveDTWClusterModel>& clusterModelVector) +{ + m_clusterModelVector = clusterModelVector; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : setSingletonVector +* DESCRIPTION : sets the vector of singletons for the shape model +* ARGUMENTS : INPUT: shapeId +* RETURNS : NONE +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +void ActiveDTWShapeModel::setSingletonVector(const shapeMatrix& singletonVector) +{ + m_singletonVector = singletonVector; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getShapeId +* DESCRIPTION : returns the shapeId of the model +* ARGUMENTS : INPUT: NULL +* RETURNS : shapeId +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeModel::getShapeId() const +{ + return m_shapeId; +} + +/************************************************************************************* +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getClusterModelVector +* DESCRIPTION : returns the clusters model vector +* ARGUMENTS : INPUT: NULL +* RETURNS : clusterModelVector +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +const vector<ActiveDTWClusterModel>& ActiveDTWShapeModel::getClusterModelVector() const +{ + return m_clusterModelVector; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getSingletonVector +* DESCRIPTION : returns the set of singleton vectors +* ARGUMENTS : INPUT: NULL +* RETURNS : shapeMatrix +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +const shapeMatrix& ActiveDTWShapeModel::getSingletonVector() const +{ + return m_singletonVector; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : ~ActiveDTWShapeModel +* DESCRIPTION : Destructor +* ARGUMENTS : NONE +* RETURNS : NONE +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +ActiveDTWShapeModel::~ActiveDTWShapeModel() +{ + +} diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeModel.h b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeModel.h new file mode 100644 index 00000000..f79182ea --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeModel.h @@ -0,0 +1,139 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies +* or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2009-04-06 11:55:15 +0530 (Mon, 06 Apr 2009) $ +* $Revision: 758 $ +* $Author: royva $ +* +************************************************************************/ +/************************************************************************ +* FILE DESCR: Definitions for ActiveDTW Shape Recognition module +* +* CONTENTS: +* +* AUTHOR: +* +* DATE: +* CHANGE HISTORY: +* Author Date Description of change +************************************************************************/ +#ifndef ACTIVEDTWSHAPEMODEL_H +#define ACTIVEDTWSHAPEMODEL_H +#include <iostream> +#include "LTKTypes.h" +#include "ActiveDTWClusterModel.h" +#include "LTKShapeFeatureMacros.h" +#include "LTKShapeFeature.h" +#include "LTKInc.h" + +using namespace std; + +typedef vector<LTKShapeFeaturePtr> shapeFeature; +typedef vector<shapeFeature> shapeMatrix; + +/** +* @ingroup ActiveDTWShapeModel.h +* @brief The Header file for the ActiveDTWShapeModel +* @class ActiveDTWShapeModel +*<p> <p> +*/ +class ActiveDTWShapeModel +{ +private: + int m_shapeId; + /** @brief shape id of the class + * <p> + * It specifies a specific shape id to each shape model + * </p> + */ + + vector<ActiveDTWClusterModel> m_clusterModelVector; + /**< @brief vector of cluster models + * <p> + * Contains the information of all the clusters of the class + * </p> + */ + + shapeMatrix m_singletonVector; + /**< @brief singletons /free samples of the class + * <p> + * Contains all the singleton vectors of the class + * </p> + */ + +public: + + /** @name Constructors and Destructor */ + ActiveDTWShapeModel(); + + ~ActiveDTWShapeModel(); + + /** + * Sets the shapeId of the class + * @param shapeId + * @return SUCCESS : if the shapeId was set successfully + * @exception EINVALID_SHAPEID + */ + int setShapeId(const int shapeId); + + /** + * Sets the clusterModelVector of the class + * @param clusterModelVector : vector<ActiveDTWClusterModel> + * @return NULL + * @exception None + */ + void setClusterModelVector(const vector<ActiveDTWClusterModel>& clusterModelVector); + + /** + * Sets the singleton vector of the class + * @param singletonVector : shapeMatrix + * @return NULL + * @exception None + */ + void setSingletonVector(const shapeMatrix& singletonVector); + + /** + * Returns the shapeId of the class + * @param None + * @return shapeId + * @exception None + */ + int getShapeId() const; + + /** + * Returns the clusterModelVector of the class + * @param None + * @return vector<ActiveDTWClusterModel> + * @exception None + */ + const vector<ActiveDTWClusterModel>& getClusterModelVector() const; + + /** + * Returns the singletonVector of the class + * @param None + * @return shapeMatrix + * @exception None + */ + const shapeMatrix& getSingletonVector() const ; +}; + +#endif diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeRecognizer.cpp b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeRecognizer.cpp new file mode 100644 index 00000000..247f5f98 --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeRecognizer.cpp @@ -0,0 +1,6257 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies +* or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2011-02-08 16:57:52 +0530 (Tue, 08 Feb 2011) $ +* $Revision: 834 $ +* $Author: mnab $ +* +************************************************************************/ +/************************************************************************ +* FILE DESCR: Implementation for ActiveDTW Shape Recognition module +* +* CONTENTS: +* +* AUTHOR: S Anand +* +w +* DATE: 3-MAR-2009 +* CHANGE HISTORY: +* Author Date Description of change +************************************************************************/ + +#include "LTKConfigFileReader.h" + +#include "ActiveDTWShapeRecognizer.h" + +#include "LTKPreprocDefaults.h" + +#include "LTKHierarchicalClustering.h" + +#include "LTKPreprocessorInterface.h" + +#include "LTKShapeFeatureExtractorFactory.h" + +#include "LTKShapeFeatureExtractor.h" + +#include "LTKShapeFeature.h" + +#include "LTKVersionCompatibilityCheck.h" + +#include "LTKInkFileWriter.h" +#include "LTKOSUtil.h" +#include "LTKOSUtilFactory.h" +#include "LTKClassifierDefaults.h" + + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : ActiveDTWShapeRecognizer +* DESCRIPTION : Default Constructor that initializes all data members +* ARGUMENTS : none +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ + +void ActiveDTWShapeRecognizer::assignDefaultValues() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::assignDefaultValues()" << endl; + + m_numShapes = 0; + m_activedtwCfgFilePath = ""; + m_activedtwMDTFilePath = ""; + m_ptrPreproc = NULL; + m_projectTypeDynamic=false; + m_prototypeSelection=NN_DEF_PROTOTYPESELECTION; + m_prototypeReductionFactor=NN_DEF_PROTOTYPEREDUCTIONFACTOR; + m_nearestNeighbors=NN_DEF_NEARESTNEIGHBORS; + m_dtwBanding=NN_DEF_BANDING; + m_dtwEuclideanFilter= ACTIVEDTW_DEF_DTWEUCLIDEANFILTER; + m_preProcSeqn=NN_DEF_PREPROC_SEQ; + m_ptrFeatureExtractor=NULL; + m_featureExtractorName=NN_DEF_FEATURE_EXTRACTOR; + m_numClusters=NN_NUM_CLUST_INITIAL; + m_MDTUpdateFreq=NN_DEF_MDT_UPDATE_FREQ; + m_prototypeSetModifyCount=0; + m_rejectThreshold=NN_DEF_REJECT_THRESHOLD; + m_adaptivekNN=false; + m_deleteLTKLipiPreProcessor=NULL; + m_minClusterSize = ADAPT_DEF_MIN_NUMBER_SAMPLES_PER_CLASS; + m_percentEigenEnergy = ACTIVEDTW_DEF_PERCENTEIGENENERGY; + m_eigenSpreadValue = ACTIVEDTW_DEF_EIGENSPREADVALUE; + m_useSingleton = ACTIVEDTW_DEF_USESINGLETON; + m_MDTFileOpenMode = NN_MDT_OPEN_MODE_ASCII; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::assignDefaultValues()" << endl; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : initialize +* DESCRIPTION : This method initializes the ActiveDTW shape recognizer +* ARGUMENTS : string Holds the Project Name +* string Holds the Profile Name +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no erros +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +ActiveDTWShapeRecognizer::ActiveDTWShapeRecognizer(const LTKControlInfo& controlInfo): +m_OSUtilPtr(LTKOSUtilFactory::getInstance()), +m_libHandler(NULL), +m_libHandlerFE(NULL) +{ + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::ActiveDTWShapeRecognizer()" << endl; + + try + { + LTKControlInfo tmpControlInfo=controlInfo; + + string strProjectName = ""; + string strProfileName = ""; + + + if( (tmpControlInfo.projectName).empty() ) + { + throw LTKException(EINVALID_PROJECT_NAME); + } + if( (tmpControlInfo.lipiRoot).empty() ) + { + throw LTKException(ELIPI_ROOT_PATH_NOT_SET); + } + + if( (tmpControlInfo.profileName).empty() ) + { + strProfileName = DEFAULT_PROFILE; + tmpControlInfo.profileName = strProfileName; + } + + if ( tmpControlInfo.toolkitVersion.empty() ) + { + throw LTKException(ENO_TOOLKIT_VERSION); + } + + assignDefaultValues(); + + m_lipiRootPath = tmpControlInfo.lipiRoot; + m_lipiLibPath = tmpControlInfo.lipiLib; + m_currentVersion = tmpControlInfo.toolkitVersion; + strProjectName = tmpControlInfo.projectName; + strProfileName = tmpControlInfo.profileName; + + + //Model Data file Header Information + m_headerInfo[PROJNAME] = strProjectName; + + //Holds the value of Number of Shapes in string format + string strNumShapes = ""; + + string strProfileDirectory = m_lipiRootPath + PROJECTS_PATH_STRING + + strProjectName + PROFILE_PATH_STRING; + + //Holds the path of the Preproc.dll + + //Holds the path of the Project.cfg + string projectCFGPath = strProfileDirectory + PROJECT_CFG_STRING; + + // Config file + + m_activedtwCfgFilePath = m_lipiRootPath + PROJECTS_PATH_STRING + + (tmpControlInfo.projectName) + PROFILE_PATH_STRING + + (tmpControlInfo.profileName) + SEPARATOR + + ACTIVEDTW + CONFIGFILEEXT; + + + //Set the path for activedtw.mdt + m_activedtwMDTFilePath = strProfileDirectory + strProfileName + SEPARATOR + ACTIVEDTW + DATFILEEXT; + + + //To find whether the project was dynamic or not andto read read number of shapes from project.cfg + int errorCode = m_shapeRecUtil.isProjectDynamic(projectCFGPath, + m_numShapes, strNumShapes, m_projectTypeDynamic); + + if( errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + "ActiveDTWShapeRecognizer::ActiveDTWShapeRecognizer()" <<endl; + throw LTKException(errorCode); + } + + //Set the NumShapes to the m_headerInfo + m_headerInfo[NUMSHAPES] = strNumShapes; + + //Currently preproc cfg also present in ActiveDTW + tmpControlInfo.cfgFileName = ACTIVEDTW; + errorCode = initializePreprocessor(tmpControlInfo,&m_ptrPreproc); + + + if( errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + "ActiveDTWShapeRecognizer::ActiveDTWShapeRecognizer()" <<endl; + throw LTKException(errorCode); + } + + //Reading ActiveDTW configuration file + errorCode = readClassifierConfig(); + + + if( errorCode != SUCCESS) + { + + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + "ActiveDTWShapeRecognizer::ActiveDTWShapeRecognizer()" <<endl; + throw LTKException(errorCode); + } + + //Writing Feature extractor name and version into the header + m_headerInfo[FE_NAME] = m_featureExtractorName; + //FE version + m_headerInfo[FE_VER] = SUPPORTED_MIN_VERSION; + + //Writing mdt file open mode to the mdt header + m_headerInfo[MDT_FOPEN_MODE] = m_MDTFileOpenMode; + + errorCode = initializeFeatureExtractorInstance(tmpControlInfo); + + + if( errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + "ActiveDTWShapeRecognizer::ActiveDTWShapeRecognizer()" <<endl; + throw LTKException(errorCode); + } + } + catch(LTKException e) + { + deletePreprocessor(); + m_prototypeShapes.clear(); + + m_cachedShapeFeature.clear(); + + //Unloading the feature Extractor instance + deleteFeatureExtractorInstance(); + + delete m_OSUtilPtr; + throw e; + } + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::ActiveDTWShapeRecognizer()" << endl; + +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : readClassifierConfig +* DESCRIPTION : Reads the ActiveDTW.cfg and initializes the data members of the class +* ARGUMENTS : none +* RETURNS : SUCCESS - If config file read successfully +* errorCode - If failure +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::readClassifierConfig() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::readClassifierConfig()" << endl; + string tempStringVar = ""; + int tempIntegerVar = 0; + float tempFloatVar = 0.0; + LTKConfigFileReader *shapeRecognizerProperties = NULL; + int errorCode = FAILURE; + + try + { + shapeRecognizerProperties = new LTKConfigFileReader(m_activedtwCfgFilePath); + } + catch(LTKException e) + { + LOG(LTKLogger::LTK_LOGLEVEL_INFO)<< "Info: " << + "Config file not found, using default values of the parameters" << + "ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + delete shapeRecognizerProperties; + + return FAILURE; + } + + //Pre-processing sequence + errorCode = shapeRecognizerProperties->getConfigValue(PREPROCSEQUENCE, m_preProcSeqn); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_INFO) << "Info: " << + "Using default value of prerocessing sequence: "<< m_preProcSeqn << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + m_preProcSeqn = NN_DEF_PREPROC_SEQ; + } + else + { + m_headerInfo[PREPROC_SEQ] = m_preProcSeqn; + } + + + if((errorCode = mapPreprocFunctions()) != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<" Error: " << errorCode << " " << + "ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + delete shapeRecognizerProperties; + + LTKReturnError(errorCode); + } + + //reading percent of eigen energy + tempStringVar = ""; + + errorCode = shapeRecognizerProperties->getConfigValue(RETAINPERCENTEIGENENERGY, + tempStringVar); + if(errorCode == SUCCESS ) + { + if (LTKStringUtil::isFloat(tempStringVar)) + { + tempFloatVar = LTKStringUtil::convertStringToFloat(tempStringVar); + + if(tempFloatVar >= MIN_PERCENT_EIGEN_ENERGY && tempFloatVar <= MAX_PERCENT_EIGEN_ENERGY) + { + m_percentEigenEnergy = tempFloatVar; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + RETAINPERCENTEIGENENERGY " = " << m_percentEigenEnergy<< endl; + + + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << + "Error: " << ECONFIG_FILE_RANGE << " " << RETAINPERCENTEIGENENERGY + " is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << + "Error: " << ECONFIG_FILE_RANGE << " " << RETAINPERCENTEIGENENERGY + " is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()" << endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << + "Using default value for " << RETAINPERCENTEIGENENERGY << ": " << + m_percentEigenEnergy << " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + } + + //reading method of prototype selection + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(PROTOTYPESELECTION, + tempStringVar); + + if (errorCode == SUCCESS) + { + if( (LTKSTRCMP(tempStringVar.c_str(), PROTOTYPE_SELECTION_CLUSTERING) == 0)) + { + m_prototypeSelection = tempStringVar; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << + PROTOTYPESELECTION << " = " << tempStringVar << + "ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << + "Error: " << ECONFIG_FILE_RANGE << " " << + PROTOTYPESELECTION << " : " << tempStringVar + << " method is not supported" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << PROTOTYPESELECTION << " : " << m_prototypeSelection << + " ActiveDTwShapeRecognizer::readClassifierConfig()"<<endl; + } + + //reading prototype reduction factor + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(PROTOREDFACTOR, + tempStringVar); + + string tempStringVar1 = ""; + int errorCode1 = shapeRecognizerProperties->getConfigValue(NUMCLUSTERS, + tempStringVar1); + + //prototype reduction factor + if(errorCode1 == SUCCESS && errorCode == SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << + "Error: " << ECONFIG_FILE_RANGE + << " Cannot use both config parameters " << + PROTOREDFACTOR << " and " << NUMCLUSTERS << " at the same time "<< + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + + if(tempStringVar != "") + { + if(LTKSTRCMP(tempStringVar.c_str(), PROTO_RED_FACTOR_AUTOMATIC)==0) + { + //DEFINE MACRO DEF_PROTO_RED_FACTOR + m_prototypeReductionFactor = -1; + } + else if(LTKSTRCMP(tempStringVar.c_str(), PROTO_RED_FACTOR_NONE)==0) + { + m_prototypeReductionFactor = 0; + } + else if(LTKSTRCMP(tempStringVar.c_str(), PROTO_RED_FACTOR_COMPLETE) == 0) + { + m_prototypeReductionFactor = 100; + } + else + { + if ( LTKStringUtil::isInteger(tempStringVar) ) + { + tempIntegerVar = atoi((tempStringVar).c_str()); + if(tempIntegerVar >= 0 && tempIntegerVar <=100) + { + m_prototypeReductionFactor = tempIntegerVar; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + << PROTOREDFACTOR << " is =" << tempStringVar<<endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << + "Error: " << ECONFIG_FILE_RANGE << + PROTOREDFACTOR << " is out of permitted range " << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << + "Error: " << ECONFIG_FILE_RANGE << + PROTOREDFACTOR << " is out of permitted range"<< + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + + } + } + else if(tempStringVar1 != "") + { + if(LTKSTRCMP(tempStringVar1.c_str(), PROTO_RED_FACTOR_AUTOMATIC) == 0) + { + m_prototypeReductionFactor = -1; + } + else + { + if ( LTKStringUtil::isInteger(tempStringVar1) ) + { + tempIntegerVar = atoi((tempStringVar1).c_str()); + if(tempIntegerVar > 0) + { + m_numClusters = tempIntegerVar; + + // m_numClusters is used in this case + m_prototypeReductionFactor = NN_NUM_CLUST_INITIAL; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + NUMCLUSTERS << " is = " << tempStringVar << endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << + NUMCLUSTERS << " is out of permitted range "<< + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + " Error: " << ECONFIG_FILE_RANGE << + NUMCLUSTERS << " is out of permitted range"<< + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Assuming default value of " NUMCLUSTERS << " : " << m_numClusters << endl; + } + + //reading adaptive kNN + tempStringVar = ""; + shapeRecognizerProperties->getConfigValue(ADAPTIVE_kNN, tempStringVar); + if(LTKSTRCMP(tempStringVar.c_str(), "true") ==0) + { + m_adaptivekNN = true; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + <<"Confidence computation method: " << ADAPTIVE_kNN << endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << ADAPTIVE_kNN << " : " << + m_adaptivekNN << endl; + } + + //reading nearest neighbors + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(NEARESTNEIGHBORS, + tempStringVar); + + if(errorCode == SUCCESS) + { + if ( LTKStringUtil::isInteger(tempStringVar) ) + { + tempIntegerVar = atoi((tempStringVar).c_str()); + + //Valid values of nearest neighbors: 1 or greater than MIN_NEARESTNEIGHBORS + if(tempIntegerVar > 0) + { + // If the value of NearestNeighbors = 1, ActiveDTW recognizer is used + if(tempIntegerVar == 1) + { + m_adaptivekNN = false; + } + + // If AdaptivekNN is set to false, simply assign the value to m_nearestNeighbors + // If AdaptivekNN is set, NearestNeighbors should be greater than than the + // minimum no.of nearest neighbors allowed (MIN_NEARESTNEIGHBORS defined as macro) + if(!m_adaptivekNN || (m_adaptivekNN && tempIntegerVar >= MIN_NEARESTNEIGHBORS)) + { + m_nearestNeighbors = tempIntegerVar; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + NEARESTNEIGHBORS << " = " <<m_nearestNeighbors<<endl; + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << NEARESTNEIGHBORS << + " is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << NEARESTNEIGHBORS << + " is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Debug: " << "Using default value for " << NEARESTNEIGHBORS << + " : " << m_nearestNeighbors << endl; + } + + //reading reject threshold + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(REJECT_THRESHOLD, + tempStringVar); + if(errorCode == SUCCESS) + { + if ( LTKStringUtil::isFloat(tempStringVar) ) + { + tempFloatVar = LTKStringUtil::convertStringToFloat(tempStringVar); + + if(tempFloatVar > 0 && tempFloatVar < 1) + { + m_rejectThreshold = tempFloatVar; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + REJECT_THRESHOLD << " = " <<tempStringVar <<endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << REJECT_THRESHOLD << + " should be in the range (0-1)" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << REJECT_THRESHOLD << + " should be in the range (0-1)" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << REJECT_THRESHOLD << + " : " << m_rejectThreshold << endl; + } + + //reading min cluster Size + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(MINCLUSTERSIZE, + tempStringVar); + + if(errorCode == SUCCESS) + { + if(LTKStringUtil::isInteger(tempStringVar)) + { + tempIntegerVar = atoi((tempStringVar).c_str()); + + if(tempIntegerVar > 1) + { + m_minClusterSize = tempIntegerVar; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + MINCLUSTERSIZE << " = " <<m_minClusterSize<<endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: "<< ECONFIG_FILE_RANGE << m_minClusterSize << + " is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: "<< ECONFIG_FILE_RANGE << MINCLUSTERSIZE << + " is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << MINCLUSTERSIZE << " : " << m_minClusterSize << endl; + } + + //reading eigen spread value + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(EIGENSPREADVALUE, + tempStringVar); + + + + if(errorCode == SUCCESS) + { + if(LTKStringUtil::isInteger(tempStringVar)) + { + tempIntegerVar = atoi((tempStringVar).c_str()); + + if(tempIntegerVar > 0) + { + m_eigenSpreadValue = tempIntegerVar; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + EIGENSPREADVALUE << " = " <<m_eigenSpreadValue<<endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: "<< ECONFIG_FILE_RANGE << EIGENSPREADVALUE << + " is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: "<< ECONFIG_FILE_RANGE << EIGENSPREADVALUE << + " is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << EIGENSPREADVALUE << " : " << m_eigenSpreadValue << endl; + } + + //reading use singleton + tempStringVar = ""; + shapeRecognizerProperties->getConfigValue(USESINGLETON, tempStringVar); + if(LTKSTRCMP(tempStringVar.c_str(), "false") ==0) + { + m_useSingleton = false; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + <<"Use Singleton: " << USESINGLETON << endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << USESINGLETON << " : " << + m_useSingleton << endl; + } + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(DTWBANDING, + tempStringVar); + if(errorCode == SUCCESS) + { + if ( LTKStringUtil::isFloat(tempStringVar) ) + { + tempFloatVar = LTKStringUtil::convertStringToFloat(tempStringVar); + + if(tempFloatVar > 0 && tempFloatVar <= 1) + { + m_dtwBanding = tempFloatVar; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + DTWBANDING << " = " <<m_dtwBanding<<endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: "<< ECONFIG_FILE_RANGE << DTWBANDING << + " is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: "<< ECONFIG_FILE_RANGE << + " DTWBANDING is out of permitted range" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << DTWBANDING << " : " << m_dtwBanding << endl; + } + + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(DTWEUCLIDEANFILTER, + tempStringVar); + if(errorCode == SUCCESS) + { + if(LTKSTRCMP(tempStringVar.c_str(), DTW_EU_FILTER_ALL) == 0) + { + m_dtwEuclideanFilter = EUCLIDEAN_FILTER_OFF; + } + + else + { + if ( LTKStringUtil::isInteger(tempStringVar) ) + { + tempIntegerVar = atoi((tempStringVar).c_str()); + + if(tempIntegerVar > 0 && tempIntegerVar <= 100) + { + if(tempIntegerVar == 100 ) + m_dtwEuclideanFilter = EUCLIDEAN_FILTER_OFF; + else + m_dtwEuclideanFilter = tempIntegerVar; + + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + DTWEUCLIDEANFILTER << " is = "<< + m_dtwEuclideanFilter<<endl; + } + else + { + + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << + DTWEUCLIDEANFILTER << " is out of permitted range " << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + delete shapeRecognizerProperties; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << DTWEUCLIDEANFILTER << + " is out of permitted range"<< + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << DTWEUCLIDEANFILTER << + " : " << m_dtwEuclideanFilter << endl; + } + + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(FEATUREEXTRACTOR, + tempStringVar); + if(errorCode == SUCCESS) + { + m_featureExtractorName = tempStringVar; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + FEATUREEXTRACTOR << " = "<<tempStringVar<<endl; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << FEATUREEXTRACTOR << " : " << + m_featureExtractorName << endl; + } + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(MDTFILEUPDATEFREQ, + tempStringVar); + + if(errorCode == SUCCESS) + { + if ( LTKStringUtil::isInteger(tempStringVar) ) + { + m_MDTUpdateFreq = atoi(tempStringVar.c_str()); + if(m_MDTUpdateFreq <= 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << MDTFILEUPDATEFREQ << + " should be zero or a positive integer" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << MDTFILEUPDATEFREQ << + " should be zero or a positive integer" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << MDT_UPDATE_FREQUENCY << + " : " << m_MDTUpdateFreq << endl; + } + + + + //reading mdt file open mode + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(MDT_FILE_OPEN_MODE, + tempStringVar); + + if(errorCode == SUCCESS) + { + if ( tempStringVar == NN_MDT_OPEN_MODE_ASCII || + tempStringVar == NN_MDT_OPEN_MODE_BINARY ) + { + m_MDTFileOpenMode = tempStringVar; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< + "Error: " << ECONFIG_FILE_RANGE << MDT_FILE_OPEN_MODE << + " should be ascii or binary" << + " ActiveDTWShapeRecognizer::readClassifierConfig()"<<endl; + + delete shapeRecognizerProperties; + + LTKReturnError(ECONFIG_FILE_RANGE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< + "Using default value for " << MDT_FILE_OPEN_MODE << + " : " << m_MDTFileOpenMode << endl; + } + + + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(SIZETHRESHOLD, + tempStringVar); + if(errorCode == SUCCESS) + { + m_headerInfo[DOT_SIZE_THRES] = tempStringVar; + } + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(ASPECTRATIOTHRESHOLD, + tempStringVar); + if(errorCode == SUCCESS) + { + m_headerInfo[ASP_RATIO_THRES] = tempStringVar; + } + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(DOTTHRESHOLD, + tempStringVar); + if(errorCode == SUCCESS) + { + m_headerInfo[DOT_THRES] = tempStringVar; + } + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(PRESERVERELATIVEYPOSITION, + tempStringVar); + + if(errorCode == SUCCESS) + { + m_headerInfo[PRESER_REL_Y_POS] = tempStringVar; + } + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(PRESERVEASPECTRATIO, + tempStringVar); + + if(errorCode == SUCCESS) + { + m_headerInfo[PRESER_ASP_RATIO] = tempStringVar; + } + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(SIZETHRESHOLD, + tempStringVar); + + if(errorCode == SUCCESS) + { + m_headerInfo[NORM_LN_WID_THRES] = tempStringVar; + } + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(RESAMPLINGMETHOD, + tempStringVar); + + if(errorCode == SUCCESS) + { + m_headerInfo[RESAMP_POINT_ALLOC] = tempStringVar; + } + + tempStringVar = ""; + errorCode = shapeRecognizerProperties->getConfigValue(SMOOTHFILTERLENGTH, + tempStringVar); + + if(errorCode == SUCCESS) + { + m_headerInfo[SMOOTH_WIND_SIZE] = tempStringVar; + } + + tempStringVar = ""; + LTKStringUtil::convertIntegerToString(m_ptrPreproc->getTraceDimension(), + tempStringVar); + + + m_headerInfo[TRACE_DIM] = tempStringVar; + + delete shapeRecognizerProperties; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::readClassifierConfig()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : mapPreprocFunctions +* DESCRIPTION : Maps the module name and its function names in the preprocessing +sequence. +* ARGUMENTS : none +* RETURNS : SUCCESS on successful, +* errorNumbers on Failure. +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::mapPreprocFunctions() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::mapPreprocFunctions()" << endl; + + stringStringMap preProcSequence; + + stringStringPair tmpPair; + + stringVector moduleFuncNames; + stringVector modFuncs; + stringVector funcNameTokens; + + string module = "", funName = "", sequence = ""; + string::size_type indx; + + LTKTraceGroup local_inTraceGroup; + + LTKStringUtil::tokenizeString(m_preProcSeqn, DELEMITER_SEQUENCE, funcNameTokens); + + int numFunctions = funcNameTokens.size(); + + if(numFunctions == 0) + { + LOG( LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< + "Wrong preprocessor sequence in cfg file : " + m_preProcSeqn << + " ActiveDTWShapeRecognizer::mapPreprocFunctions()"<<endl; + + LTKReturnError(EINVALID_PREPROC_SEQUENCE); + } + + for (indx = 0; indx < numFunctions ; indx++) + { + moduleFuncNames.push_back(funcNameTokens[indx]); + } + + int numModuleFunctions = moduleFuncNames.size(); + + for(indx=0; indx < numModuleFunctions ; indx++) + { + sequence = moduleFuncNames[indx]; + + LTKStringUtil::tokenizeString(sequence, DELEMITER_FUNC, modFuncs); + + if(modFuncs.size() >= 2) + { + module = modFuncs.at(0); + + funName = modFuncs.at(1); + + if(!module.compare("CommonPreProc")) + { + FN_PTR_PREPROCESSOR pPreprocFunc = NULL; + pPreprocFunc = m_ptrPreproc->getPreprocptr(funName); + if(pPreprocFunc!= NULL) + { + tmpPair.first = module; + tmpPair.second = funName; + m_preprocSequence.push_back(tmpPair); + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_PREPROC_SEQUENCE << " " << + "Wrong preprocessor sequence entry in cfg file : " <<funName<< + " ActiveDTWShapeRecognizer::mapPreprocFunctions()"<<endl; + LTKReturnError(EINVALID_PREPROC_SEQUENCE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_PREPROC_SEQUENCE << " " << + "Wrong preprocessor sequence entry in cfg file : " << module<< + " ActiveDTWShapeRecognizer::mapPreprocFunctions()"<<endl; + LTKReturnError(EINVALID_PREPROC_SEQUENCE); + } + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_PREPROC_SEQUENCE << " " << + "Wrong preprocessor sequence entry in cfg file : "<<module<< + " ActiveDTWShapeRecognizer::mapPreprocFunctions()"<<endl; + LTKReturnError(EINVALID_PREPROC_SEQUENCE); + } + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::mapPreprocFunctions()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : ~ActiveDTWShapeRecognizer +* DESCRIPTION : destructor +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +ActiveDTWShapeRecognizer::~ActiveDTWShapeRecognizer() +{ + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::~ActiveDTWShapeRecognizer()" << endl; + + int returnStatus = SUCCESS; + + if(LTKAdapt::getInstance(this)) + deleteAdaptInstance(); + + if(m_prototypeSetModifyCount >0) + { + m_prototypeSetModifyCount = m_MDTUpdateFreq-1; + + returnStatus = writePrototypeShapesToMDTFile(); + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " << + " ActiveDTWShapeRecognizer::~ActiveDTWShapeRecognizer()" << endl; + throw LTKException(returnStatus); + } + } + + m_neighborInfoVec.clear(); + + returnStatus = deletePreprocessor(); + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " << + " ActiveDTWShapeRecognizer::~ActiveDTWShapeRecognizer()" << endl; + throw LTKException(returnStatus); + } + + m_prototypeShapes.clear(); + m_cachedShapeFeature.clear(); + + //Unloading the feature Extractor instance + returnStatus = deleteFeatureExtractorInstance(); + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " << + " ActiveDTWShapeRecognizer::~ActiveDTWShapeRecognizer()" << endl; + throw LTKException(returnStatus); + } + + delete m_OSUtilPtr; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::~ActiveDTWShapeRecognizer()" << endl; +} + + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : train +* DESCRIPTION : +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::train(const string& trainingInputFilePath, + const string& mdtHeaderFilePath, + const string &comment,const string &dataset, + const string &trainFileType) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::train()" << endl; + + + + int returnStatus = SUCCESS; + + + if(comment.empty() != true) + { + m_headerInfo[COMMENT] = comment; + } + + if(dataset.empty() != true) + { + m_headerInfo[DATASET] = dataset; + } + + + if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_CLUSTERING) == 0) + { + returnStatus = trainClustering(trainingInputFilePath, + mdtHeaderFilePath, + trainFileType); + + if(returnStatus != SUCCESS) + { + LTKReturnError(returnStatus); + } + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::train()" << endl; + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : trainClustering +* DESCRIPTION : This function is the train method using Clustering prototype +* selection technique. +* ARGUMENTS : +* RETURNS : SUCCESS : if training done successfully +* errorCode : if traininhas some errors +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::trainClustering(const string& trainingInputFilePath, + const string &mdtHeaderFilePath, + const string& inFileType) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::trainClustering()" << endl; + + + //Time at the beginning of Train Clustering + m_OSUtilPtr->recordStartTime(); + + int returnStatus = SUCCESS; + + if(LTKSTRCMP(inFileType.c_str(), INK_FILE) == 0) + { + //If the Input file is UNIPEN Ink file + returnStatus = trainFromListFile(trainingInputFilePath); + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Error: " << + getErrorMessage(returnStatus) << + " ActiveDTWShapeRecognizer::trainClustering()" << endl; + LTKReturnError(returnStatus); + } + } + + + //Updating the Header Information + updateHeaderWithAlgoInfo(); + + //Adding header information and checksum generation + LTKCheckSumGenerate cheSumGen; + + returnStatus = cheSumGen.addHeaderInfo(mdtHeaderFilePath, + m_activedtwMDTFilePath, + m_headerInfo); + + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Error: " << + getErrorMessage(returnStatus) << + " ActiveDTWShapeRecognizer::trainClustering()" << endl; + + LTKReturnError(returnStatus); + } + + //Time at the end of Train Clustering + m_OSUtilPtr->recordEndTime(); + + string timeTaken = ""; + m_OSUtilPtr->diffTime(timeTaken); + + cout << "Time Taken = " << timeTaken << endl; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::trainClustering()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : appendShapeModelToMDTFile +* DESCRIPTION : This method is called after performing clustering on each class +It writes the class information to the activedtw.mdt file +* ARGUMENTS : INPUT +shapeModel struct ActiveDTWShapeModel (class training data) +mdtFileHandle ofstream (mdt File handle) + + * RETURNS : integer Holds error value if occurs + * Holds SUCCESS if no erros +*************************************************************************************/ +int ActiveDTWShapeRecognizer::appendShapeModelToMDTFile(const ActiveDTWShapeModel& shapeModel,ofstream& mdtFileHandle) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::appendShapeModelToMDTFile()" << endl; + + + //used to temporarily store the size of a vector + int vecSize; + if(!mdtFileHandle) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_FILE_HANDLE << " " << + "Invalid file handle for MDT file"<< + " ActiveDTWShapeRecognizer::appendShapeModelToMDTFile()" << endl; + LTKReturnError(EINVALID_FILE_HANDLE); + } + + string strFeature; + + vector<ActiveDTWClusterModel> clusterModelVector = shapeModel.getClusterModelVector(); + vector<ActiveDTWClusterModel>::iterator iStart = clusterModelVector.begin(); + vector<ActiveDTWClusterModel>::iterator iEnd = clusterModelVector.end(); + double2DVector eigenVectors; + doubleVector eigenValues; + doubleVector clusterMean; + shapeMatrix singletonVector = shapeModel.getSingletonVector(); + ActiveDTWClusterModel clusterModel; + + /**APPENDING CLASS INFORMATION**/ + //APPENDING CLASSID NUMCLUSTERS NUMSINGLETONS + if(m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII) + { + mdtFileHandle<<shapeModel.getShapeId()<<" "<<clusterModelVector.size()<<" "<<singletonVector.size()<<endl; + } + else + { + int clusterSize = clusterModelVector.size(); + int singletonSize = singletonVector.size(); + int shapeId = shapeModel.getShapeId(); + int numFeatures; + int featureDimension; + int clusterMeanDimension; + mdtFileHandle.write((char*) &shapeId,sizeof(int)); + mdtFileHandle.write((char*) &clusterSize,sizeof(int)); + mdtFileHandle.write((char*) &singletonSize,sizeof(int)); + + if(clusterSize != 0) + { + clusterMean = clusterModelVector[0].getClusterMean(); + clusterMeanDimension = clusterMean.size(); + mdtFileHandle.write((char*) &clusterMeanDimension,sizeof(int)); + } + else + { + clusterMeanDimension = 0; + mdtFileHandle.write((char*) &clusterMeanDimension,sizeof(int)); + } + + //writing number of features and feature dimension + if(singletonSize != 0) + { + numFeatures = singletonVector[0].size(); + mdtFileHandle.write((char*) &numFeatures,sizeof(int)); + featureDimension = singletonVector[0][0]->getFeatureDimension(); + mdtFileHandle.write((char*) &featureDimension,sizeof(int)); + } + else + { + numFeatures = 0; + mdtFileHandle.write((char*) &numFeatures,sizeof(int)); + featureDimension = 0; + mdtFileHandle.write((char*) &featureDimension,sizeof(int)); + } + + } + + /**APPENDING CLUSTER DATA**/ + //iterating through the cluster models + + for(;iStart != iEnd; ++iStart) + { + + clusterModel = *iStart; + + + //appending number of clusters in each sample + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle<<clusterModel.getNumSamples()<<" "; + } + else + { + int numSamples = clusterModel.getNumSamples(); + mdtFileHandle.write((char*) &numSamples,sizeof(int)); + } + + + eigenValues = clusterModel.getEigenValues(); + vecSize = eigenValues.size(); + + /**WRITING EIGEN VALUES**/ + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + for(int i = 0; i < vecSize; i++) + { + mdtFileHandle<<eigenValues[i]; + if(i != (vecSize - 1)) + { + mdtFileHandle<<","; + } + } + mdtFileHandle<<FEATURE_EXTRACTOR_DELIMITER; + } + else + { + //writing number of eigen values + mdtFileHandle.write((char*) &vecSize,sizeof(int)); + + //writing eigenValues + for(int i = 0; i < vecSize; i++) + { + mdtFileHandle.write((char*) &(eigenValues[i]),sizeof(double)); + } + } + + /**WRITING EIGEN VECTORS**/ + + eigenVectors = clusterModel.getEigenVectors(); + vecSize = eigenVectors[0].size(); + int eigVecSize = eigenVectors.size(); + + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + for(int i = 0; i < eigVecSize; i++) + { + for(int j = 0; j < vecSize; j++) + { + mdtFileHandle<<eigenVectors[i][j]; + if(j != (vecSize - 1)) + { + mdtFileHandle<<","; + } + } + mdtFileHandle<<FEATURE_EXTRACTOR_DELIMITER; + } + } + else + { + for(int i = 0; i < eigVecSize; i++) + { + for(int j = 0; j < vecSize; j++) + { + mdtFileHandle.write((char*) &(eigenVectors[i][j]),sizeof(double)); + } + } + } + + /**APPENDING CLUSTER MEAN**/ + + clusterMean = clusterModel.getClusterMean(); + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + for(int i = 0; i < vecSize; i++) + { + mdtFileHandle<<clusterMean[i]; + if(i != (vecSize - 1)) + { + mdtFileHandle<<","; + } + + } + mdtFileHandle<<FEATURE_EXTRACTOR_DELIMITER<<endl; + } + else + { + for(int i = 0; i < vecSize; i++) + { + mdtFileHandle.write((char*) &(clusterMean[i]),sizeof(double)); + } + } + + eigenVectors.clear(); + eigenValues.clear(); + clusterMean.clear(); + + } + clusterModelVector.clear(); + + /**WRITING SINGLETON VECTORS**/ + shapeMatrix::iterator iterStart = singletonVector.begin(); + shapeMatrix::iterator iterEnd = singletonVector.end(); + shapeFeature singleton; + + for(; iterStart != iterEnd; ++iterStart ) + { + + singleton = *iterStart; + + vecSize = singleton.size(); + + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + vector<LTKShapeFeaturePtr>::const_iterator shapeFeatureIter = singleton.begin(); + vector<LTKShapeFeaturePtr>::const_iterator shapeFeatureIterEnd = singleton.end(); + + for(; shapeFeatureIter != shapeFeatureIterEnd; ++shapeFeatureIter) + { + (*shapeFeatureIter)->toString(strFeature); + mdtFileHandle << strFeature << FEATURE_EXTRACTOR_DELIMITER; + } + mdtFileHandle<<endl; + + } + else + { + + //converting the singleton vector to float and writing it + floatVector floatFeatureVector; + int errorCode = m_shapeRecUtil.shapeFeatureVectorToFloatVector(singleton, + floatFeatureVector); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<errorCode<< + " ActiveDTWShapeRecognizer::appendShapeModelToMDTFile" << endl; + LTKReturnError(errorCode); + } + + vecSize = floatFeatureVector.size(); + + + for (int i=0; i< vecSize; i++) + { + float floatValue = floatFeatureVector[i]; + mdtFileHandle.write((char *)(&floatValue), sizeof(float)); + } + } + } + + singletonVector.clear(); + + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::appendShapeModelToMDTFile()" << endl; + + return SUCCESS; + +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : preprocess +* DESCRIPTION : calls the required pre-processing functions from the LTKPreprocessor library +* ARGUMENTS : inTraceGroup - reference to the input trace group +* outPreprocessedTraceGroup - pre-processed inTraceGroup +* RETURNS : SUCCESS on successful pre-processing operation +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::preprocess (const LTKTraceGroup& inTraceGroup, + LTKTraceGroup& outPreprocessedTraceGroup) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::preprocess()" << endl; + + int indx = 0; + int errorCode = -1; + + string module = ""; + string funName = "" ; + + LTKTraceGroup local_inTraceGroup; + + local_inTraceGroup = inTraceGroup; + + if(m_preprocSequence.size() != 0) + { + while(indx < m_preprocSequence.size()) + { + module = m_preprocSequence.at(indx).first; + funName = m_preprocSequence.at(indx).second; + + FN_PTR_PREPROCESSOR pPreprocFunc = NULL; + pPreprocFunc = m_ptrPreproc->getPreprocptr(funName); + + if(pPreprocFunc!= NULL) + { + outPreprocessedTraceGroup.emptyAllTraces(); + + + if((errorCode = (m_ptrPreproc->*(pPreprocFunc)) + (local_inTraceGroup,outPreprocessedTraceGroup)) != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::preprocess()" << endl; + LTKReturnError(errorCode); + } + local_inTraceGroup = outPreprocessedTraceGroup; + } + indx++; + } + } + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Exiting ActiveDTWShapeRecognizer::preprocess()"<<endl; + return SUCCESS; +} + + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : computerDTWDistanceClusteringWrapper +* DESCRIPTION : Wrapper function to the function whichcomputes DTW distance between +two characters +* ARGUMENTS : train character, test character +* RETURNS : DTWDistance +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::computeDTWDistance( + const LTKShapeSample& inFirstShapeSampleFeatures, + const LTKShapeSample& inSecondShapeSampleFeatures, + float& outDTWDistance) + +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::computeDTWDistance()" << endl; + + const vector<LTKShapeFeaturePtr>& firstFeatureVec = inFirstShapeSampleFeatures.getFeatureVector(); + const vector<LTKShapeFeaturePtr>& secondFeatureVec = inSecondShapeSampleFeatures.getFeatureVector(); + + int errorCode = m_dtwObj.computeDTW(firstFeatureVec, secondFeatureVec, getDistance,outDTWDistance, + m_dtwBanding, FLT_MAX, FLT_MAX); + + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "DTWDistance: " << + outDTWDistance << endl; + + if (errorCode != SUCCESS ) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Error: "<< + getErrorMessage(errorCode) << + " ActiveDTWShapeRecognizer::computeDTWDistance()" << endl; + LTKReturnError(errorCode); + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::computeDTWDistance()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : computeDTWDistance +* DESCRIPTION : This method computes the dtw distance between two shape features +* ARGUMENTS : INPUT +inFirstFeatureVector vector<LTKShapeFeaturePtr> +inSecondFeatureVector vector<LTKShapeFeaturePtr> +: OUTPUT +outDTWDistance float +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ +int ActiveDTWShapeRecognizer::computeDTWDistance( + const vector<LTKShapeFeaturePtr>& inFirstFeatureVector, + const vector<LTKShapeFeaturePtr>& inSecondFeatureVector, + float& outDTWDistance) + +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::computeDTWDistance()" << endl; + + int errorCode = m_dtwObj.computeDTW(inFirstFeatureVector, inSecondFeatureVector, getDistance,outDTWDistance, + m_dtwBanding, FLT_MAX, FLT_MAX); + + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "DTWDistance: " << + outDTWDistance << endl; + + if (errorCode != SUCCESS ) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Error: "<< + getErrorMessage(errorCode) << + " ActiveDTWShapeRecognizer::computeDTWDistance()" << endl; + LTKReturnError(errorCode); + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::computeDTWDistance()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : computeEuclideanDistance +* DESCRIPTION : This computes the euclideanDistance between two shapeFeatures +* ARGUMENTS : INPUT +inFirstFeature shapeFeature +inSecondFeature shapeFeature +:OUTPUT +outEuclideanDistance floats +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ +int ActiveDTWShapeRecognizer::computeEuclideanDistance( + const shapeFeature& inFirstFeature, + const shapeFeature& inSecondFeature, + float& outEuclideanDistance) +{ + int firstFeatureVectorSize = inFirstFeature.size(); + int secondFeatureVectorSize = inSecondFeature.size(); + + if(firstFeatureVectorSize != secondFeatureVectorSize) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EUNEQUAL_LENGTH_VECTORS << " " << + getErrorMessage(EUNEQUAL_LENGTH_VECTORS) << + " ActiveDTWShapeRecognizer::computeEuclideanDistance()" << endl; + + LTKReturnError(EUNEQUAL_LENGTH_VECTORS); + } + + for(int i = 0; i < firstFeatureVectorSize; ++i) + { + float tempDistance = 0.0; + getDistance(inFirstFeature[i], + inSecondFeature[i], + tempDistance); + + outEuclideanDistance += tempDistance; + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::computeEuclideanDistance()" << endl; + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : loadModelData +* DESCRIPTION : loads the reference model file into memory +* ARGUMENTS : +* RETURNS : SUCCESS on successful loading of the reference model file +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::loadModelData() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::loadModelData()" << endl; + + int errorCode = -1; + + int numofShapes = 0; + + // variable for shape Id + int classId = -1; + int i = 0; + + //Algorithm version + string algoVersionReadFromMDT = ""; + + stringStringMap headerSequence; + LTKCheckSumGenerate cheSumGen; + + if(errorCode = cheSumGen.readMDTHeader(m_activedtwMDTFilePath,headerSequence)) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(errorCode); + } + + // printing the headerseqn + stringStringMap::const_iterator iter = headerSequence.begin(); + stringStringMap::const_iterator endIter = headerSequence.end(); + + for(; iter != endIter; iter++) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Debug: header seqn"<< + iter->first << " : " << + iter->second << endl; + } + + string featureExtractor = headerSequence[FE_NAME]; + + if(LTKSTRCMP(m_featureExtractorName.c_str(), featureExtractor.c_str()) != 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of FeatureExtractor parameter in config file ("<< + m_featureExtractorName<<") does not match with the value in MDT file ("<< + featureExtractor<<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + + string feVersion = headerSequence[FE_VER]; + + // comparing the mdt open mode read from cfg file with value in the mdt header + string mdtOpenMode = headerSequence[MDT_FOPEN_MODE]; + + if (LTKSTRCMP(m_MDTFileOpenMode.c_str(), mdtOpenMode.c_str()) != 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of ActiveDTWMDTFileOpenMode parameter in config file ("<< + m_MDTFileOpenMode <<") does not match with the value in MDT file ("<< + mdtOpenMode<<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + + // validating preproc parameters + int iErrorCode = validatePreprocParameters(headerSequence); + if (iErrorCode != SUCCESS ) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Values of ActiveMDTMDTFileOpenMode parameter in config file does not match with " + <<"the values in MDT file " << "ActiveDTWShapeRecognizer::loadModelData()" << endl; + + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + + // Version comparison START + algoVersionReadFromMDT = headerSequence[RECVERSION].c_str(); + + LTKVersionCompatibilityCheck verTempObj; + string supportedMinVersion(SUPPORTED_MIN_VERSION); + string currentVersionStr(m_currentVersion); + + bool compatibilityResults = verTempObj.checkCompatibility(supportedMinVersion, + currentVersionStr, + algoVersionReadFromMDT); + + if(compatibilityResults == false) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINCOMPATIBLE_VERSION << " " << + " Incompatible version"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(EINCOMPATIBLE_VERSION); + } + + // Version comparison END + + //Input Stream for Model Data file + ifstream mdtFileHandle; + + if (m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle.open(m_activedtwMDTFilePath.c_str(), ios::in); + } + else + { + mdtFileHandle.open(m_activedtwMDTFilePath.c_str(), ios::in | ios::binary); + } + + //If error while opening, return an error + if(!mdtFileHandle) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EMODEL_DATA_FILE_OPEN << " " << + " Unable to open model data file : " <<m_activedtwMDTFilePath<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(EMODEL_DATA_FILE_OPEN); + } + + mdtFileHandle.seekg(atoi(headerSequence[HEADERLEN].c_str()),ios::beg); + + //Read the number of shapes + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle >> numofShapes; + } + else + { + mdtFileHandle.read((char*) &numofShapes, + atoi(headerSequence[SIZEOFSHORTINT].c_str())); + } + + if(!m_projectTypeDynamic && m_numShapes != numofShapes) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< ECONFIG_MDT_MISMATCH << " " << + " Value of NumShapes parameter in config file ("<<m_numShapes<< + ") does not match with the value in MDT file ("<<numofShapes<<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + + if(m_projectTypeDynamic) + { + m_numShapes = numofShapes; + } + + stringVector tokens; + + stringVector subTokens; + + string strFeatureVector = ""; + + //number of samples in each cluster + int numSamples; + + //keeps count of number of clusters + // and singletons while reading from + //mdt file + int tempCount; + + //number of clusters in a class + int numClusters; + + //number of singletons in a class + int numSingletons; + + //dimension of cluster mean + int clusterMeanDimension; + + //number of features in a feature vector + int numFeatures; + + //dimension of the featureVector + int featureDimension; + + + shapeMatrix singletonVector; + shapeFeature singleton; + doubleVector eigenValues; + double2DVector eigenVectors; + doubleVector clusterMean; + ActiveDTWClusterModel clusterModel; + ActiveDTWShapeModel shapeModel; + vector<ActiveDTWClusterModel> clusterModelVector; + doubleVector tempVector; + + int floatSize = atoi(headerSequence[SIZEOFFLOAT].c_str()); + + int intSize = atoi(headerSequence[SIZEOFINT].c_str()); + + int doubleSize = sizeof(double); + + //Each pass over the loop reads data corresponding to one class + //includes reading all the cluster data + //all singleton vectors + + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle >> classId; + } + else + { + mdtFileHandle.read((char*) &classId, intSize); + + } + + while(!mdtFileHandle.eof()) + { + + /**READING CLASS INFORMATION**/ + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle >> numClusters; + + mdtFileHandle >> numSingletons; + } + else + { + //reading number of clusters, singletons, clusterMeanDimension, + //number of Features, and featureDimension + mdtFileHandle.read((char*) &numClusters,intSize); + + mdtFileHandle.read((char*) &numSingletons,intSize); + + mdtFileHandle.read((char*) &clusterMeanDimension,intSize); + + mdtFileHandle.read((char*) &numFeatures,intSize); + + + mdtFileHandle.read((char*) &featureDimension,intSize); + + + + } + + tempCount = 0; + + /**READING CLUSTER DATA**/ + + for(int clustersCount = 0 ; clustersCount < numClusters; clustersCount++) + { + //reading number of samples in a cluster + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle >> numSamples; + } + else + { + mdtFileHandle.read((char*) &numSamples,intSize); + } + + iErrorCode = clusterModel.setNumSamples(numSamples); + if(iErrorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< iErrorCode << " " << + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(iErrorCode); + } + + + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + strFeatureVector = ""; + mdtFileHandle >> strFeatureVector; + + LTKStringUtil::tokenizeString(strFeatureVector,FEATURE_EXTRACTOR_DELIMITER,tokens); + + + //first token contains eigen values + LTKStringUtil::tokenizeString(tokens[0],",",subTokens); + + //extracting eigen values + int i = 0; + for(i = 0; i < subTokens.size(); i++) + { + + eigenValues.push_back(LTKStringUtil::convertStringToFloat(subTokens[i])); + + } + + clusterModel.setEigenValues(eigenValues); + + subTokens.clear(); + + //extracting eigen vectors + + for( i = 1; i < (eigenValues.size() + 1); i++) + { + LTKStringUtil::tokenizeString(tokens[i],",",subTokens); + + for(int j = 0; j < subTokens.size(); j++) + { + tempVector.push_back(LTKStringUtil::convertStringToFloat(subTokens[j])); + } + + + eigenVectors.push_back(tempVector); + tempVector.clear(); + subTokens.clear(); + } + + clusterModel.setEigenVectors(eigenVectors); + + + //extracting cluster mean + + LTKStringUtil::tokenizeString(tokens[(eigenValues.size() + 1)],",",subTokens); + + for( i = 0; i < subTokens.size(); i++) + { + + clusterMean.push_back(LTKStringUtil::convertStringToFloat(subTokens[i])); + } + + clusterModel.setClusterMean(clusterMean); + + subTokens.clear(); + + clusterModelVector.push_back(clusterModel); + } + else + { + //reading number of eigenValues + int numEigenValues; + mdtFileHandle.read((char*) &numEigenValues,intSize); + + //reading eigen values + int i = 0; + for(i = 0; i < numEigenValues; i++) + { + double eigenValue; + mdtFileHandle.read((char*) &eigenValue,doubleSize ); + + eigenValues.push_back(eigenValue); + + if ( mdtFileHandle.fail() ) + { + break; + } + } + + clusterModel.setEigenValues(eigenValues); + + + //reading eigenVectors + for( i = 0; i < numEigenValues; i++) + { + for(int j = 0; j < clusterMeanDimension; j++) + { + double eigenVectorValue; + mdtFileHandle.read((char*) &eigenVectorValue,doubleSize); + tempVector.push_back(eigenVectorValue); + + if ( mdtFileHandle.fail() ) + { + break; + } + } + + eigenVectors.push_back(tempVector); + tempVector.clear(); + } + + clusterModel.setEigenVectors(eigenVectors); + + + //reading cluster mean + for( i = 0; i < clusterMeanDimension; i++) + { + double clusterMeanValue; + mdtFileHandle.read((char*) &clusterMeanValue,doubleSize); + + clusterMean.push_back(clusterMeanValue); + + if ( mdtFileHandle.fail() ) + { + break; + } + } + + clusterModel.setClusterMean(clusterMean); + + + clusterModelVector.push_back(clusterModel); + } + + //clearing vectors + + eigenValues.clear(); + + eigenVectors.clear(); + + clusterMean.clear(); + + tempVector.clear(); + tokens.clear(); + + } + + /**READING SINGLETON VECTORS**/ + tempCount = 0; + + for(int singletonCount = 0; singletonCount < numSingletons; singletonCount++) + { + LTKShapeFeaturePtr feature; + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + strFeatureVector = ""; + mdtFileHandle >> strFeatureVector; + + //parsing the singleton vector + LTKStringUtil::tokenizeString(strFeatureVector, FEATURE_EXTRACTOR_DELIMITER, tokens); + + for(int i = 0; i < tokens.size(); ++i) + { + feature = m_ptrFeatureExtractor->getShapeFeatureInstance(); + + if (feature->initialize(tokens[i]) != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_INPUT_FORMAT << " " << + "Number of features extracted from a trace is not correct"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + + LTKReturnError(EINVALID_INPUT_FORMAT); + } + + singleton.push_back(feature); + } + + singletonVector.push_back(singleton); + + singleton.clear(); + tokens.clear(); + } + else + { + int featureIndex = 0; + + for ( ; featureIndex < numFeatures ; featureIndex++) + { + floatVector floatFeatureVector; + int featureValueIndex = 0; + + feature = m_ptrFeatureExtractor->getShapeFeatureInstance(); + + for(; featureValueIndex < featureDimension ; featureValueIndex++) + { + float featureValue = 0.0f; + + mdtFileHandle.read((char*) &featureValue, floatSize); + + floatFeatureVector.push_back(featureValue); + + if ( mdtFileHandle.fail() ) + { + break; + } + } + + if (feature->initialize(floatFeatureVector) != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< + EINVALID_INPUT_FORMAT << " " << + "Number of features extracted from a trace is not correct"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + + LTKReturnError(EINVALID_INPUT_FORMAT); + } + + + singleton.push_back(feature); + + } + + singletonVector.push_back(singleton); + + singleton.clear(); + } + } + + /**CONSTRUCTING SHAPE MODEL**/ + + + iErrorCode = shapeModel.setShapeId(classId); + if(iErrorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< iErrorCode << " "<< endl; + LTKReturnError(iErrorCode); + } + + shapeModel.setClusterModelVector(clusterModelVector); + + shapeModel.setSingletonVector(singletonVector); + + + + + /**APPENDING THE SHAPE MODEL TO PROTOTYPE VECTOR**/ + + m_prototypeShapes.push_back(shapeModel); + + + m_shapeIDNumPrototypesMap[classId] = clusterModelVector.size(); + + + if(m_useSingleton == true || clusterModelVector.size() == 0) + m_shapeIDNumPrototypesMap[classId] += singletonVector.size(); + + + + + + clusterModelVector.clear(); + + singletonVector.clear(); + + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle >> classId; + } + else + { + mdtFileHandle.read((char*) &classId, intSize); + + if ( mdtFileHandle.fail() ) + { + break; + } + } + + + } + + + + mdtFileHandle.close(); + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::loadModelData()" << endl; + + return SUCCESS; +} + + + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : recognize +* DESCRIsPTION : recognizes the incoming tracegroup +* ARGUMENTS : inTraceGroup - trace group to be recognized +* screenContext - screen context +* subSetOfClasses - subset of classes whose samples will be compared with traceGroup +* confThreshold - classes with confidence below this threshold are not returned, valid range of confThreshold: (0,1) +* numChoices - maximum number of choices to be returned +* outResultVector - result of recognition +* RETURNS : SUCCESS on successful running of the code +* NOTES : +* CHANGE HISTROY +* Author : Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::recognize(const LTKTraceGroup& traceGroup, + const LTKScreenContext& screenContext, + const vector<int>& subSetOfClasses, + float confThreshold, + int numChoices, + vector<LTKShapeRecoResult>& outResultVector) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::recognize()" << endl; + + + //Check for empty traces in traceGroup + + if(traceGroup.containsAnyEmptyTrace()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<EEMPTY_TRACE << " " << + " Input trace is empty"<< + " ActiveDTWShapeRecognizer::recognize()" << endl; + LTKReturnError(EEMPTY_TRACE); + } + + + //Contains TraceGroup after Preprocessing is done + LTKTraceGroup preprocessedTraceGroup; + + + //Preprocess the traceGroup + int errorCode = preprocess(traceGroup, preprocessedTraceGroup); + if( errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + getErrorMessage(errorCode)<< + " ActiveDTWShapeRecognizer::recognize()" << endl; + LTKReturnError(errorCode); + } + + //Extract the shapeSample from preprocessedTraceGroup + if(!m_ptrFeatureExtractor) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< ENULL_POINTER << " " << + " m_ptrFeatureExtractor is NULL"<< + " ActiveDTWShapeRecognizer::recognize()" << endl; + LTKReturnError(ENULL_POINTER); + } + + vector<LTKShapeFeaturePtr> shapeFeatureVec; + errorCode = m_ptrFeatureExtractor->extractFeatures(preprocessedTraceGroup, + shapeFeatureVec); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + // call recognize with featureVector + + if(recognize( shapeFeatureVec, subSetOfClasses, confThreshold, + numChoices, outResultVector) != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + getErrorMessage(errorCode)<< + " ActiveDTWShapeRecognizer::recognize()" << endl; + LTKReturnError(errorCode); + + } + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::recognize()" << endl; + + return SUCCESS; + +} +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : recognize +* DESCRIsPTION : recognizes the incoming tracegroup +* ARGUMENTS : shapeFeatureVec - feature vector to be recognized +* screenContext - screen context +* subSetOfClasses - subset of classes whose samples will be compared with traceGroup +* confThreshold - classes with confidence below this threshold are not returned, valid range of confThreshold: (0,1) +* numChoices - maximum number of choices to be returned +* outResultVector - result of recognition +* RETURNS : SUCCESS on successful running of the code +* NOTES : +* CHANGE HISTROY +* Author : Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::recognize(const vector<LTKShapeFeaturePtr>& shapeFeatureVec, + const vector<int>& inSubSetOfClasses, + float confThreshold, + int numChoices, + vector<LTKShapeRecoResult>& outResultVector) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::recognize()" << endl; + + m_cachedShapeFeature = shapeFeatureVec; + + //Creating a local copy of input inSubSetOfClasses, as it is const, STL's unique function modifies it + vector<int> subSetOfClasses = inSubSetOfClasses; + + int numPrototypeShapes = m_prototypeShapes.size(); + + /*********Validation for m_prototypeShapes ***************************/ + if ( numPrototypeShapes == 0 ) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EPROTOTYPE_SET_EMPTY << " " << + " getErrorMessage(EPROTOTYPE_SET_EMPTY) "<< + " ActiveDTWShapeRecognizer::recognize()" << endl; + LTKReturnError(EPROTOTYPE_SET_EMPTY); + } + + /******************************************************************/ + /*******************VALIDATING INPUT ARGUMENTS*********************/ + /******************************************************************/ + + // Validating numChoices: valid values: {-1, (0,m_numShapes]} + if(numChoices <= 0 && numChoices != NUM_CHOICES_FILTER_OFF) + { + LOG(LTKLogger::LTK_LOGLEVEL_INFO)<< + "numChoices ("<<numChoices<<")<=0, setting it to off (-1)"<<endl; + numChoices = -1; + } + + if(!m_projectTypeDynamic && numChoices > m_numShapes) + { + LOG(LTKLogger::LTK_LOGLEVEL_INFO)<< + "numChoices ("<<numChoices<<") > numShapes ("<< + m_numShapes<<"), using numShapes "<<m_numShapes<<" instead"<<endl; + numChoices = m_numShapes; + } + + + //Validating confThreshold: valid values: [0,1] + if(confThreshold > 1 || confThreshold < 0) + { + + LOG(LTKLogger::LTK_LOGLEVEL_INFO)<< + "Invalid value of confThreshold, valid values are: [0,1]"<<endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + + // Clearing cached Variables + m_vecRecoResult.clear(); + m_neighborInfoVec.clear(); + + //Temporary variable to be used to populate distIndexPairVector + struct NeighborInfo tempPair; + + struct NeighborInfo tempDist; + + int i = 0; + int j = 0; + + //Variable to store the DTW distance. + float dtwDistance = 0.0f; + + //Variable to store the Euclidean distance. + float euclideanDistance = 0.0f; + + + /***************End of declarations and initializations of variables**************/ + + + + /**CONVERTING THE FEATURE VECTOR TO DOUBLE***/ + + doubleVector featureVector; + floatVector floatFeatureVector; + int errorCode = m_shapeRecUtil.shapeFeatureVectorToFloatVector(shapeFeatureVec,floatFeatureVector); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + int floatFeatureVectorSize = floatFeatureVector.size(); + + + for(i = 0; i < floatFeatureVectorSize; i++) + featureVector.push_back(floatFeatureVector[i]); + floatFeatureVector.clear(); + + + + + ActiveDTWShapeModel evalShapeModel; + //current shape model evaluated against test Sample + + + ActiveDTWClusterModel evalClusterModel; + //currently evaluated cluster model + + + vector<ActiveDTWClusterModel> clusterVector; + //vector of cluster models of current shape model + + + shapeMatrix evalSingletonVector; + //vector of all singletonVectors of current shape model + + doubleVector eigenValues; + //eigen values of cluster model + + double2DVector eigenVector; + //eigen vectors of cluster model + + doubleVector clusterMean; + //cluster mean of cluster model + + doubleVector deformationParameters; + //paramters required to construct optimal Deformation + + doubleVector reconstructedSample; + //double vector form of optima lDeformation + + shapeMatrix optimalDeformations; + //vector of all optimalDeformations of a class + + vector<bool> clusterFilter; + //indicates which cluster are to be considered for computing DTW DISTANCE + + vector<bool> singletonFilter; + //indicates which singletons are to be considered for computing DTW DISTANCE + + vector<struct NeighborInfo> distInfo; + //used in dtwEuclidean filter + + vector<LTKShapeFeaturePtr> shapeFeatureVector; + + + /*****************COMPUTING DISTANCE******************************/ + if(subSetOfClasses.size() == 0) + { + for(i = 0; i < m_prototypeShapes.size(); i++) + { + evalShapeModel = m_prototypeShapes[i]; + clusterVector = evalShapeModel.getClusterModelVector(); + + + evalSingletonVector = evalShapeModel.getSingletonVector(); + + + int singletonSize = evalSingletonVector.size(); + int clusterVectorSize = clusterVector.size(); + + + + //computing the optimalDeformations + for(j = 0; j < clusterVectorSize; j++) + { + evalClusterModel = clusterVector[j]; + + eigenVector = evalClusterModel.getEigenVectors(); + + eigenValues = evalClusterModel.getEigenValues(); + + clusterMean = evalClusterModel.getClusterMean(); + + deformationParameters.assign(eigenVector.size(),0.0); + + + int errorCode = findOptimalDeformation(deformationParameters,eigenValues,eigenVector, + clusterMean,featureVector); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + //reconstruct the sample + double tempCoordinate = 0.0; + int clusterMeanSize = clusterMean.size(); + int deformationParametersSize = deformationParameters.size(); + + for(int k = 0; k < clusterMeanSize; k++) + { + tempCoordinate = clusterMean[k]; + + for(int l = 0; l < deformationParametersSize; l++) + tempCoordinate += deformationParameters[l]*eigenVector[l][k]; + + reconstructedSample.push_back(tempCoordinate); + } + + //converting the reconstructed Sample to a featureVector + errorCode = convertDoubleToFeatureVector(shapeFeatureVector,reconstructedSample); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + optimalDeformations.push_back(shapeFeatureVector); + + //clearing vectors + eigenValues.clear(); + eigenVector.clear(); + clusterMean.clear(); + reconstructedSample.clear(); + shapeFeatureVector.clear(); + deformationParameters.clear(); + } + + + //setting up dtweuclidean filter for the class + if(m_dtwEuclideanFilter != EUCLIDEAN_FILTER_OFF) + { + //calculating euclidean distance to clusters + for( j = 0; j < clusterVectorSize; j++) + { + + euclideanDistance = 0.0; + + errorCode = computeEuclideanDistance(shapeFeatureVec,optimalDeformations[j],euclideanDistance); + + + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + tempDist.typeId = CLUSTER; + tempDist.sampleId = j; + tempDist.distance = euclideanDistance; + + distInfo.push_back(tempDist); + } + + //calcualting euclidean distances to singletons + if(m_useSingleton == true || clusterVectorSize == 0) + { + + for(j = 0; j < singletonSize; j++) + { + + euclideanDistance = 0.0; + //computing euclidean distance between test sample + //and singleton vectors + + errorCode = computeEuclideanDistance(shapeFeatureVec,evalSingletonVector[j], + euclideanDistance); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + tempDist.typeId = SINGLETON; + tempDist.sampleId = j; + tempDist.distance = euclideanDistance; + + distInfo.push_back(tempDist); + + + } + } + + + //sorting the euclidean distances in ascending order + sort(distInfo.begin(), distInfo.end(), sortDist); + + + //choose the top n + int numTopChoices = (int)(distInfo.size() * m_dtwEuclideanFilter)/100; + if(numTopChoices == 0) + { + numTopChoices = distInfo.size(); + } + + //setting the filter + clusterFilter.assign(clusterVectorSize,false); + + if(m_useSingleton == true || clusterVectorSize == 0) + singletonFilter.assign(singletonSize,false); + + + for( j = 0; j < numTopChoices; j++) + { + if(distInfo[j].typeId == 0) + clusterFilter[distInfo[j].sampleId] = true; + + if(distInfo[j].typeId == 1) + singletonFilter[distInfo[j].sampleId] = true; + } + + //clearing distInfo + distInfo.clear(); + } + else + { + clusterFilter.assign(clusterVectorSize,true); + + if(m_useSingleton == true || clusterVectorSize == 0) + singletonFilter.assign(singletonSize,true); + } + + + /*****DETERMINING THE MINIMUM CLUSTER DISTANCE***************/ + float minDistance = FLT_MAX; + float minClusterDistance; + float minSingletonDistance; + + int clusterId; + int singletonId; + + for( j = 0; j < clusterVectorSize; j++) + { + + if(clusterFilter[j]) + { + float tempDistance = 0.0; + errorCode = computeDTWDistance(shapeFeatureVec,optimalDeformations[j],tempDistance); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + if(tempDistance < minDistance) + { + minDistance = tempDistance; + clusterId = j; + } + + + + } + + } + + clusterVector.clear(); + clusterFilter.clear(); + optimalDeformations.clear(); + + minClusterDistance = minDistance; + + /***DETERMINE THE MINIMUM DISTANCE FROM CLUSTERS ONLY IF THE + USE SINGLETON SWITCH IS TURNED ON. IF THE NUMBER OF CLUSTERS + IN A CLASS IS 0 THEN AUTOMATICALLY TURN ON THE SINGLETON SWITCH + FOR THAT CLASS ALONE ***/ + + if(m_useSingleton == false && clusterVectorSize == 0) + m_useSingleton = true; + + /***************DETERMINING MINIMUM DISTANCE FROM SINGLETON VECTORS*********/ + if(m_useSingleton == true) + { + evalSingletonVector = evalShapeModel.getSingletonVector(); + + int evalSingletonVectorSize = evalSingletonVector.size(); + + for(int j = 0; j < evalSingletonVectorSize; j++) + { + if(singletonFilter[j]) + { + + //calculate the dtw distance between testsamples and every singleton vector + float tempDistance = 0.0; + + errorCode = computeDTWDistance(shapeFeatureVec,evalSingletonVector[j],tempDistance); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + if(tempDistance < minDistance) + { + minDistance = tempDistance; + singletonId = j; + } + + } + } + singletonFilter.clear(); + } + + //clearing vectors + evalSingletonVector.clear(); + + minSingletonDistance = minDistance; + + //choosing the minimum distance + if(m_useSingleton == false) + { + tempPair.distance = minClusterDistance; + tempPair.typeId = CLUSTER; + tempPair.sampleId = clusterId; + } + else + { + if(clusterVectorSize == 0) + { + tempPair.distance = minSingletonDistance; + tempPair.typeId = SINGLETON; + tempPair.sampleId = singletonId; + } + else + { + if(minClusterDistance < minSingletonDistance) + { + tempPair.distance = minClusterDistance; + tempPair.typeId = CLUSTER; + tempPair.sampleId = clusterId; + } + else + { + tempPair.distance = minSingletonDistance; + tempPair.typeId = SINGLETON; + tempPair.sampleId = singletonId; + } + } + } + + //turning off the singleton switch in case it was turned on automatically + if(m_useSingleton == true && clusterVectorSize == 0) + m_useSingleton = false; + + + tempPair.classId = evalShapeModel.getShapeId(); + m_neighborInfoVec.push_back(tempPair); + } + } + else + { + /*****EVALUATE TEST SAMPLES ONLY AGAINST CLASSES SPECIFIED BY SUBSETOFCLASSES***/ + intVector::iterator subSetStart = subSetOfClasses.begin(); + intVector::iterator subSetEnd = subSetOfClasses.end(); + + for(;subSetStart != subSetEnd; ++subSetStart) + { + evalShapeModel = m_prototypeShapes[(*subSetStart)]; + + clusterVector = evalShapeModel.getClusterModelVector(); + + evalSingletonVector = evalShapeModel.getSingletonVector(); + + int clusterVectorSize = clusterVector.size(); + int singletonSize = evalSingletonVector.size(); + + //computing the optimalDeformations + for( j = 0; j < clusterVectorSize; j++) + { + evalClusterModel = clusterVector[j]; + + eigenVector = evalClusterModel.getEigenVectors(); + + eigenValues = evalClusterModel.getEigenValues(); + + clusterMean = evalClusterModel.getClusterMean(); + + deformationParameters.assign(eigenVector.size(),0.0); + + int errorCode = findOptimalDeformation(deformationParameters,eigenValues,eigenVector, + clusterMean,featureVector); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + //reconstruct the sample + double tempCoordinate = 0.0; + int clusterMeanSize = clusterMean.size(); + int deformationParametersSize = deformationParameters.size(); + + for(int k = 0; k < clusterMeanSize; k++) + { + tempCoordinate = clusterMean[k]; + + for(int l = 0; l < deformationParametersSize; l++) + tempCoordinate += deformationParameters[l]*eigenVector[l][k]; + + reconstructedSample.push_back(tempCoordinate); + } + + //converting the reconstructed Sample to a featureVector + errorCode = convertDoubleToFeatureVector(shapeFeatureVector,reconstructedSample); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + optimalDeformations.push_back(shapeFeatureVector); + + //clearing vectors + eigenValues.clear(); + eigenVector.clear(); + clusterMean.clear(); + reconstructedSample.clear(); + shapeFeatureVector.clear(); + deformationParameters.clear(); + } + + //setting up dtweuclidean filter for the class + if(m_dtwEuclideanFilter != EUCLIDEAN_FILTER_OFF) + { + //calculating euclidean distance to clusters + for(j = 0; j < clusterVectorSize; j++) + { + euclideanDistance = 0.0; + + errorCode = computeEuclideanDistance(shapeFeatureVec,optimalDeformations[j],euclideanDistance); + + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + tempDist.typeId = CLUSTER; + tempDist.sampleId = j; + tempDist.distance = euclideanDistance; + + distInfo.push_back(tempDist); + } + + //calcualting euclidean distances to singletons + if(m_useSingleton == true || clusterVectorSize == 0) + { + for(j = 0; j < singletonSize; j++) + { + euclideanDistance = 0.0; + //computing euclidean distance between test sample + //and singleton vectors + + errorCode = computeEuclideanDistance(shapeFeatureVec,evalSingletonVector[j], + euclideanDistance); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + tempDist.typeId = SINGLETON; + tempDist.sampleId = j; + tempDist.distance = euclideanDistance; + + distInfo.push_back(tempDist); + } + } + + //sorting the euclidean distances in ascending order + + sort(distInfo.begin(), distInfo.end(), sortDist); + + + //choose the top n + int numTopChoices = (int)(distInfo.size() * m_dtwEuclideanFilter)/100; + + if(numTopChoices == 0) + { + numTopChoices = distInfo.size(); + } + + //setting the filter + clusterFilter.assign(clusterVectorSize,false); + + if(m_useSingleton == true || clusterVectorSize == 0) + singletonFilter.assign(singletonSize,false); + + for( j = 0; j < numTopChoices; j++) + { + if(distInfo[j].typeId == 0) + clusterFilter[distInfo[j].sampleId] = true; + + if(distInfo[j].typeId == 1) + singletonFilter[distInfo[j].sampleId] = true; + } + + //clearing distInfo + distInfo.clear(); + } + + /*****DETERMINING THE MINIMUM CLUSTER DISTANCE***************/ + float minDistance = FLT_MAX; + float minClusterDistance; + float minSingletonDistance; + + int clusterId; + int singletonId; + + for( j = 0; j < clusterVectorSize; j++) + { + if(clusterFilter[j]) + { + float tempDistance = 0.0; + errorCode = computeDTWDistance(shapeFeatureVec,optimalDeformations[j],tempDistance); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + if(tempDistance < minDistance) + { + minDistance = tempDistance; + clusterId = j; + } + } + } + + clusterVector.clear(); + clusterFilter.clear(); + optimalDeformations.clear(); + + minClusterDistance = minDistance; + + /***DETERMINE THE MINIMUM DISTANCE FROM CLUSTERS ONLY IF THE + USE SINGLETON SWITCH IS TURNED ON. IF THE NUMBER OF CLUSTERS + IN A CLASS IS 0 THEN AUTOMATICALLY TURN ON THE SINGLETON SWITCH + FOR THAT CLASS ALONE ***/ + + if(m_useSingleton == false && clusterVectorSize == 0) + m_useSingleton = true; + + /***************DETERMINING MINIMUM DISTANCE FROM SINGLETON VECTORS*********/ + if(m_useSingleton == true) + { + + evalSingletonVector = evalShapeModel.getSingletonVector(); + int evalSingletonVectorSize = evalSingletonVector.size(); + + for(j = 0; j < evalSingletonVectorSize; j++) + { + if(singletonFilter[j]) + { + //calculate the dtw distance between testsamples and every singleton vector + float tempDistance = 0.0; + + errorCode = computeDTWDistance(shapeFeatureVec,evalSingletonVector[j],tempDistance); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + + LTKReturnError(errorCode); + } + + + if(tempDistance < minDistance) + { + minDistance = tempDistance; + singletonId = j; + } + + + } + } + + singletonFilter.clear(); + } + + //clearing vectors + evalSingletonVector.clear(); + + minSingletonDistance = minDistance; + + //choosing the minimum distance + if(m_useSingleton == false) + { + tempPair.distance = minClusterDistance; + tempPair.typeId = CLUSTER; + tempPair.sampleId = clusterId; + } + else + { + if(clusterVectorSize == 0) + { + tempPair.distance = minSingletonDistance; + tempPair.typeId = SINGLETON; + tempPair.sampleId = singletonId; + } + else + { + if(minClusterDistance < minSingletonDistance) + { + tempPair.distance = minClusterDistance; + tempPair.typeId = CLUSTER; + tempPair.sampleId = clusterId; + } + else + { + tempPair.distance = minSingletonDistance; + tempPair.typeId = SINGLETON; + tempPair.sampleId = singletonId; + } + } + } + + //turning off the singleton switch in case it was turned on automatically + if(m_useSingleton == true && clusterVectorSize == 0) + m_useSingleton = false; + + + tempPair.classId = evalShapeModel.getShapeId(); + + + m_neighborInfoVec.push_back(tempPair); + } + } + + featureVector.clear(); + + + //Sort the distIndexPairVector based on distances, in ascending order. + sort(m_neighborInfoVec.begin(), m_neighborInfoVec.end(), sortDist); + + //Reject the sample if the similarity of the nearest sample is lower than m_rejectThreshold specified by the user. + if(SIMILARITY(m_neighborInfoVec[0].distance) <= m_rejectThreshold) + { + m_vecRecoResult.clear(); + LOG(LTKLogger::LTK_LOGLEVEL_INFO)<<"Test sample too distinct, rejecting the sample"<<endl; + return SUCCESS; + } + + //compute confidence + if((errorCode = computeConfidence()) != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::recognize()" << endl; + LTKReturnError(errorCode); + } + + // Temporary result vector to store the results based on confThreshold and numChoices specified by the user. + vector<LTKShapeRecoResult> tempResultVector; + + //If confThreshold is specified, get the entries from resultVector with confidence >= confThreshold + if(confThreshold != CONF_THRESHOLD_FILTER_OFF) + { + for(i = 0 ; i < m_vecRecoResult.size() ; i++) + { + if( m_vecRecoResult[i].getConfidence() >= confThreshold) + { + tempResultVector.push_back(m_vecRecoResult[i]); + } + } + m_vecRecoResult.clear(); + m_vecRecoResult = tempResultVector; + tempResultVector.clear(); + } + //Check if outResultVector is empty, if so, log + if(m_vecRecoResult.size() == 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_INFO) << + "Size of the result vector is empty, could not satisfy confThreshold criteria"<<endl; + } + + //If numChoices is specified, get the top numChoices entries from outResultVector + if(numChoices != NUM_CHOICES_FILTER_OFF) + { + //Get the entries from outResultVector only if size of resultVector > numChoices + if(m_vecRecoResult.size() > numChoices) + { + for( i = 0 ; i < numChoices ; ++i) + tempResultVector.push_back(m_vecRecoResult[i]); + m_vecRecoResult.clear(); + m_vecRecoResult = tempResultVector; + tempResultVector.clear(); + } + + } + + outResultVector = m_vecRecoResult; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::recognize()" << endl; + + return SUCCESS; + +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : sortDist +* DESCRIPTION : +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +bool ActiveDTWShapeRecognizer::sortDist(const NeighborInfo& x, const NeighborInfo& y) +{ + return (x.distance) < (y.distance); +} + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : computeConfidence +* DESCRIPTION : +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ +int ActiveDTWShapeRecognizer::computeConfidence() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::computeConfidence()" << endl; + + /******************************************************************/ + /*******************VALIDATING INPUT ARGUMENTS*********************/ + /******************************************************************/ + if(m_neighborInfoVec.empty()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< ENEIGHBOR_INFO_VECTOR_EMPTY << " " << + getErrorMessage(ENEIGHBOR_INFO_VECTOR_EMPTY) << + " ActiveDTWShapeRecognizer::computeConfidence()" << endl; + + LTKReturnError(ENEIGHBOR_INFO_VECTOR_EMPTY); + } + // Temporary vector to store the recognition results + LTKShapeRecoResult outResult; + vector<pair<int,float> > classIdSimilarityPairVec; + pair<int, float> classIdSimilarityPair; + + // Temporary vector to store the distinct classes appearing in distIndexPairVector + intVector distinctClassVector; + intVector::iterator distinctClassVectorIter; + + vector <LTKShapeRecoResult>::iterator resultVectorIter = m_vecRecoResult.begin(); + vector <LTKShapeRecoResult>::iterator resultVectorIterEnd = m_vecRecoResult.end(); + + // Variable to store sum of distances to all the prototypes in distIndexPairVector + float similaritySum = 0.0f; + // Temporary variable to store the confidence value. + float confidence = 0.0f; + + + + // Confidence computation for the ActiveDTW (1-NN) Classifier + if(m_nearestNeighbors == 1) + { + vector <struct NeighborInfo>::iterator distIndexPairIter = m_neighborInfoVec.begin(); + vector <struct NeighborInfo>::iterator distIndexPairIterEnd = m_neighborInfoVec.end(); + + + + for(; distIndexPairIter != distIndexPairIterEnd; ++distIndexPairIter) + { + //Check if the class is already present in distinctClassVector + //The complexity of STL's find() is linear, with atmost last-first comparisons for equality + distinctClassVectorIter = find(distinctClassVector.begin(), distinctClassVector.end(), (*distIndexPairIter).classId); + + //The distinctClassVectorIter will point to distinctClassVector.end() if the class is not present in distinctClassVector + if(distinctClassVectorIter == distinctClassVector.end()) + { + classIdSimilarityPair.first = (*distIndexPairIter).classId ; + float similarityValue = SIMILARITY((*distIndexPairIter).distance); + + classIdSimilarityPair.second = similarityValue; + similaritySum += similarityValue; + + classIdSimilarityPairVec.push_back(classIdSimilarityPair); + distinctClassVector.push_back((*distIndexPairIter).classId); + } + } + + /************COMPUTING CONFIDENCE VALUES FOR EACH CLASS************/ + int classIdSimilarityPairVecSize = classIdSimilarityPairVec.size(); + for( int i = 0 ; i < classIdSimilarityPairVecSize ; ++i) + { + int classID = classIdSimilarityPairVec[i].first; + confidence = classIdSimilarityPairVec[i].second; + confidence /= similaritySum; + outResult.setConfidence(confidence); + outResult.setShapeId(classID); + + if(confidence > 0) + m_vecRecoResult.push_back(outResult); + } + classIdSimilarityPairVec.clear(); + } + // Computing confidence for k-NN classifier, implementation of the confidence measure described in paper (cite) + else + { + if(m_nearestNeighbors >= m_neighborInfoVec.size()) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << + "m_nearestNeighbors >= m_prototypeSet.size(), using distIndexPairVector.size() for m_nearestNeighbors instead" << endl; + m_nearestNeighbors = m_neighborInfoVec.size(); + } + + // Variable to store the maximum of the number of samples per class. + int maxClassSize = (max_element(m_shapeIDNumPrototypesMap.begin(), m_shapeIDNumPrototypesMap.end(), &compareMap))->second; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "maxClassSize: " <<maxClassSize<< endl; + + // Vector to store the cumulative similarity values + vector<float> cumulativeSimilaritySum; + + // Populate the values in cumulativeSimilaritySum vector for the top m_nearestNeighbors prototypes + // Assumption is m_nearestNeighbors >= MIN_NEARESTNEIGHBORS and m_nearestNeighbors < m_dtwEuclideanFilter, validation done in readClassifierConfig() + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Displaying cumulativeSimilaritySum..." << endl; + int i = 0; + for( i = 0 ; i < m_nearestNeighbors ; ++i) + { + + classIdSimilarityPair.first = m_neighborInfoVec[i].classId; + float similarityValue = SIMILARITY((m_neighborInfoVec[i]).distance); + + classIdSimilarityPair.second = similarityValue; + + classIdSimilarityPairVec.push_back(classIdSimilarityPair); + similaritySum += similarityValue; + cumulativeSimilaritySum.push_back(similaritySum); + + // Logging the cumulative similarity values for debugging + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "classID:" << + m_neighborInfoVec[i].classId << " confidence:" << + similarityValue << endl; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << i << ": " << similaritySum << endl; + } + + + for(i = 0 ; i < classIdSimilarityPairVec.size() ; ++i) + { + + int classID = classIdSimilarityPairVec[i].first; + + int finalNearestNeighbors = 0; + + //Check if the class is already present in distinctClassVector + distinctClassVectorIter = find(distinctClassVector.begin(), distinctClassVector.end(), classID); + + //The distinctClassVectorIter will point to distinctClassVector.end() if the class is not present in distinctClassVector + if(distinctClassVectorIter == distinctClassVector.end()) + { + distinctClassVector.push_back(classID); + confidence = 0.0f; + + //If the confidence is based on Adaptive k-NN scheme, + //Computing number of nearest neighbours for the class to be used for computation of confidence + if(m_adaptivekNN == true ) + { + + int sizeProportion = (int)ceil(1.0*m_nearestNeighbors*m_shapeIDNumPrototypesMap[classID]/maxClassSize); + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"sizeProportion of class " <<classID<<" is "<<sizeProportion<<endl; + + // Computing min(sizeProportion, m_shapeIDNumPrototypesMap[classID]) + int upperBound = (sizeProportion < m_shapeIDNumPrototypesMap[classID]) ? sizeProportion:m_shapeIDNumPrototypesMap[classID]; + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"upperBound: " <<upperBound<<endl; + + // Computing max(upperBound, MIN_NEARESTNEIGHBORS) + finalNearestNeighbors = (MIN_NEARESTNEIGHBORS > upperBound) ? MIN_NEARESTNEIGHBORS:upperBound; + } + //Else, compute kNN based confidence + else if(m_adaptivekNN == false) + { + finalNearestNeighbors = m_nearestNeighbors; + } + else + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<"Error: " << ECONFIG_FILE_RANGE << " " << + "m_adaptivekNN should be true or false" << + " ActiveDTWShapeRecognizer::computeConfidence()" << endl; + LTKReturnError(ECONFIG_FILE_RANGE); + } + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"finalNearestNeighbors: " <<finalNearestNeighbors<<endl; + + for( int j = 0 ; j < finalNearestNeighbors ; ++j) + { + if(classID == classIdSimilarityPairVec[j].first) + { + confidence += classIdSimilarityPairVec[j].second; + } + } + confidence /= cumulativeSimilaritySum[finalNearestNeighbors-1]; + + outResult.setShapeId(classID); + outResult.setConfidence(confidence); + + if(confidence > 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"classId: " <<classID<<" confidence: "<<confidence<<endl; + + m_vecRecoResult.push_back(outResult); + } + } + } + classIdSimilarityPairVec.clear(); + } + + //Sort the result vector in descending order of confidence + sort(m_vecRecoResult.begin(), m_vecRecoResult.end(), sortResultByConfidence); + + distinctClassVector.clear(); + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::computeConfidence()" << endl; + + return SUCCESS; + +} + + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : sortResultByConfidence +* DESCRIPTION : Sort the LTKShapeRecoResult vector based on the Confidence value +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ +bool ActiveDTWShapeRecognizer::sortResultByConfidence(const LTKShapeRecoResult& x, const LTKShapeRecoResult& y) +{ + return (x.getConfidence()) > (y.getConfidence()); +} +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : compareMap +* DESCRIPTION : Sort the STL's map based on the 'value'(second) field +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ + +bool ActiveDTWShapeRecognizer::compareMap( const map<int, int>::value_type& lhs, const map<int, int>::value_type& rhs ) +{ + return lhs.second < rhs.second; +} + + + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : unloadModelData +* DESCRIPTION : +* ARGUMENTS : +* RETURNS : SUCCESS +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::unloadModelData() +{ + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::unloadModelData()" << endl; + + int returnStatus = SUCCESS; + + //Update MDT file with any modification, if available in memory + if(m_prototypeSetModifyCount >0) + { + m_prototypeSetModifyCount = m_MDTUpdateFreq-1; + + returnStatus = writePrototypeShapesToMDTFile(); + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " << + " ActiveDTWShapeRecognizer::unloadModelData()" << endl; + } + m_prototypeSetModifyCount = 0; + } + + //Clearing the prototypSet + m_prototypeShapes.clear(); + m_shapeIDNumPrototypesMap.clear(); + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::unloadModelData()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : setDeviceContext +* DESCRIPTION : New Function - Not yet added +* ARGUMENTS : +* RETURNS : SUCCESS +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::setDeviceContext(const LTKCaptureDevice& deviceInfo) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::setDeviceContext()" << endl; + + m_captureDevice = deviceInfo; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::setDeviceContext()" << endl; + + return SUCCESS; +} +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : performClustering +* DESCRIPTION : This method performs clustering on each class data +and returns a vector specifying which samples +belong to which cluster +* ARGUMENTS : INPUT +shapeSamplesVec vector<LTKShapeSample> Class Data to be clustered +: OUTPUT +outputVector int2DVector +(Here each row of the outputVector denotes a cluster +in turn each row holds the indices of the samples +belonging to that cluster) +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ +int ActiveDTWShapeRecognizer::performClustering(const vector<LTKShapeSample>& shapeSamplesVec, + int2DVector& outputVector) +{ + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::performClustering()" << endl; + + intVector tempVec; + + float2DVector distanceMatrix; + int sampleCount=shapeSamplesVec.size(); + int returnStatus = SUCCESS; + + + + if(m_prototypeReductionFactor == -1) + { + //find number of clusters automatically + //this is done when either of NumClusters or PrototypeReducrion factor is set + //to automatic + LTKHierarchicalClustering<LTKShapeSample,ActiveDTWShapeRecognizer> hc(shapeSamplesVec,AVERAGE_LINKAGE,AVG_SIL); + + returnStatus = hc.cluster(this,&ActiveDTWShapeRecognizer::computeDTWDistance); + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " << + " ActiveDTWShapeRecognizer::performClustering()" << endl; + LTKReturnError(returnStatus); + } + + //Cluster results are populated in an outputVector + hc.getClusterResult(outputVector); + + } + else if(m_prototypeReductionFactor == 0|| m_numClusters >= sampleCount) + { + intVector clusterIndices; + //case where clustering is not required every sample is a cluster by itself + for(int i = 0; i < sampleCount; i++) + clusterIndices.push_back(i); + + outputVector.push_back(clusterIndices); + clusterIndices.clear(); + + } + else + { + //clustering has to be performed + + int numClusters; + if(m_numClusters == NN_NUM_CLUST_INITIAL) + { + numClusters = (100-m_prototypeReductionFactor)*sampleCount/100; + if(numClusters == 0) + { + numClusters = 1; + } + } + + else if(m_prototypeReductionFactor == NN_NUM_CLUST_INITIAL) + { + numClusters = m_numClusters; + } + + try + { + + LTKHierarchicalClustering<LTKShapeSample,ActiveDTWShapeRecognizer> + hc(shapeSamplesVec,numClusters, AVERAGE_LINKAGE); + + if(numClusters == 1) + { + int tempVar; + hc.computeProximityMatrix(this, &ActiveDTWShapeRecognizer::computeDTWDistance); + + + for(tempVar=0;tempVar<shapeSamplesVec.size();tempVar++) + { + tempVec.push_back(tempVar); + } + + outputVector.push_back(tempVec); + tempVec.clear(); + } + else + { + returnStatus = hc.cluster(this,&ActiveDTWShapeRecognizer::computeDTWDistance); + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " << + " ActiveDTWShapeRecognizer::performClustering()" << endl; + LTKReturnError(returnStatus); + } + + //Cluster results are populated in an outputVector + hc.getClusterResult(outputVector); + } + + } + catch(LTKException e) + { + int errorCode = e.getErrorCode(); + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " << + " ActiveDTWShapeRecognizer::performClustering()" << endl; + LTKReturnError(errorCode); + } + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::performClustering()" << endl; + + + + return SUCCESS; + +} + + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getShapeSampleFromInkFile +* DESCRIPTION : This method will get the ShapeSample by giving the ink +* file path as input +* ARGUMENTS : +* RETURNS : SUCCESS +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ +int ActiveDTWShapeRecognizer::getShapeFeatureFromInkFile(const string& inkFilePath, + vector<LTKShapeFeaturePtr>& shapeFeatureVec) +{ + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::getShapeFeatureFromInkFile()" << endl; + + if ( inkFilePath.empty() ) + return FAILURE; + + LTKCaptureDevice captureDevice; + LTKScreenContext screenContext; + + + LTKTraceGroup inTraceGroup, preprocessedTraceGroup; + + + inTraceGroup.emptyAllTraces(); + + int returnVal = m_shapeRecUtil.readInkFromFile(inkFilePath, + m_lipiRootPath, inTraceGroup, + captureDevice, screenContext); + + if (returnVal!= SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<returnVal<< + " ActiveDTWShapeRecognizer::getShapeFeatureFromInkFile()" << endl; + LTKReturnError(returnVal); + } + + m_ptrPreproc->setCaptureDevice(captureDevice); + m_ptrPreproc->setScreenContext(screenContext); + + preprocessedTraceGroup.emptyAllTraces(); + + //Preprocessing to be done for the trace group that was read + int errorCode = preprocess(inTraceGroup, preprocessedTraceGroup); + if( errorCode != SUCCESS ) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::getShapeFeatureFromInkFile()" << endl; + LTKReturnError(errorCode); + } + + + + errorCode = m_ptrFeatureExtractor->extractFeatures(preprocessedTraceGroup, + shapeFeatureVec); + + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::getShapeFeatureFromInkFile()" << endl; + LTKReturnError(errorCode); + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::getShapeFeatureFromInkFile()" << endl; + + return SUCCESS; +} + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : trainFromListFile +* DESCRIPTION : This method will do the training by giving the Train List +* file as input +* ARGUMENTS : +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ +int ActiveDTWShapeRecognizer::trainFromListFile(const string& listFilePath) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + + //Count for the no. of samples read for a shape + int sampleCount = 0; + + //Count of the no. of shapes read so far + int shapeCount = 0; + + //Flag to skip reading a newline in the list file, when a new class starts + bool lastshapeIdFlag = false; + + //Ink File Path + string path = ""; + + //Line from the list file + string line = ""; + + //Line is split into tokens + stringVector tokens; + + //Flag is set when EOF is reached + bool eofFlag = false; + + //ID for each shapes + int shapeId = -1; + + //classId of the character + int prevClassId = -1; + + //Indicates the first class + bool initClassFlag = false; + + /**vectors for cluster indices + *each vector corresponds to a cluster in a class + *each vector has the indices of the shapesamples belonging to the cluster + **/ + int2DVector clusterIndices; + + /** + * this will hold a vector of indices pertaining to a certain cluster + **/ + intVector cluster; + + /** + * this will hold a temporary float feature vector + **/ + doubleVector tempFeature; + + /** + * Feature Matrix + **/ + double2DVector featureMatrix; + + /** + * Covariance Matrix + **/ + double2DVector covarianceMatrix; + + /** + * Eigen Vector Matrix + **/ + double2DVector eigenVectors; + + /** + * Eigen Values + **/ + doubleVector eigenValues; + + /** + * nrot --> number of iterations for eigen vector computation + **/ + int nrot = 0; + + /** + * clusterModel + **/ + + ActiveDTWClusterModel clusterModel; + + + + /** + * vector of cluster models + **/ + vector<ActiveDTWClusterModel> clusterModelVector; + + + /** + * shape Model + **/ + + ActiveDTWShapeModel shapeModel; + + /** + * vector of singleton clusters + **/ + + shapeMatrix singletonVector; + + /** + * selected eigen vectors + **/ + double2DVector selectedEigenVectors; + + /** + * cluster mean + **/ + doubleVector clusterMean; + + + + LTKShapeSample shapeSampleFeatures; + + + vector<LTKShapeSample> shapeSamplesVec; + + vector<LTKShapeSample> clusteredShapeSampleVec; + + ofstream mdtFileHandle; + ifstream listFileHandle; + + vector<LTKShapeFeaturePtr> shapeFeature; + + //Opening the train list file for reading mode + listFileHandle.open(listFilePath.c_str(), ios::in); + + //Return error if unable to open the training list file + if(!listFileHandle) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< ETRAINLIST_FILE_OPEN << " " << + getErrorMessage(ETRAINLIST_FILE_OPEN)<< + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + LTKReturnError(ETRAINLIST_FILE_OPEN); + } + + //Open the Model data file for writing mode + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle.open(m_activedtwMDTFilePath.c_str(), ios::out); + } + else + { + mdtFileHandle.open(m_activedtwMDTFilePath.c_str(),ios::out|ios::binary); + } + + //Return error if unable to open the Model data file + if(!mdtFileHandle) + { + listFileHandle.close(); + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EMODEL_DATA_FILE_OPEN << " " << + getErrorMessage(EMODEL_DATA_FILE_OPEN)<< + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + LTKReturnError(EMODEL_DATA_FILE_OPEN); + } + + //Write the number of Shapes + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle << m_numShapes << endl; + } + else + { + mdtFileHandle.write((char*) &m_numShapes, sizeof(unsigned short)); + } + + int errorCode = SUCCESS; + while(!listFileHandle.eof()) + { + // Not a sample of a new class + if( lastshapeIdFlag == false ) + { + //Get the line from the list file + getline(listFileHandle, line, NEW_LINE_DELIMITER); + + path = ""; + + //Check if EOF is reached + if( listFileHandle.eof() ) + { + eofFlag = true; + } + + //Skip commented line + if ( line[0] == COMMENTCHAR ) + { + continue; + } + + if (eofFlag == false) + { + //Tokenize the string + errorCode = LTKStringUtil::tokenizeString(line, LIST_FILE_DELIMITER, tokens); + + if( errorCode != SUCCESS ) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + listFileHandle.close(); + mdtFileHandle.close(); + LTKReturnError(errorCode); + } + + + //Tokens must be of size 2, one is pathname and other is shapeId + //If the end of file not reached then continue the looping + if( tokens.size() != 2 && eofFlag == false ) + continue; + + //Tokens[0] indicates the path name + path = tokens[0]; + + //Tokens[1] indicates the shapeId + shapeId = atoi( tokens[1].c_str() ); + + if(shapeId < 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< + "The ActiveDTWShapeRecognizer requires training file class Ids to be positive integers and listed in the increasing order"<< + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + errorCode = EINVALID_SHAPEID; + break; + } + else if(shapeId < prevClassId) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< + "Shape IDs in the train list file should be in the increasing order. Please use scripts/validateListFile.pl to generate list files." << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + errorCode = EINVALID_ORDER_LISTFILE; + break; + } + + + //This condition is used to check the first shape must be start from 0 + if( initClassFlag == false ) + { + initClassFlag = true; + prevClassId=shapeId; + } + } + } + else //Sample of a new class; do not read the next line during this iteration + { + //flag unset to read next line during the next iteration + lastshapeIdFlag = false; + } + + // Sample from the same class, extract features, and push the extracted features to shapeSamplesVec + if( shapeId == prevClassId && ! path.empty()) + { + if( getShapeFeatureFromInkFile(path, shapeFeature) != SUCCESS ) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< + "Error extracting features from the ink file: " << + path << ", extracting features from the next sample."<< + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + continue; + } + + shapeSampleFeatures.setFeatureVector(shapeFeature); + shapeSampleFeatures.setClassID(shapeId); + + ++sampleCount; + shapeSamplesVec.push_back(shapeSampleFeatures); + + shapeFeature.clear(); + + } + + // Sample of new class seen, or end of list file reached; train all the samples of previous class ID + if( shapeId != prevClassId || eofFlag == true ) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << + "Training for class : " << prevClassId << endl; + + //Increase shape count only if there are atleast one sample per class + if( sampleCount > 0 ) + shapeCount++; + + //check that shapecount must not be greater than specified number + //of shapes, if projecttype was not dynamic + if( !m_projectTypeDynamic && shapeCount > m_numShapes ) + { + errorCode = EINVALID_NUM_OF_SHAPES; + break; + } + + if( shapeCount > 0 && sampleCount > 0 ) + { + + /** PERFORM CLUSTERING **/ + + + + errorCode = performClustering(shapeSamplesVec,clusterIndices); + + + + if( errorCode != SUCCESS ) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + listFileHandle.close(); + mdtFileHandle.close(); + LTKReturnError(errorCode); + } + + + + + int2DVector::iterator iter = clusterIndices.begin(); + int2DVector::iterator iEnd = clusterIndices.end(); + + + + /**ITERATING THROUGH THE VARIOUS CLUSTERS **/ + for(;iter != iEnd; ++iter) + { + cluster = (*iter); + + + + /** SINGLETON VECTORS **/ + if(cluster.size() < m_minClusterSize) + { + /**CONSTRUCTING THE SINGLETON VECTOR**/ + for(int i = 0; i < cluster.size(); i++) + singletonVector.push_back(shapeSamplesVec[cluster[i]].getFeatureVector()); + } + + /** CLUSTER PROCESSING **/ + else + { + //gather all the shape samples pertaining to a particular cluster + int clusterSize = cluster.size(); + int i = 0; + for( i = 0; i < clusterSize; i++) + { + //CONVERT ALL THE SHAPE SAMPLES TO FLOAT FEATURE VECTORS + floatVector floatFeatureVector; + errorCode = m_shapeRecUtil.shapeFeatureVectorToFloatVector(shapeSamplesVec[cluster[i]].getFeatureVector(), + floatFeatureVector); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + LTKReturnError(errorCode); + } + + int floatFeatureVectorSize = floatFeatureVector.size(); + for(int i = 0; i < floatFeatureVectorSize; i++) + tempFeature.push_back(floatFeatureVector[i]); + + featureMatrix.push_back(tempFeature); + tempFeature.clear(); + floatFeatureVector.clear(); + + } + + + /** COMPUTING COVARIANCE MATRIX **/ + errorCode = computeCovarianceMatrix(featureMatrix,covarianceMatrix,clusterMean); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + LTKReturnError(errorCode); + } + + //setting cluster mean for cluster model + + clusterModel.setClusterMean(clusterMean); + + + /** COMPUTING EIGEN VECTORS **/ + //computes the eigen vector for the larger covarianceMatrix + //from the smaller covarianceMatrix + errorCode = computeEigenVectorsForLargeDimension(featureMatrix,covarianceMatrix,eigenVectors,eigenValues); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + LTKReturnError(errorCode); + } + + + doubleVector tempEigenVector; + int eigenVectorDimension = eigenVectors.size(); + + if(eigenVectorDimension <= 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EEMPTY_EIGENVECTORS << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + LTKReturnError(EEMPTY_EIGENVECTORS); + } + + int numEigenVectors = eigenVectors[0].size(); + + if(numEigenVectors <= 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_NUM_OF_EIGENVECTORS << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + LTKReturnError(EINVALID_NUM_OF_EIGENVECTORS ); + } + + for( i = 0; i < numEigenVectors; i++) + { + for(int j = 0; j < eigenVectorDimension; j++) + tempEigenVector.push_back(eigenVectors[j][i]); + + selectedEigenVectors.push_back(tempEigenVector); + tempEigenVector.clear(); + } + + + + /**CONSTRUCTING CLUSTER MODEL **/ + errorCode = clusterModel.setNumSamples(cluster.size()); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + LTKReturnError(errorCode); + } + + + clusterModel.setEigenValues(eigenValues); + + clusterModel.setEigenVectors(selectedEigenVectors); + + + /**APPENDING THE CLUSTER MODEL VECTOR**/ + clusterModelVector.push_back(clusterModel); + + featureMatrix.clear(); + covarianceMatrix.clear(); + selectedEigenVectors.clear(); + clusterMean.clear(); + eigenValues.clear(); + eigenVectors.clear(); + } + } + + + clusterIndices.clear(); + + + + /**CONSTRUCTING SHAPE MODEL**/ + + errorCode = shapeModel.setShapeId(shapeCount - 1); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " "<< endl; + LTKReturnError(errorCode); + } + + shapeModel.setClusterModelVector(clusterModelVector); + + shapeModel.setSingletonVector(singletonVector); + + + clusterModelVector.clear(); + singletonVector.clear(); + + + if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_CLUSTERING) == 0) + { + + //Writing results to the MDT file + + errorCode = appendShapeModelToMDTFile(shapeModel, mdtFileHandle); + + + if( errorCode != SUCCESS ) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<errorCode << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + + listFileHandle.close(); + mdtFileHandle.close(); + LTKReturnError(errorCode); + } + + + } + + //Clearing the shapeSampleVector and clusteredShapeSampleVector + + + shapeSamplesVec.clear(); + + //Resetting sampleCount for the next class + sampleCount = 0; + + //Set the flag so that the already read line of next class in the list file is not lost + lastshapeIdFlag = true; + + prevClassId = shapeId; + + } + } + }//End of while + + //Closing the Train List file and Model Data file + listFileHandle.close(); + mdtFileHandle.close(); + + if(!m_projectTypeDynamic && shapeCount != m_numShapes) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EINVALID_NUM_OF_SHAPES << " " << + getErrorMessage(EINVALID_NUM_OF_SHAPES)<< + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + LTKReturnError(EINVALID_NUM_OF_SHAPES); + } + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + LTKReturnError(errorCode); + + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + + return SUCCESS; + +} + + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : computeCovarianceMatrix +* DESCRIPTION : This method computes the covariance matrix and mean of +a feature matrix +* ARGUMENTS : INPUT +featureMatrix double2DVector Feature matrix whose covarianceMatrix +is to be computed +;OUTPUT +covarianceMatrix double2DVector covarianceMatrix of feature matrix +meanFeature doubleVector mean of feature matrix + + * RETURNS : integer Holds error value if occurs + * Holds SUCCESS if no errors + *************************************************************************************/ + int ActiveDTWShapeRecognizer::computeCovarianceMatrix(double2DVector& featureMatrix, + double2DVector& covarianceMatrix,doubleVector& meanFeature) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::computeCovarianceMatrix()" << endl; + + if(featureMatrix.empty()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_FEATUREMATRIX << " " << + getErrorMessage(EEMPTY_FEATUREMATRIX) << + " ActiveDTWShapeRecognizer::computeCovarianceMatrix()" << endl; + + LTKReturnError(EEMPTY_FEATUREMATRIX); + } + + + doubleVector tempVector; + double mean; + + int numberOfRows; + int numberOfColumns; + + //rows + numberOfRows = featureMatrix.size(); + //cols + numberOfColumns = featureMatrix[0].size(); + + + int i = 0; + int j = 0; + /***********CALCULATING MEAN*********/ + for(i = 0; i < numberOfColumns;i++) + { + mean = 0.0; + for(j = 0;j < numberOfRows;j++) + { + mean = mean + featureMatrix[j][i]; + } + mean = mean /numberOfRows; + meanFeature.push_back(mean); + } + + /**********MEAN CORRECTED DATA************/ + for( i = 0; i < numberOfRows; i++) + { + for(j = 0; j < numberOfColumns; j++) + { + featureMatrix[i][j] = featureMatrix[i][j] - meanFeature[j]; + } + } + + /** COMPUTING COVARIANCE MATRIX**/ + tempVector.assign(numberOfColumns,0.0); + covarianceMatrix.assign(numberOfColumns,tempVector); + tempVector.clear(); + + bool bcovarianceMatrixFlag = false; + for( i = 0; i < numberOfColumns; i++) + { + for(j = 0;j < numberOfColumns; j++) + { + if(i <= j) + { + for(int k = 0; k < numberOfRows; k++) + { + + covarianceMatrix[i][j] += featureMatrix[k][i]*featureMatrix[k][j]; + + } + covarianceMatrix[i][j] = covarianceMatrix[i][j] /(numberOfRows - 1); + } + else + { + covarianceMatrix[i][j] = covarianceMatrix[j][i]; + } + if(covarianceMatrix[i][j] != 0.0) + bcovarianceMatrixFlag = true; + } + } + + if(!bcovarianceMatrixFlag) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_COVARIANCEMATRIX << " " << + getErrorMessage(EEMPTY_COVARIANCEMATRIX) << + " ActiveDTWShapeRecognizer::computeCovarianceMatrix()" << endl; + + LTKReturnError(EEMPTY_COVARIANCEMATRIX); + } + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::computeCovarianceMatrix()" << endl; + + return SUCCESS; + } + + + /********************************************************************************** + * AUTHOR : S Anand + * DATE : 3-MAR-2009 + * NAME : computeEigenVectors + * DESCRIPTION : This method computes the eigenValues and eigenVectors of + a covarianceMatrix + * ARGUMENTS : INPUT + covarianceMatrix double2DVector (matrix whose eigenValues and eigenVectors are to be computed) + rank int (rank of covarianceMatrix) + nrot int (number of rotations) This a parameter used by the algorithm + OUTPUT + eigenValueVec doubleVector Eigen values of covarianceMatrix + eigenVectorMatrix double2DVector Eigen vectors of covarianceMatrix + + * RETURNS : integer Holds error value if occurs + * Holds SUCCESS if no erros + * NOTES : + * CHANGE HISTROY + * Author Date Description + *************************************************************************************/ + int ActiveDTWShapeRecognizer::computeEigenVectors(double2DVector &covarianceMatrix,const int rank, + doubleVector &eigenValueVec, double2DVector &eigenVectorMatrix, int& nrot) + { + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::computeEigenVectors()" << endl; + + if(covarianceMatrix.empty()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_COVARIANCEMATRIX << " " << + getErrorMessage(EEMPTY_COVARIANCEMATRIX) << + " ActiveDTWShapeRecognizer::computeEigenVectors()" << endl; + + LTKReturnError(EEMPTY_COVARIANCEMATRIX); + } + + if(rank <= 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EINVALID_RANK << " " << + getErrorMessage(EINVALID_RANK) << + " ActiveDTWShapeRecognizer::computeEigenVectors()" << endl; + + LTKReturnError(EINVALID_RANK); + } + + int MAX_ITER = 1000; + + int ip,count,p,q,r; + + double theta, tau, t,sm,s,h,g,c; + + double app,aqq,apq,vpp,vqq,vpq; + + double2DVector::iterator itrRow,itrRowEnd; + + doubleVector::iterator itrCol,itrColEnd; + + itrRowEnd = eigenVectorMatrix.end(); + + for(ip = 0,itrRow = eigenVectorMatrix.begin(); itrRow <itrRowEnd;++ip, ++itrRow) + { + itrColEnd = (*itrRow).end(); + + for(itrCol = (*itrRow).begin(); itrCol < itrColEnd; ++itrCol) + { + *itrCol = 0; + } + + *((*itrRow).begin() + ip) = 1; + + eigenValueVec.push_back(0.0); + } + + nrot = 0; + + for(count = 0; count < MAX_ITER; count++) + { + nrot++; + + sm = 0.0; + + itrRowEnd = covarianceMatrix.end(); + + for(p = 0,itrRow = covarianceMatrix.begin(); itrRow <itrRowEnd;++p, ++itrRow) + { + itrColEnd = (*itrRow).end(); + + for(itrCol = (*itrRow).begin()+p+1; itrCol < itrColEnd; ++itrCol) + { + sm += fabs(*itrCol); + } + } + + if(sm < EPS) + { + for(r=0;r<rank;r++) + { + eigenValueVec[r] = covarianceMatrix[r][r]; + } + + } + + for(p=0; p<(rank-1) ; p++) + { + for(q=(p+1); q<rank; q++) + { + if(fabs(covarianceMatrix[p][q])>EPS1) + { + theta = (covarianceMatrix[q][q] - covarianceMatrix[p][p])/ + (2*covarianceMatrix[p][q]); + + t = sqrt(1+theta * theta) - theta; + + c = 1/(sqrt(1+t*t)); + + s = t*c; + + tau = s/(1+c); + + apq = covarianceMatrix[p][q]; + + app = covarianceMatrix[p][p]; + + aqq = covarianceMatrix[q][q]; + + vpp = eigenVectorMatrix[p][p]; + + vpq = eigenVectorMatrix[p][q]; + + vqq = eigenVectorMatrix[q][q]; + + for(r=0;r<p;r++) + { + h = covarianceMatrix[r][p]; + + g = covarianceMatrix[r][q]; + + covarianceMatrix[r][p] = (double)(c*h - s*g); + + covarianceMatrix[r][q] = (double)(c*g + s*h); + } + covarianceMatrix[p][p] -= (double)(t*apq); + + covarianceMatrix[p][q] = (double)(0.0); + + for(r=p+1; r<q; r++) + { + h = covarianceMatrix[p][r]; + + g = covarianceMatrix[r][q]; + + covarianceMatrix[p][r] = (double)(c*h - s*g); + + covarianceMatrix[r][q] = (double)(c*g + s*h); + } + + covarianceMatrix[q][q] += (double)(t*apq); + + for(r = q+1; r<rank; r++) + { + h = covarianceMatrix[p][r]; + + g = covarianceMatrix[q][r]; + + covarianceMatrix[p][r] = (double)(c*h - s*g); + + covarianceMatrix[q][r] = (double)(c*g + s*h); + } + + for(r = 0; r<rank ; r++) + { + h = eigenVectorMatrix[r][p]; + + g = eigenVectorMatrix[r][q]; + + eigenVectorMatrix[r][p] = (double)(c*h - s*g); + + eigenVectorMatrix[r][q] = (double)(c*g + s*h); + } + } + else + { + covarianceMatrix[p][q] = 0; + } + } + } + + } + + + + for(r=0;r<rank;r++) + { + eigenValueVec[r] = covarianceMatrix[r][r]; + } + + double temp; + + for(p = 0; p<rank-1; p++) + { + for(q = p+1; q<rank; q++) + { + if(fabs(eigenValueVec[p]) < fabs(eigenValueVec[q])) + { + for(r = 0; r<rank; r++) + { + temp = eigenVectorMatrix[r][p]; + + eigenVectorMatrix[r][p] = eigenVectorMatrix[r][q]; + + eigenVectorMatrix[r][q] = temp; + + } + + temp = eigenValueVec[p]; + + eigenValueVec[p] = eigenValueVec[q]; + + eigenValueVec[q] = temp; + + } + } + } + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::computeEigenVectors()" << endl; + + return SUCCESS; + +} + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : initializeFeatureExtractorInstance +* DESCRIPTION : This method get the Instance of the Feature Extractor +* from LTKShapeFeatureExtractorFactory +* ARGUMENTS : +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ +int ActiveDTWShapeRecognizer::initializeFeatureExtractorInstance(const LTKControlInfo& controlInfo) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::initializeFeatureExtractorInstance()" << endl; + + + LTKShapeFeatureExtractorFactory factory; + int errorCode = factory.createFeatureExtractor(m_featureExtractorName, + m_lipiRootPath, + m_lipiLibPath, + &m_libHandlerFE, + controlInfo, + &m_ptrFeatureExtractor); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EFTR_EXTR_NOT_EXIST << " " << + " ActiveDTWShapeRecognizer::initializeFeatureExtractorInstance()" << endl; + LTKReturnError(errorCode); + } + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::initializeFeatureExtractorInstance()" << endl; + + return SUCCESS; +} + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : deleteFeatureExtractorInstance +* DESCRIPTION : This method unloads the Feature extractor instance +* ARGUMENTS : none +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ +int ActiveDTWShapeRecognizer::deleteFeatureExtractorInstance() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::deleteFeatureExtractorInstance()" << endl; + + if (m_ptrFeatureExtractor != NULL) + { + typedef int (*FN_PTR_DELETE_SHAPE_FEATURE_EXTRACTOR)(LTKShapeFeatureExtractor *obj); + FN_PTR_DELETE_SHAPE_FEATURE_EXTRACTOR deleteFeatureExtractor; + void * functionHandle = NULL; + + // Map createpreprocessor and deletePreprocessor functions + int returnVal = m_OSUtilPtr->getFunctionAddress(m_libHandlerFE, + DELETE_SHAPE_FEATURE_EXTRACTOR, + &functionHandle); + + // Could not map the createLipiPreprocessor function from the DLL + if(returnVal != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << + "Error: "<< EDLL_FUNC_ADDRESS_DELETE_FEATEXT << " " << + getErrorMessage(EDLL_FUNC_ADDRESS_DELETE_FEATEXT) << + " ActiveDTWShapeRecognizer::deleteFeatureExtractorInstance()" << endl; + + LTKReturnError(EDLL_FUNC_ADDRESS_DELETE_FEATEXT); + } + + deleteFeatureExtractor = (FN_PTR_DELETE_SHAPE_FEATURE_EXTRACTOR)functionHandle; + + deleteFeatureExtractor(m_ptrFeatureExtractor); + + m_ptrFeatureExtractor = NULL; + + // unload feature extractor dll + if(m_libHandlerFE != NULL) + { + //Unload the DLL + m_OSUtilPtr->unloadSharedLib(m_libHandlerFE); + m_libHandlerFE = NULL; + + } + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::deleteFeatureExtractorInstance()" << endl; + + return SUCCESS; +} + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : updateHeaderWithAlgoInfo +* DESCRIPTION : This method will Update the Header information for the MDT file +* ARGUMENTS : +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ +void ActiveDTWShapeRecognizer::updateHeaderWithAlgoInfo() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::updateHeaderWithAlgoInfo()" << endl; + + m_headerInfo[RECVERSION] = m_currentVersion; + string algoName = ACTIVEDTW; + m_headerInfo[RECNAME] = algoName; + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::updateHeaderWithAlgoInfo()" << endl; + +} + + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getDistance +* DESCRIPTION : +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ +void ActiveDTWShapeRecognizer::getDistance(const LTKShapeFeaturePtr& f1, + const LTKShapeFeaturePtr& f2, + float& distance) +{ + f1->getDistance(f2, distance); +} + + + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getFeaturesFromTraceGroup +* DESCRIPTION : 1. PreProcess 2. Extract Features 3.Add to PrototypeSet +* 4. Add to MDT +* ARGUMENTS : +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ + +int ActiveDTWShapeRecognizer::extractFeatVecFromTraceGroup(const LTKTraceGroup& inTraceGroup, + vector<LTKShapeFeaturePtr>& featureVec) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::extractFeatVecFromTraceGroup()" << endl; + + //TraceGroup after Preprocessing + LTKTraceGroup preprocessedTraceGroup; + + //Check for empty traces in inTraceGroup + if(inTraceGroup.containsAnyEmptyTrace()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_TRACE << " " << + getErrorMessage(EEMPTY_TRACE) << + " ActiveDTWShapeRecognizer::extractFeatVecFromTraceGroup()" << endl; + LTKReturnError(EEMPTY_TRACE); + } + + //Preprocess the inTraceGroup + int errorCode = preprocess(inTraceGroup, preprocessedTraceGroup); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::extractFeatVecFromTraceGroup()" << endl; + LTKReturnError(errorCode); + } + + errorCode = m_ptrFeatureExtractor->extractFeatures(preprocessedTraceGroup, + featureVec); + + if (errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::extractFeatVecFromTraceGroup()" << endl; + LTKReturnError(errorCode); + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + <<"Exiting ActiveDTWShapeRecognizer::extractFeatVecFromTraceGroup()" << endl; + return SUCCESS; +} + +/****************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : getTraceGroup +* DESCRIPTION : Returns the tracegroups of the shape +* For singletons it returns the tracegroups from the feature vector +* For clusters it returns the tracegroup of the cluster mean +* ARGUMENTS : INPUT: +shapeID - class whose trace groups are to be returned +numberOfTraceGroups - maximum number of trace groups to be returned +: OUTPUT +outTraceGroups - tracegroups of the class +* RETURNS : +* NOTES : +* CHANGE HISTROY +* Author Date Description +******************************************************************************/ + +int ActiveDTWShapeRecognizer::getTraceGroups(int shapeID, int numberOfTraceGroups, + vector<LTKTraceGroup> &outTraceGroups) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + <<"Entering ActiveDTWShapeRecognizer::getTraceGroups" + <<endl; + + if(m_shapeIDNumPrototypesMap.find(shapeID) == m_shapeIDNumPrototypesMap.end()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EINVALID_SHAPEID << " " << + getErrorMessage(EINVALID_SHAPEID) << + " ActiveDTWShapeRecognizer::getTraceGroups()" << endl; + LTKReturnError(EINVALID_SHAPEID); + } + + if(m_shapeIDNumPrototypesMap[shapeID] < numberOfTraceGroups) + { + numberOfTraceGroups = m_shapeIDNumPrototypesMap[shapeID]; + LOG(LTKLogger::LTK_LOGLEVEL_INFO) + << "Number of TraceGroup in PrototypeShapes is less than specified." + << "Returning all TraceGroups :" + << numberOfTraceGroups <<endl; + } + + vector<ActiveDTWShapeModel>::iterator prototypeShapesIter = m_prototypeShapes.begin(); + int counter =0; + vector<ActiveDTWClusterModel> clusterModelVector; + shapeMatrix singletonVector; + + for(;prototypeShapesIter!=m_prototypeShapes.end();) + { + int currentShapeId = (*prototypeShapesIter).getShapeId(); + + if(currentShapeId == shapeID) + { + LTKTraceGroup traceGroup; + + clusterModelVector = (*prototypeShapesIter).getClusterModelVector(); + singletonVector = (*prototypeShapesIter).getSingletonVector(); + + int clusterModelVectorSize = clusterModelVector.size(); + int singletonVectorSize = singletonVector.size(); + + if(singletonVectorSize > 0) + { + //convert singletons into tracegroups + for(int i = 0; i < singletonVectorSize; i++) + { + //converting the featureVector to traceGroup + int errorCode = m_ptrFeatureExtractor->convertFeatVecToTraceGroup( + singletonVector[i],traceGroup); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::getTraceGroups()" << endl; + + LTKReturnError(errorCode); + } + + outTraceGroups.push_back(traceGroup); + counter++; + if(counter==numberOfTraceGroups) + break; + } + } + + + if(clusterModelVectorSize > 0) + { + //converting all the cluster means into traceGroups + for(int i = 0; i < clusterModelVectorSize; i++) + { + doubleVector clusterMean = clusterModelVector[i].getClusterMean(); + + //converting the doubleVector to featureVector + vector<LTKShapeFeaturePtr> shapeFeatureVec; + + int errorCode = convertDoubleToFeatureVector(shapeFeatureVec,clusterMean); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::getTraceGroups()" << endl; + + LTKReturnError(errorCode); + } + + //converting the featureVector to traceGroup + errorCode = m_ptrFeatureExtractor->convertFeatVecToTraceGroup( + shapeFeatureVec,traceGroup); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::getTraceGroups()" << endl; + + LTKReturnError(errorCode); + } + + outTraceGroups.push_back(traceGroup); + clusterMean.clear(); + counter++; + if(counter==numberOfTraceGroups) + break; + } + } + } + prototypeShapesIter++; + } + + //clearing vectors + clusterModelVector.clear(); + singletonVector.clear(); + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) + <<"Exiting ActiveDTWShapeRecognizer::getTraceGroups" + <<endl; + return SUCCESS; +} + +/*********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : initializePreprocessor +* DESCRIPTION : This method is used to initialize the PreProcessor +* ARGUMENTS : preprocDLLPath : string : Holds the Path of the Preprocessor DLL, +* returnStatus : int : Holds SUCCESS or Error Values, if occurs +* RETURNS : preprocessor instance +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::initializePreprocessor(const LTKControlInfo& controlInfo, + LTKPreprocessorInterface** preprocInstance) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::initializePreprocessor()" << endl; + + FN_PTR_CREATELTKLIPIPREPROCESSOR createLTKLipiPreProcessor = NULL; + + int errorCode; + + // Load the DLL with path=preprocDLLPath + void* functionHandle = NULL; + + int returnVal = m_OSUtilPtr->loadSharedLib(controlInfo.lipiLib, PREPROC, &m_libHandler); + + if(returnVal != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< ELOAD_PREPROC_DLL << " " << + getErrorMessage(ELOAD_PREPROC_DLL) << + " ActiveDTWShapeRecognizer::initializePreprocessor()" << endl; + LTKReturnError(ELOAD_PREPROC_DLL); + } + + // Map createpreprocessor and deletePreprocessor functions + returnVal = m_OSUtilPtr->getFunctionAddress(m_libHandler, + CREATEPREPROCINST, + &functionHandle); + // Could not map the createLipiPreprocessor function from the DLL + if(returnVal != SUCCESS) + { + //Unload the dll + unloadPreprocessorDLL(); + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EDLL_FUNC_ADDRESS_CREATE << " " << + getErrorMessage(EDLL_FUNC_ADDRESS_CREATE) << + " ActiveDTWShapeRecognizer::initializePreprocessor()" << endl; + + LTKReturnError(EDLL_FUNC_ADDRESS_CREATE); + } + + createLTKLipiPreProcessor = (FN_PTR_CREATELTKLIPIPREPROCESSOR)functionHandle; + + functionHandle = NULL; + + // Map createpreprocessor and deletePreprocessor functions + returnVal = m_OSUtilPtr->getFunctionAddress(m_libHandler, + DESTROYPREPROCINST, + &functionHandle); + + // Could not map the createLipiPreprocessor function from the DLL + if(returnVal != SUCCESS) + { + //Unload the dll + unloadPreprocessorDLL(); + + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EDLL_FUNC_ADDRESS_CREATE << " " << + getErrorMessage(EDLL_FUNC_ADDRESS_CREATE) << + " ActiveDTWShapeRecognizer::initializePreprocessor()" << endl; + LTKReturnError(EDLL_FUNC_ADDRESS_CREATE); + } + + m_deleteLTKLipiPreProcessor = (FN_PTR_DELETELTKLIPIPREPROCESSOR)functionHandle; + + // Create preprocessor instance + errorCode = createLTKLipiPreProcessor(controlInfo, preprocInstance); + + if(errorCode!=SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::initializePreprocessor()" << endl; + LTKReturnError(errorCode); + } + + // Could not create a LTKLipiPreProcessor + if(*preprocInstance == NULL) + { + // Unload the DLL + unloadPreprocessorDLL(); + + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< ECREATE_PREPROC << " " << + getErrorMessage(ECREATE_PREPROC) << + " ActiveDTWShapeRecognizer::initializePreprocessor()" << endl; + LTKReturnError(ECREATE_PREPROC); + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::initializePreprocessor()" << endl; + + return SUCCESS; + + +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : deletePreprocessor +* DESCRIPTION : This method is used to deletes the PreProcessor instance +* ARGUMENTS : ptrPreprocInstance : Holds the pointer to the LTKPreprocessorInterface +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ + +//int ActiveDTWShapeRecognizer::deletePreprocessor(LTKPreprocessorInterface *ptrPreprocInstance) +int ActiveDTWShapeRecognizer::deletePreprocessor() +{ + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::deletePreprocessor()" << endl; + + //deleting the preprocessor instance + if(m_ptrPreproc != NULL) + { + m_deleteLTKLipiPreProcessor(m_ptrPreproc); + m_ptrPreproc = NULL; + } + + //Unload the dll + int returnStatus = unloadPreprocessorDLL(); + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Error: " << + getErrorMessage(returnStatus) << + " ActiveDTWShapeRecognizer::deletePreprocessor()" << endl; + LTKReturnError(returnStatus); + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::deletePreprocessor()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : unloadPreprocessorDLL +* DESCRIPTION : This method is used to Unloads the preprocessor DLL. +* ARGUMENTS : none +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::unloadPreprocessorDLL() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::unloadPreprocessorDLL()" << endl; + + //Check the preprocessor DLL was loaded already + if(m_libHandler != NULL) + { + //Unload the DLL + m_OSUtilPtr->unloadSharedLib(m_libHandler); + m_libHandler = NULL; + } + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::unloadPreprocessorDLL()" << endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : findOptimalDeformation +* DESCRIPTION : This method computes the parameters required to construct the optimal +deformation of each cluster that is closest to the test sample +* ARGUMENTS : INPUT +eigenValues doubleVector (eigenValues of cluster) +eigenVector double2DVector (eigenVectors of cluster) +clusterMean doubleVector (mean of cluster) +testSample doubleVector (test sample) +:OUTPUT +deformationParameters doubleVector (deformation parameters) +* +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ +int ActiveDTWShapeRecognizer::findOptimalDeformation(doubleVector& deformationParameters,doubleVector& eigenValues, double2DVector& eigenVector, + doubleVector& clusterMean, doubleVector& testSample) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::findOptimalDeformation()" << endl; + + if(eigenValues.empty()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_EIGENVALUES << " " << + getErrorMessage(EEMPTY_EIGENVALUES) << + " ActiveDTWShapeRecognizer::findOptimalDeformation()" << endl; + + LTKReturnError(EEMPTY_EIGENVALUES); + } + + if(eigenVector.empty()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_EIGENVECTORS << " " << + getErrorMessage(EEMPTY_EIGENVECTORS) << + " ActiveDTWShapeRecognizer::findOptimalDeformation()" << endl; + + LTKReturnError(EEMPTY_EIGENVECTORS); + } + + if(clusterMean.empty()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_CLUSTERMEAN << " " << + getErrorMessage(EEMPTY_CLUSTERMEAN) << + " ActiveDTWShapeRecognizer::findOptimalDeformation()" << endl; + + LTKReturnError(EEMPTY_CLUSTERMEAN); + } + + if(eigenValues.size() != eigenVector.size()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< ENUM_EIGVALUES_NOTEQUALTO_NUM_EIGVECTORS << " " << + getErrorMessage(ENUM_EIGVALUES_NOTEQUALTO_NUM_EIGVECTORS) << + " ActiveDTWShapeRecognizer::findOptimalDeformation()" << endl; + + LTKReturnError(ENUM_EIGVALUES_NOTEQUALTO_NUM_EIGVECTORS); + } + + + doubleVector diffVec; + doubleVector linearConstant; + doubleVector tempDoubleVec; + doubleVector lowerBounds; + doubleVector upperBounds; + double tempSum; + + int n ; + + int i = 0; + + + + /***************CALCULATING PARAMETERS***********************/ + /**CALCULATING THE DIFFERENCE VECTOR**/ + diffVec.assign(clusterMean.size(),0.0); + + for(i = 0; i < diffVec.size(); i++) + diffVec[i] = testSample[i] - clusterMean[i]; + + + /**CALCULATING THE LINEAR CONSTANT TERM**/ + //linearConstant is calculated as: + //linearConstant = eigVec*diffVec + double2DVector::iterator iStart = eigenVector.begin(); + double2DVector::iterator iEnd = eigenVector.end(); + + for(;iStart != iEnd;++iStart) + { + tempDoubleVec = (*iStart); + + tempSum = 0.0; + for(i = 0; i < tempDoubleVec.size(); i++ ) + { + + tempSum += (tempDoubleVec[i] * diffVec[i]); + } + + linearConstant.push_back(tempSum); + } + + //problem dimension + n = eigenVector.size(); + + + + double tempBounds; + + for( i = 0; i < n; i++) + { + + tempBounds = sqrt(eigenValues[i] * m_eigenSpreadValue); + lowerBounds.push_back((-1) * tempBounds); + upperBounds.push_back(tempBounds); + } + + /**OPTIMIZATION PROCEDURE**/ + for( i = 0; i < n; i++) + { + if(linearConstant[i] >= lowerBounds[i] && linearConstant[i] <= upperBounds[i]) + deformationParameters[i] = linearConstant[i]; + else + { + if(linearConstant[i] < lowerBounds[i]) + deformationParameters[i] = lowerBounds[i]; + else + deformationParameters[i] = upperBounds[i]; + } + } + + //clearing vectors + linearConstant.clear(); + lowerBounds.clear(); + upperBounds.clear(); + diffVec.clear(); + tempDoubleVec.clear(); + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::findOptimalDeformation()" << endl; + return SUCCESS; +}; + +/************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : validatePreprocParameters +* DESCRIPTION : This method is used to validate the preproc parameters with +* mdt header values +* ARGUMENTS : none +* RETURNS : none +* NOTES : +* CHANGE HISTROY +* Author Date Description +****************************************************************************/ +int ActiveDTWShapeRecognizer::validatePreprocParameters(stringStringMap& headerSequence) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::validatePreprocParameters()" << endl; + + + string tempStrVar = ""; + string headerValue = ""; + int headerValueInt = 0; + float headerValueFloat = 0.0f; + int tempIntegerValue = 0; + float tempFloatValue = 0.0f; + + //preproc sequence + string mdtPreprocSeqn = headerSequence[PREPROC_SEQ]; + if(LTKSTRCMP(m_preProcSeqn.c_str(), mdtPreprocSeqn.c_str()) != 0 && + LTKSTRCMP("NA", mdtPreprocSeqn.c_str()) != 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of preprocSeqn in config file ("<< + m_preProcSeqn <<") does not match with the value in MDT file ("<< + mdtPreprocSeqn <<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + + + + //ResampTraceDimension + headerValue = ""; + if(LTKSTRCMP("NA", headerSequence[TRACE_DIM].c_str()) != 0) + { + headerValueInt = atoi(headerSequence[TRACE_DIM].c_str()); + tempIntegerValue = m_ptrPreproc->getTraceDimension(); + + if(headerValueInt != tempIntegerValue ) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of TraceDimension in config file ("<< + tempIntegerValue<<") does not match with the value in MDT file ("<< + headerValueInt <<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + } + + + // preserve aspect ratio + bool preProcPreserveAspectRatio = m_ptrPreproc->getPreserveAspectRatio(); + tempStrVar = "false"; + if (preProcPreserveAspectRatio == true) + { + tempStrVar = "true"; + } + + if(LTKSTRCMP((headerSequence[PRESER_ASP_RATIO]).c_str(), tempStrVar.c_str()) != 0 && + LTKSTRCMP((headerSequence[PRESER_ASP_RATIO]).c_str(), "NA") != 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of preProcPreserveAspectRatio in config file ("<< + tempStrVar<<") does not match with the value in MDT file ("<< + headerSequence[PRESER_ASP_RATIO] <<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + + + //NormPreserveRelativeYPosition + bool preProcNormPreserveRelativeYPosition = m_ptrPreproc->getPreserveRealtiveYPosition(); + tempStrVar = "false"; + if (preProcNormPreserveRelativeYPosition == true) + { + tempStrVar = "true"; + } + + if(LTKSTRCMP((headerSequence[PRESER_REL_Y_POS]).c_str(), tempStrVar.c_str()) != 0 && + LTKSTRCMP((headerSequence[PRESER_REL_Y_POS]).c_str(), "NA") != 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of preProcNormPreserveRelativeYPosition in config file ("<< + tempStrVar<<") does not match with the value in MDT file ("<< + headerSequence[PRESER_REL_Y_POS] <<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + + + + // NormPreserveAspectRatioThreshold + tempFloatValue = m_ptrPreproc->getAspectRatioThreshold(); + if(LTKSTRCMP((headerSequence[ASP_RATIO_THRES]).c_str(), "NA") != 0) + { + headerValueFloat = LTKStringUtil::convertStringToFloat(headerSequence[ASP_RATIO_THRES]); + + if(headerValueFloat != tempFloatValue) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of preProcPreserveAspectRatioThreshold in config file ("<< + tempFloatValue<<") does not match with the value in MDT file ("<< + headerValueFloat <<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + } + + + + // NormLineWidthThreshold + if(LTKSTRCMP((headerSequence[DOT_SIZE_THRES]).c_str(), "NA") != 0) + { + headerValueFloat = LTKStringUtil::convertStringToFloat(headerSequence[DOT_SIZE_THRES]); + tempFloatValue = m_ptrPreproc->getSizeThreshold(); + + if(headerValueFloat != tempFloatValue) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of preProcNormLineWidthThreshold in config file ("<< + tempFloatValue<<") does not match with the value in MDT file ("<< + headerValueFloat <<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + } + + + // NormDotSizeThreshold + if(LTKSTRCMP((headerSequence[DOT_THRES]).c_str(), "NA") != 0) + { + headerValueFloat = LTKStringUtil::convertStringToFloat(headerSequence[DOT_THRES]); + tempFloatValue = m_ptrPreproc->getDotThreshold(); + + if(headerValueFloat != tempFloatValue) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of preProcNormDotSizeThreshold in config file ("<< + tempFloatValue<<") does not match with the value in MDT file ("<< + headerValueFloat <<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + } + + + + //ResampPointAllocation + tempStrVar = ""; + tempStrVar = m_ptrPreproc->getResamplingMethod(); + if(LTKSTRCMP((headerSequence[RESAMP_POINT_ALLOC]).c_str(), tempStrVar.c_str()) != 0 && + LTKSTRCMP((headerSequence[RESAMP_POINT_ALLOC]).c_str(), "NA") != 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of preProcResampPointAllocation in config file ("<< + tempStrVar<<") does not match with the value in MDT file ("<< + headerSequence[RESAMP_POINT_ALLOC] <<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + + + //SmoothWindowSize + if(LTKSTRCMP((headerSequence[SMOOTH_WIND_SIZE]).c_str(), "NA") != 0) + { + headerValueInt = atoi(headerSequence[SMOOTH_WIND_SIZE].c_str()); + tempIntegerValue = m_ptrPreproc->getFilterLength(); + + if(headerValueInt != tempIntegerValue) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<< ECONFIG_MDT_MISMATCH << " " << + "Value of preProcSmoothWindowSize in config file ("<< + tempIntegerValue<<") does not match with the value in MDT file ("<< + headerValueInt <<")"<< + " ActiveDTWShapeRecognizer::loadModelData()" << endl; + LTKReturnError(ECONFIG_MDT_MISMATCH); + } + } + + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::validatePreprocParameters()" << endl; + return SUCCESS; + +} + + +/********************************************************************************************* +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : computeEigenVectorsForLargeDimension +* DESCRIPTION : This method computes the eigen values and eigen vectors for larger +covariance matrices of large dimension using the eigen value and +eigen vectors of the smaller covariance matrix +* ARGUMENTS :INPUT +meanCorrectedData double2DVector +-- used for constructing the smaller covariance matrix +covarianceMatrix double2DVector +-- this is the larger covariance matrix whose eigen values and +eigen vectors are to be computed +:OUTPUT +eigenValues doubleVector +-- eigenValues of the larger covarianceMatrix +eigenVectors double2DVector +-- eigenVectors of the larger covarianceMatrix +* +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +* NOTES : This based on a paper implementation +*************************************************************************************/ +int ActiveDTWShapeRecognizer::computeEigenVectorsForLargeDimension(double2DVector& meanCorrectedData,double2DVector& covarianceMatrix, + double2DVector& eigenVector,doubleVector& eigenValues) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::computeEigenVectorsForLargeDimension()" << endl; + + if(meanCorrectedData.empty()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_MEANCORRECTEDDATA << " " << + getErrorMessage(EEMPTY_MEANCORRECTEDDATA) << + " ActiveDTWShapeRecognizer::computeEigenVectorsForLargeDimension()" << endl; + + LTKReturnError(EEMPTY_MEANCORRECTEDDATA); + } + + if(covarianceMatrix.empty()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_COVARIANCEMATRIX << " " << + getErrorMessage(EEMPTY_COVARIANCEMATRIX) << + " ActiveDTWShapeRecognizer::computeEigenVectorsForLargeDimension()" << endl; + + LTKReturnError(EEMPTY_COVARIANCEMATRIX); + } + + + //covarianceSmall = A(transpose) * A + double2DVector covarianceSmall; + + doubleVector tempVector; + + //eigen values and eigen vectors of A(transpose) * A + double2DVector eigVecMat; + doubleVector eigValVec; + + //number of iterations for computing eigen vectors + int nrot = 0; + + int meanCorrectedDataSize = meanCorrectedData.size(); + int rowSize = meanCorrectedData[0].size(); + + tempVector.assign(meanCorrectedDataSize,0.0); + covarianceSmall.assign(meanCorrectedDataSize,tempVector); + tempVector.clear(); + + int i = 0; + int j = 0; + + //calculating A(transpose)* A + for(i = 0; i < meanCorrectedDataSize; i++) + { + for(j = 0;j < meanCorrectedDataSize; j++) + { + if(i <= j) + { + for(int k = 0; k < rowSize; k++) + { + covarianceSmall[i][j] += meanCorrectedData[i][k]*meanCorrectedData[j][k]; + } + covarianceSmall[i][j] = covarianceSmall[i][j] /(meanCorrectedDataSize -1); + } + else + { + covarianceSmall[i][j] = covarianceSmall[j][i]; + } + } + } + + + //allocating memory for eigVecMat + tempVector.assign(meanCorrectedDataSize,0.0); + eigVecMat.assign(meanCorrectedDataSize,tempVector); + tempVector.clear(); + + + //computing the eigen vectors of A(transpose)*A + + + int errorCode = computeEigenVectors(covarianceSmall,covarianceSmall.size(), + eigValVec,eigVecMat,nrot); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::trainFromListFile()" << endl; + LTKReturnError(errorCode); + } + + + + + + /**CALCULATING EIGEN ENERGY **/ + double totalEigenEnergy = 0.0; + double currentEigenEnergy = 0.0; + int numEigenVectors = 0; + + int eigenValSize = eigValVec.size(); + for( i = 0; i < eigenValSize; i++) + totalEigenEnergy += eigValVec[i]; + + /**DETERMINING NUMBER OF EIGEN VECTORS**/ + while(currentEigenEnergy <= ((m_percentEigenEnergy*totalEigenEnergy)/100) && numEigenVectors < eigenValSize) + currentEigenEnergy += eigValVec[numEigenVectors++]; + + /**COMPUTING THE EIGEN VECTORS OF THE LARGER COVARIANCE MATRIX AS (A * EIGENVECTOR) **/ + + tempVector.assign(numEigenVectors,0.0); + eigenVector.assign(rowSize,tempVector); + tempVector.clear(); + + for( i = 0; i < rowSize; i++) + { + for(int j = 0; j < numEigenVectors; j++) + { + for(int k = 0; k < meanCorrectedDataSize; k++) + { + eigenVector[i][j] += meanCorrectedData[k][i] * eigVecMat[k][j]; + } + } + } + + //calculating the magnitude of each eigenVectors + doubleVector magnitudeVector; + for( i = 0; i < numEigenVectors; i++) + { + double tempMagnitude = 0; + for(j = 0; j < rowSize; j++) + tempMagnitude += (eigenVector[j][i] * eigenVector[j][i]); + double sqrtMagnitude = sqrt(tempMagnitude); + magnitudeVector.push_back(sqrtMagnitude); + } + + + //normalizing eigenVectors + for( i = 0; i < numEigenVectors; i++) + { + for(j = 0; j < rowSize; j++) + eigenVector[j][i] = (eigenVector[j][i]/magnitudeVector[i]); + } + magnitudeVector.clear(); + + //selecting the corresponding eigen values + for( i = 0; i < numEigenVectors; i++) + eigenValues.push_back(eigValVec[i]); + + eigVecMat.clear(); + eigValVec.clear(); + covarianceSmall.clear(); + + + return SUCCESS; + + +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : convertDoubleToFeatureVector +* DESCRIPTION : This method converts the double Vector (flatenned version of the feature vector) +to the vector<LTKShapeFeaturePtr> form +* ARGUMENTS : INPUT +* featureVec doubleVector +:OUTPUT +shapeFeatureVec vector<LTKShapeFeaturePtr> +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no erros +*************************************************************************************/ +int ActiveDTWShapeRecognizer::convertDoubleToFeatureVector(vector<LTKShapeFeaturePtr>& shapeFeatureVec,doubleVector& featureVec) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::convertDoubleToFeatureVector" << endl; + + LTKShapeFeaturePtr shapeFeature; + int featureVectorSize = featureVec.size(); + int featureDimension; + floatVector tempFeature; + + for(int i = 0; i < featureVectorSize;) + { + shapeFeature = m_ptrFeatureExtractor->getShapeFeatureInstance(); + featureDimension = shapeFeature->getFeatureDimension(); + + + for(int j = 0; j < featureDimension; j++) + { + tempFeature.push_back((float)featureVec[i]); + i++; + } + + + if (shapeFeature->initialize(tempFeature) != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_INPUT_FORMAT << " " << + "Number of features extracted from a trace is not correct"<< + " ActiveDTWShapeRecognizer::convertDoubleToFeatureVector" << endl; + + LTKReturnError(EINVALID_INPUT_FORMAT); + } + shapeFeatureVec.push_back(shapeFeature); + + tempFeature.clear(); + } + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::convertDoubleToFeatureVector" << endl; + + return SUCCESS; + +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : adapt +* DESCRIPTION : adapt recent recognized sample +* ARGUMENTS : shapeID : True shapeID of sample +* RETURNS : Success : If sample was adapted successfully +* Failure : Returns Error Code +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::adapt(int shapeId) +{ + try{ + LOG(LTKLogger::LTK_LOGLEVEL_INFO) + << "Enter ActiveDTWShapeRecognizer::adapt()"<<endl; + + //check if shapeId has already seen by classifier else add shapeId + if(m_shapeIDNumPrototypesMap.find(shapeId) == m_shapeIDNumPrototypesMap.end()) + { + + LTKReturnError(EINVALID_SHAPEID); + } + + //Adaptation Code + LTKAdapt* adaptObj = LTKAdapt::getInstance(this); + + int nErrorCode; + nErrorCode = adaptObj->adapt(shapeId); + if(nErrorCode !=0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) + << "Error during ActiveDTWShapeRecognizer::adapt()"<<endl; + LTKReturnError(nErrorCode); + } + + //Clear Variables cached + m_neighborInfoVec.clear(); + m_vecRecoResult.clear(); + + } + catch(...) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) + << "Error during ActiveDTWShapeRecognizer::adapt()"<<endl; + return FAILURE; + } + + LOG(LTKLogger::LTK_LOGLEVEL_INFO) + << "Exit ActiveDTWShapeRecognizer::adapt()"<<endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : adapt +* DESCRIPTION : adapt sample passed as argument +* ARGUMENTS : sampleTraceGroup : TraceGroup of sample to be adapted +* shapeID : True shapeID of sample +* RETURNS : Success : If sample was adapted successfully +* Failure : Returns Error Code +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::adapt(const LTKTraceGroup& sampleTraceGroup, int shapeId ) +{ + LOG(LTKLogger::LTK_LOGLEVEL_INFO) + << "Enter ActiveDTWShapeRecognizer::Adapt()"<<endl; + + int errorCode; + + if(shapeId < 0) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) + << "ActiveDTWShapeRecognizer::Adapt(): Invalid shapeId"<< endl; + LTKReturnError(EINVALID_SHAPEID); + } + + //check if shapeId has already seen by classifier else add shapeId + if(m_shapeIDNumPrototypesMap.find(shapeId) == m_shapeIDNumPrototypesMap.end()) + { + //add class + errorCode = addClass(sampleTraceGroup, shapeId); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) + << "Error during call to recognize in ActiveDTWShapeRecognizer::Adapt()"<<endl; + LTKReturnError(errorCode); + } + } + else + { + //recognize and adapt + vector<int> vecSubSet; + vector<LTKShapeRecoResult> vecRecoResult; + LTKScreenContext objScreenContext; + + errorCode = recognize(sampleTraceGroup,objScreenContext, + vecSubSet,CONF_THRESHOLD_FILTER_OFF, + NN_DEF_RECO_NUM_CHOICES,vecRecoResult); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) + << "Error during call to recognize in ActiveDTWShapeRecognizer::Adapt()"<<endl; + LTKReturnError(errorCode); + } + + errorCode = adapt(shapeId); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) + << "Error during call to recognize in ActiveDTWShapeRecognizer::Adapt()"<<endl; + LTKReturnError(errorCode); + } + + } + + + LOG(LTKLogger::LTK_LOGLEVEL_INFO) + << "Exit ActiveDTWShapeRecognizer::Adapt()"<<endl; + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : deleteAdaptInstance +* DESCRIPTION : delete AdaptInstance +* ARGUMENTS : +* RETURNS : None +* NOTES : +* CHANGE HISTROY +* Author Date Description +*************************************************************************************/ +int ActiveDTWShapeRecognizer::deleteAdaptInstance() +{ + //Implemented as deleteAdaptInstance is called by ~NNShapeRecognizer + //and adaptObj object is not available in NN.cpp + + LTKAdapt *adaptInstance = LTKAdapt::getInstance(this); + if(adaptInstance) + { + adaptInstance->deleteInstance(); + } + + return SUCCESS; +} + +/********************************************************************************** +* AUTHOR ; S Anand +* DATE : 3-MAR-2009 +* NAME : writePrototypeShapesToMDTFile +* DESCRIPTION : Flushes the prototype shapes data to activedtw.mdt file +* ARGUMENTS : +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ + +int ActiveDTWShapeRecognizer::writePrototypeShapesToMDTFile() +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::writePrototypeShapesToMDTFile()" << endl; + + int errorCode = SUCCESS; + + //Flush to MDT only after m_MDTUpdateFreq modifications + m_prototypeSetModifyCount++; + + if(m_prototypeSetModifyCount == m_MDTUpdateFreq) + { + m_prototypeSetModifyCount = 0; + + ofstream mdtFileHandle; + + //Open the Model data file for writing mode + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + mdtFileHandle.open(m_activedtwMDTFilePath.c_str(), ios::out); + } + else + { + mdtFileHandle.open(m_activedtwMDTFilePath.c_str(),ios::out|ios::binary); + } + + //Return error if unable to open the Model data file + if(!mdtFileHandle) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EMODEL_DATA_FILE_OPEN << " " << + getErrorMessage(EMODEL_DATA_FILE_OPEN) << + " ActiveDTWShapeRecognizer::writePrototypeShapesToMDTFile()" << endl; + + LTKReturnError(EMODEL_DATA_FILE_OPEN); + } + + //write the number of shapes to MDT file + + if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII ) + { + // 0 represents dynamic + mdtFileHandle << 0 << endl; + } + else + { + int numShapes = 0; + mdtFileHandle.write((char*) &numShapes, sizeof(unsigned short)); + } + + int prototypeShapesSize = m_prototypeShapes.size(); + + for(int i = 0; i < prototypeShapesSize; i++) + { + errorCode = appendShapeModelToMDTFile(m_prototypeShapes[i],mdtFileHandle); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::writePrototypeShapesToMDTFile()" << endl; + LTKReturnError(errorCode); + } + } + + mdtFileHandle.close(); + + //Updating the Header Information + updateHeaderWithAlgoInfo(); + + //Adding header information and checksum generation + string strModelDataHeaderInfoFile = ""; + LTKCheckSumGenerate cheSumGen; + + errorCode = cheSumGen.addHeaderInfo( + strModelDataHeaderInfoFile, + m_activedtwMDTFilePath, + m_headerInfo); + + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::writePrototypeSetToMDTFile()" << endl; + + LTKReturnError(errorCode); + } + } + + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::writePrototypeShapesToMDTFile()" << endl; + + return SUCCESS; +} +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : addClass +* DESCRIPTION : Adds a new trace group as a class +* ARGUMENTS : INPUT +sampleTraceGroup LTKTraceGroup +shapeID int +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ +int ActiveDTWShapeRecognizer::addClass(const LTKTraceGroup& sampleTraceGroup, int& shapeID) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::addClass()" << endl; + + int errorCode; + + //unless projecttype is dynamic we cannot add classes + if(!m_projectTypeDynamic) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EPROJ_NOT_DYNAMIC << " " << + "Not allowed to ADD shapes to a project with fixed number of shapes"<< + " ActiveDTWShapeRecognizer::addClass()" << endl; + + LTKReturnError(EPROJ_NOT_DYNAMIC); + } + + + //if the sample does not have a shape id, we assign it NEW_SHAPEID = -2 in runshaperecInternal + //then in the following module we determine the new shape id based on the existing shape ids + if(shapeID = NEW_SHAPEID) + { + int tempShapeID; + + if(m_shapeIDNumPrototypesMap.size() > 0) + { + map<int,int>::reverse_iterator m_shapeIDNumPrototypesMapIter; + m_shapeIDNumPrototypesMapIter = m_shapeIDNumPrototypesMap.rbegin(); + tempShapeID = m_shapeIDNumPrototypesMapIter->first; + shapeID = tempShapeID+1; + } + else + { + shapeID = LTK_START_SHAPEID; + } + + } + + vector<LTKShapeFeaturePtr> tempFeatureVec; + + errorCode = extractFeatVecFromTraceGroup(sampleTraceGroup,tempFeatureVec); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::addClass()" << endl; + LTKReturnError(errorCode); + } + + shapeMatrix newShapeMatrix; + + newShapeMatrix.push_back(tempFeatureVec); + + //add the feature vector as a singleton Vector + ActiveDTWShapeModel newShapeModel; + + + errorCode = newShapeModel.setShapeId(shapeID); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " "<< endl; + LTKReturnError(errorCode); + } + + newShapeModel.setSingletonVector(newShapeMatrix); + + if(m_prototypeShapes.empty()) + { + m_prototypeShapes.push_back(newShapeModel); + } + else + { + int prototypeShapesSize = m_prototypeShapes.size(); + int maxClassId = m_prototypeShapes[prototypeShapesSize - 1].getShapeId(); + + if(shapeID > maxClassId) + m_prototypeShapes.push_back(newShapeModel); + else + { + vector<ActiveDTWShapeModel>::iterator prototypeShapesIter = m_prototypeShapes.begin(); + + while(prototypeShapesIter != m_prototypeShapes.end()) + { + int currentShapeId = (*prototypeShapesIter).getShapeId(); + + if(currentShapeId > shapeID) + { + m_prototypeShapes.insert(prototypeShapesIter,newShapeModel); + break; + } + prototypeShapesIter++; + } + } + } + + //Update m_shapeIDNumPrototypesMap + m_shapeIDNumPrototypesMap[shapeID]= 1; + + //Update MDT File + errorCode = writePrototypeShapesToMDTFile(); + if(errorCode != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " << + " ActiveDTWShapeRecognizer::addClass()" << endl; + LTKReturnError(errorCode); + } + + //clearing vectors + tempFeatureVec.clear(); + newShapeMatrix.clear(); + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::addClass()" << endl; + + return SUCCESS; +} +/********************************************************************************** +* AUTHOR : S Anand +* DATE : 3-MAR-2009 +* NAME : deleteClass +* DESCRIPTION : Deletes the class with shapeID +* ARGUMENTS : INPUT +shapeID int +* RETURNS : integer Holds error value if occurs +* Holds SUCCESS if no errors +*************************************************************************************/ +int ActiveDTWShapeRecognizer::deleteClass(int shapeID) +{ + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " << + "ActiveDTWShapeRecognizer::deleteClass()" << endl; + + if(!m_projectTypeDynamic) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EPROJ_NOT_DYNAMIC << " " << + "Not allowed to delete shapes to a project with fixed number of Shapes"<< + " ActiveDTWShapeRecognizer::deleteClass()" << endl; + + LTKReturnError(EPROJ_NOT_DYNAMIC); + } + + //Validate Input Parameters - shapeID + if(m_shapeIDNumPrototypesMap.find(shapeID) ==m_shapeIDNumPrototypesMap.end()) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_SHAPEID << " " << + "shapeID is not valid"<< + " ActiveDTWShapeRecognizer::deleteClass()" << endl; + + LTKReturnError(EINVALID_SHAPEID); + } + + vector<ActiveDTWShapeModel>::iterator prototypeShapesIter; + + int prototypeShapesSize = m_prototypeShapes.size(); + int k = 0; + + for(int i = 0; i < prototypeShapesSize; i++) + { + prototypeShapesIter = m_prototypeShapes.begin() + k; + + int classId = (*prototypeShapesIter).getShapeId(); + + if(classId == shapeID) + { + vector<ActiveDTWClusterModel> currentClusterModelVector; + shapeMatrix currentSingletonVector; + + //clearing cluster Model and singleton vectors + currentClusterModelVector = (*prototypeShapesIter).getClusterModelVector(); + currentClusterModelVector.clear(); + (*prototypeShapesIter).setClusterModelVector(currentClusterModelVector); + + currentSingletonVector = (*prototypeShapesIter).getSingletonVector(); + currentSingletonVector.clear(); + (*prototypeShapesIter).setSingletonVector(currentSingletonVector); + + m_prototypeShapes.erase(prototypeShapesIter); + continue; + } + k++; + prototypeShapesIter++; + } + + //Update m_shapeIDNumPrototypesMap + m_shapeIDNumPrototypesMap.erase(shapeID); + + //Update MDT File + int returnStatus = writePrototypeShapesToMDTFile(); + + if(returnStatus != SUCCESS) + { + LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: " << returnStatus << " " << + "Exiting ActiveDTWShapeRecognizer::deleteClass" <<endl; + LTKReturnError(returnStatus); + } + + + LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " << + "ActiveDTWShapeRecognizer::deleteClass()" << endl; + + return SUCCESS; +} diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeRecognizer.h b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeRecognizer.h new file mode 100644 index 00000000..9459d5c7 --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/ActiveDTWShapeRecognizer.h @@ -0,0 +1,1203 @@ +/***************************************************************************************** +* Copyright (c) 2006 Hewlett-Packard Development Company, L.P. +* Permission is hereby granted, free of charge, to any person obtaining a copy of +* this software and associated documentation files (the "Software"), to deal in +* the Software without restriction, including without limitation the rights to use, +* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +* Software, and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies +* or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*****************************************************************************************/ +/************************************************************************ +* SVN MACROS +* +* $LastChangedDate: 2011-08-23 13:28:15 +0530 (Tue, 23 Aug 2011) $ +* $Revision: 857 $ +* $Author: jitender $ +* +************************************************************************/ +/********************************************************************************************* +* FILE DESCR: Definitions for ActiveDTW Shape Recognition module +* +* CONTENTS: +* +* AUTHOR: S Anand +* +* +* DATE:3-MAR-2009 +* CHANGE HISTORY: +* Author Date Description of change +***********************************************************************************************/ + + +#ifndef __ACTIVEDTWSHAPERECOGNIZER_H +#define __ACTIVEDTWSHAPERECOGNIZER_H + +#include "LTKInc.h" +#include "LTKTypes.h" +#include "LTKMacros.h" +#include "LTKShapeRecognizer.h" +#include "LTKShapeRecoUtil.h" +#include "LTKShapeSample.h" +#include "LTKCheckSumGenerate.h" +#include "LTKDynamicTimeWarping.h" +#include "ActiveDTWShapeModel.h" +#include "ActiveDTWAdapt.h" + +class LTKTraceGroup; +class LTKPreprocessorInterface; +class LTKShapeSample; +class LTKShapeFeatureExtractor; +class LTKShapeFeature; +class LTKAdapt; + +#define SIMILARITY(distance) (1 / (distance + EPS )) +#define SUPPORTED_MIN_VERSION "3.0.0" + +#define CLUSTER 0 +#define SINGLETON 1 + +#define INVALID_SHAPEID -2 +#define NEW_SHAPEID -2 + +//#ifdef _INTERNAL +//#endif + +typedef int (*FN_PTR_LOCAL_DISTANCE)(LTKShapeFeaturePtr, LTKShapeFeaturePtr,float&); +typedef int (*FN_PTR_CREATELTKLIPIPREPROCESSOR)(const LTKControlInfo& , LTKPreprocessorInterface** ); +typedef int (*FN_PTR_DELETELTKLIPIPREPROCESSOR)(LTKPreprocessorInterface* ); + +typedef vector<LTKShapeFeaturePtr> shapeFeature; +typedef vector<shapeFeature> shapeMatrix; + + +/** +* @ingroup ActiveDTWShapeRecognizer.h +* @brief The Header file for the ActiveDTWShapeRecognizer +* @class ActiveDTWShapeRecognizer +*<p> <p> +*/ + +class ActiveDTWShapeRecognizer: public LTKShapeRecognizer +{ + +public: + //#ifdef _INTERNAL + friend class LTKAdapt; + int adapt(int shapeID ); + int adapt(const LTKTraceGroup& sampleTraceGroup, int shapeID ); + + /** + * This function does the recognition function required for training phase (called from trainLVQ) + * The input parameter are the incharacter, which is compared with the existing + * set of prototypes and then the matched code vector and along with its index (and also the shape id) is returned + * @param incharacter is the character which we are trying to recognise. + * @param returnshapeID is the value of the matched character which is returned, codeCharacter is the matched prototype (code vector) vector, and codeVecIndex is the matched prototype (code vector) index + */ + int trainRecognize(LTKShapeSample& inShapeSample, LTKShapeSample& bestShapeSample, int& codeVecIndex); + + int writePrototypeShapesToMDTFile(); + + int addClass(const LTKTraceGroup& sampleTraceGroup, int& shapeID); + + int deleteClass(int shapeID); + + int readInternalClassifierConfig(); + +private: + + int deleteAdaptInstance(); + + + + // #endif + + +private: + + FN_PTR_DELETELTKLIPIPREPROCESSOR m_deleteLTKLipiPreProcessor; + //Function pointer for deleteLTKLipiPreProcessor + + // preproc lib handle + void *m_libHandler; + + // feature extractor lib handle + void *m_libHandlerFE; + + unsigned short m_numShapes; + /**< @brief Number of shapes + * <p> + * It Defines the number of shapes to be recognized + * + * DEFAULT: 0 + * + * Note: If the project is dynamic, then this numShapes was set to 0 + * If the project is not dynamic, then the numShapes was read from project configuration file + * </p> + */ + + + string m_prototypeSelection; + /**< @brief The Prototype Selection + * <p> + * if Prototype Selection = clustering, the training method used was clustering + * + * DEFAULT: LTKPreprocDefaults::NN_DEF_PROTOTYPESELECTION + * Possible values are "clustering" + * </p> + */ + + int m_prototypeReductionFactor; + /**< @brief The prototype Reduction factor + * <p> + * if PrototypeReductionFactor = 0 every training sample is cluster on its own + * = 100 all training samples are represented by one prototype + * = 80 then all samples are represented by 20% of the training samples + * + * DEFAULT: LTKPreprocDefaults::NN_DEF_PROTOTYPEREDUCTIONFACTOR + * RANGE: 0 TO 100 + * </p> + */ + + int m_numClusters; + /**< @brief The number of clusters + * <p> + * if NumClusters = k, then k clusters are found from the training samples + * + * + * + * DEFAULT: There is no default as this and prototype reduction factor are dependent + * RANGE: + * </p> + */ + + + float m_percentEigenEnergy; + /**< @brief The percent of Eigen Energy + * <p> + * if PercentEigenEnergy = 90 then those eigen values contributing to 90% of the Eigen Energy, + * and their corresponding eigen vectors are retained + * + * + * DEFAULT: LTKClassifierDefaults::ACTIVEDTW_DEF_PERCENTEIGENENERGY + * RANGE: 1-100 + * </p> + */ + + int m_eigenSpreadValue; + /**< @brief The eigen values spread range + * <p> + * if EigenSpreadValue = 16 then deformation parameters for computing the optimal deformation, + * can lie in the range [-4*Eigen Value,4*Eigen Value] + * + * + * DEFAULT: LTKClassifierDefaults::ACTIVEDTW_DEF_EIGENSPREADVALUE + * RANGE: greater than 0 + * </p> + */ + + int m_minClusterSize; + /**< @brief The minimum cluster size + * <p> + * It specifies the minimum number of samples required to form a cluster + * + * + * DEFAULT: LTKPreprocDefaults::ADAPT_DEF_MIN_NUMBER_SAMPLES_PER_CLASS + * RANGE: >= 2 + * </p> + */ + + bool m_useSingleton; + /**< @brief Use Singletons + * <p> + * It specifies if singletons should be considered during the recognition process + * If Use Singleton is true, singletons will be considered during the recognition process, + * else they will be ignored + * + * DEFAULT: LTKClassifierDefaults::ACTIVEDTW_DEF_USESINGLETON + * RANGE: True or False + * </p> + */ + + + int m_nearestNeighbors; + /**< @brief Nearest Neighbors + * <p> + * + * DEFAULT: LTKClassifierDefaults::NN_DEF_NEARESTNEIGHBORS + * </p> + */ + + + float m_dtwBanding; + /**< @brief DTW Banding + * <p> + * + * DEFAULT: LTKClassifierDefaults::NN_DEF_BANDING + * </p> + */ + + int m_dtwEuclideanFilter; + /**< @brief DTW Euclidean Filter + * <p> + * + * DEFAULT: LTKClassifierDefaults::ACTIVEDTW_DEF_DTWEUCLIDEANFILTER + * </p> + */ + + string m_featureExtractorName; + /**< @brief The Feature Extractor + * <p> + * + * DEFAULT: + * + * </p> + */ + + bool m_projectTypeDynamic; + /**< @brief Project Dynamic + * <p> + * if projectTypeDynamic = true, then the project is dynamic ie, the numShapes can take any number of value + * = false, then the project is not dynamic ie, the numShape can take value specified in project.cfg file + * + * DEFAULT: false + * </p> + */ + + LTKPreprocessorInterface *m_ptrPreproc; + /**< @brief Pointer to preprocessor instance + * <p> + * Instance which is used to call the preprocessing methods before recognition + * + * DEFAULT: NULL + * </p> + */ + + string m_activedtwCfgFilePath; + /**< @brief Full path of ActiveDTW configuration file + * <p> + * Assigned value in the ActiveDTWShapeRecognizer::initialize function + * </p> + */ + + string m_activedtwMDTFilePath; + /**< @brief Full path of Model data file + * <p> + * Assigned value in the ActiveDTWShapeRecognizer::initialize function + * </p> + */ + + stringStringMap m_headerInfo; + /**< @brief Header Information + * <p> + * </p> + */ + + LTKShapeRecoUtil m_shapeRecUtil; + /**< @brief Pointer to LTKShapeRecoUtil class + * <p> + * Instance which used to call Shape Recognizer Utility functions + * + * DEFAULT: NULL + */ + + string m_lipiRootPath; + /**< @brief Path of the Lipi Root + * <p> + * DEFAULT: LipiEngine::getLipiPath() + * </p> + */ + + string m_lipiLibPath; + /**< @brief Path of the Lipi Libraries + * <p> + * DEFAULT: LipiEngine::getLipiLibPath() + * </p> + */ + + LTKShapeFeatureExtractor *m_ptrFeatureExtractor; + /**< @brief Pointer to LTKShapeFeatureExtractor class + * <p> + * DEFAULT: NULL + * </p> + */ + + string m_preProcSeqn; + /**< @brief Preprocessor Sequence + * <p> + * This string will holds what sequence the preprocessor methods to be executed + * </p> + */ + + LTKCaptureDevice m_captureDevice; + + /** Structure to store information required for recognition and adaptation **/ + struct NeighborInfo + { + int typeId; + int sampleId; + int classId; + double distance; + }; + /**< @brief Structure to store information required for recognition and adaptation + * <p> + * TypeId: Specifies whether it is a singleton (defined by 1) or a cluster (defined by 0) + * SampleId: Specifies which singleton or cluster sample. The range of values depend on + * the number of clusters or singletons (>= 0) + * ClassId: Specifies the class id + * Distance: The distance between the test sample and singleton or + * the distance between the test sample and optimal deformation (cluster case) + * The range of values is >= 0 + * + * DEFAULT: NULL + * Range: Depends on Individual fields + * </p> + */ + + /**Vector to store the distances from each class to test sample**/ + vector <struct NeighborInfo> m_neighborInfoVec; + /**< @brief Neighbor Information Vector + * <p> + * This vector contains the distance information between the test samples and + * prototype data. It is a vector of structures NeighborInfo + * </p> + */ + + /** contains all the prototype data from load Model data **/ + vector<ActiveDTWShapeModel> m_prototypeShapes; + /**< @brief Prototype Shapes + * <p> + * This is a vector of ActiveDTWShapeModels + * This populated via the loadModelData function + * </p> + */ + + /** Sorts dtw distances **/ + static bool sortDist(const NeighborInfo& x, const NeighborInfo& y); + /** + * This method compares distances + * + * Semantics + * + * - Compare distances + * + * @param NeighborInfo(X) + * @param NeighborInfo(Y) + * + * @return TRUE: if X.distance lesser than Y.distance + * FALSE: if X.distance greater than Y.distance + * @exception none + */ + + vector<stringStringPair> m_preprocSequence; + + intIntMap m_shapeIDNumPrototypesMap; + /**< @brief Map of shapeID and Number of Samples per shape + * <p> + * + * </p> + */ + + int m_prototypeSetModifyCount; + /**< @brief + * <p> + * Used to count number of modifications done to m_prototypeShapes. + * Write to MDT after m_prototypeModifyCntCFG such modifications or at Exit. + * </p> + */ + + int m_MDTUpdateFreq; + /**< @brief Update MDT after a specified number of modifications to m_prototypeSet + * <p> + * Specified in ActiveDTW.cfg + * + * </p> + */ + + shapeFeature m_cachedShapeFeature; + /**< @brief Store shapeFeature of the last inTraceGroup to Recognize + * Used during subsequent call to Adapt + * <p> + * + * + * </p> + */ + + float m_rejectThreshold; + /**< @brief Threshold on the confidence to reject a test sample + * <p> + * + * </p> + */ + + bool m_adaptivekNN; + /**< @brief Adaptive kNN method to compute confidence + * <p> + * If m_adaptivekNN = true, the adaptive kNN method is used for confidence computation + * false, NN or kNN method is used, based on the value of m_nearestNeighbors + * </p> + */ + + string m_currentVersion; + + string m_MDTFileOpenMode; + /**< @brief File modes of the mdt file + * <p> + * If m_adaptivekNN = ascii, the mdt file is written in ascii mode + * binary, the mdt file will be written in binary mode + * Default: LTKPreprocDefaults::NN_MDT_OPEN_MODE_ASCII + * </p> + */ + + //dtw obj for computing the dtw distance between features + DynamicTimeWarping<LTKShapeFeaturePtr, float> m_dtwObj; + /**< @brief Dynamic Time Warping Object + * <p> + * This object aids in calculating the dtw distance between two LTKShapeFeaturePtrs + * and the distance is in float + * </p> + */ + + //store the recognitioresults + vector<LTKShapeRecoResult> m_vecRecoResult; + /**< @brief Vector of LTKShapeRecoResult + * <p> + * This vector is used to store the confidence values computed using computeConfidence + * </p> + */ + + //minimum numberOfSamples to form cluster + + + public: + + /** @name Constructors and Destructor */ + + /** + * Constructor + */ + ActiveDTWShapeRecognizer(const LTKControlInfo& controlInfo); + + /** + * Destructor + */ + ~ActiveDTWShapeRecognizer(); + + //@} + + /** + * This method initializes the ActiveDTW shape recognizer + * <p> + * Semantics + * - Set the project name in ActiveDTWShapeRecognizer::headerInfo with the parameter passed.<br> + * m_headerInfo[PROJNAME] = strProjectName; + * + * - Initialize ActiveDTWShapeRecognizer::m_activedtwCfgFilePath <br> + * m_activedtwCfgFilePath = ActiveDTWShapeRecognizer::m_lipiRootPath + LTKMacros::PROJECTS_PATH_STRING + + * strProjectName + LTKMacros::PROFILE_PATH_STRING + strProfileName + + * LTKInc::SEPARATOR + LTKInc::ActiveDTW + LTKInc::CONFIGFILEEXT; + * + * - Initializes ActiveDTWShapeRecognizer::m_activedtwMDTFilePath <br> + * m_activedtwMDTFilePath = ActiveDTWShapeRecognizer::m_lipiRootPath + LTKMacros::PROJECTS_PATH_STRING + + * strProjectName + LTKMacros::PROFILE_PATH_STRING + strProfileName + + * LTKInc::SEPARATOR + LTKInc::ActiveDTW + LTKInc::DATFILEEXT; + * + * - Initializes ActiveDTWShapeRecognizer::m_projectTypeDynamic with the value returned from LTKShapeRecoUtil::isProjectDynamic + * + * - Initialize the preprocessor using LTKShapeRecoUtil::initializePreprocessor and assign + * default values for + * -# Normalised size + * -# Threshold size + * -# Aspect ratio + * -# Dot threshold + * + * - Initialize the recognizers instance variables with the values given in classifier config file. + * + * </p> + * @param strProjectName : string : Holds the name of the Project + * @param strProfileName : string : Holds the name of the Profile + * + * @return int : LTKInc::SUCCESS if initialization done successfully + * errorValues if initialization has some errors + * + * @exception LTKErrorList::ECONFIG_FILE_OPEN Could not open project.cfg + * @exception LTKErrorList::EINVALID_NUM_OF_SHAPES Negative value for number of shapes + * @exception LTKErrorList::ELOAD_PREPROC_DLL Could not load preprocessor DLL + * @exception LTKErrorList::EDLL_FUNC_ADDRESS_CREATE Could not map createPreprocInst + * @exception LTKErrorList::EDLL_FUNC_ADDRESS_DELETE Could not map destroyPreprocInst + */ + + /** + * This method calls the train method of the ActiveDTW classifier. + * + */ + int train(const string& trainingInputFilePath, + const string& mdtHeaderFilePath, + const string &comment,const string &dataset, + const string &trainFileType=INK_FILE) ; + + /** + * This method loads the Training Data of the ActiveDTW classifier. + * @param + * @return LTKInc::SUCCESS : if the model data was loaded successfully + * @exception + */ + int loadModelData(); + + /** + * This method unloads all the training data + * @param none + * @return LTKInc::SUCCESS : if the model data was unloaded successfully + * @exception none + */ + int unloadModelData(); + + /** + * This method sets the device context for the recognition + * + * @param deviceInfo The parameter to be set + * @return + * @exception + */ + int setDeviceContext(const LTKCaptureDevice& deviceInfo); + + /** + * Populates a vector of LTKShapeRecoResult consisting of top classes with their confidences. + * + * Semantics + * + * - Validate the input arguments + * - Extract the features from traceGroup + * - Compute the optimal deformation vectors for each class + * - If the dtwEuclidean filter is on: + * --Then for Clusters + * -- Calculate the euclidean distances between the test samples and the optimal deformations + * Accordingly populate the distFilter vector + * --Then for singletons + * --Calculate the euclidean distances between the test samples and the singletonVectors + * Accordingly populate the distFilter vector + * - Compute the dtw distances between the test sample and the optimal deformations and singletonVectors + -- If the dtwEuclidean filter is on then calculate the dtw distances only + to those deformations and singletonVectors recommended by the dtw euclidean filter + * - Populate the distIndexPairVector with distances and shapeID + * - Sort the distIndexPairVector based on the distances in ascending order + * - Compute the confidences of the classes appearing in distIndexPairVector, call computeConfidence() + * - Check if the first element of resultVector has confidence less than m_rejectThreshold, if so, + empty the resultVector (reject the sample), log and return. + * - If the confThreshold value was specified by the user (not equal to -1), + delete the entries from resultVector with confidence values less than confThreshold. + * - If the numChoices value was specified by the user (not equal to -1), + update the resultVector with top numChoices entries, delete the other values. + * + * @param traceGroup The co-ordinates of the shape which is to be recognized + * @param screenContext Contains information about the input field like whether it is boxed input + * or continuous writing + * @param subSetOfClasses A subset of the entire class space which is to be used for + * recognizing the input shape. + * @param confThreshold Classes with confidence below this threshold are not returned, + * valid range of confThreshold: (0,1) + * @param numOfChoices Number of top choices to be returned in the result structure + * @param resultVector The result of recognition + * + * @return SUCCESS: resultVector populated successfully + * FAILURE: return ErrorCode + * @exception none + */ + int recognize(const LTKTraceGroup& traceGroup, + const LTKScreenContext& screenContext, + const vector<int>& subSetOfClasses, + float confThreshold, + int numChoices, + vector<LTKShapeRecoResult>& outResultVector); + + /* Overloaded the above function to take vector<LTKShapeFeaturePtr> as + * input + */ + int recognize(const vector<LTKShapeFeaturePtr>& shapeFeatureVec, + const vector<int>& inSubSetOfClasses, + float confThreshold, + int numChoices, + vector<LTKShapeRecoResult>& outResultVector); + + /** + * In case of: + * 1. Singleton Vectors: This method converts them to traceGroups + * 2. Clusters: This method converts the cluster means to traceGroup + * Semantics + * + * - Check if shapeID is valid, if not return error code + * - Check if project is Dynamic, if not return ErrorCode + * - Update PrototypeSet + * - Update MDTFile + * + * @param shapeID : int : Holds shapeID + * @param numberOfTraceGroups : int : Maximum number of Trace Groups to populate + * @param outTraceGroups : vector<LTKTraceGroup> : TraceGroup + * + * @return SUCCESS: TraceGroup is populated successfully + * FAILURE: return ErrorCode + * @exception none + */ + int getTraceGroups(int shapeID, int numberOfTraceGroups, vector<LTKTraceGroup> &outTraceGroups); + + + + private: + /** + * This function is the train method using Clustering prototype selection technique. + * + * + * Semantics + * + * - Note the start time for time calculations. + * + * - Create an instance of the feature extractor using ActiveDTWShapeRecognizer::initializeFeatureExtractorInstance() method + * + * - Call train method depending on the inFileType + * - ActiveDTWShapeRecognizer::trainFromListFile() if inFileType = LTKMacros::INK_FILE + * - ActiveDTWShapeRecognizer::trainFromFeatureFile() if inFileType = LTKMacros ::FEATURE_FILE + * + * - Update the headerInfo with algorithm version and name using ActiveDTWShapeRecognizer::updateHeaderWithAlgoInfo() method + * + * - Calculate the checksum. + * + * - Note the finish time for time calculations. + * + * + * @param inputFilePath :string : Path of trainListFile / featureFile + * @param strModelDataHeaderInfoFile : string : Holds the Header information of Model Data File + * @param inFileType : string : Possible values ink / featureFile + * + * @return LTKInc::SUCCESS : if the training done successfully + * @return errorCode : if it contains some errors + */ + int trainClustering(const string& trainingInputFilePath, + const string& mdtHeaderFilePath, + const string& trainFileType); + + + /** + * This method do the map between the module name and function names from the cfg file + * + * Semantics + * + * - Read the Preprocess Sequence from the nn.cfg + * + * - Split the sequence into tokens with delimiter LTKMacros::DELEMITER_SEQUENCE using LTKStringUtil::tokenizeString + * + * - Split each token with delimiter LTKMacrosDELEMITER_FUNC using LTKStringUtil::tokenizeString + * to get the Module name and Function name + * + * - Store the Module name and the Function name into a structure + * + * + * @param none + * @return LTKInc::SUCCESS : if functions are successfully mapped, + * @return errorCodes : if contains any errors + * @exception none + */ + int mapPreprocFunctions(); + + /** + * This method will assign default values to the members + * + * Semantics + * + * - Assign Default values to all the data members + * + * + * @param none + * + * @return none + */ + void assignDefaultValues(); + + /** Reads the ActiveDTW.cfg and initializes the instance variable of the classifier with the user defined + * values. + * + * Semantics + * + * - Open the activedtw.cfg using LTKConfigFileReader + * + * - Incase of file open failure (activedtw.cfg), default values of the classifier parameters are used. + * + * - The valid values of the classifier parameters are cached in to the class data members. + * LTKConfigFileReader::getConfigValue is used to get the value fora key defined in the config file + * + * - Exception is thrown if the user has specified an invalid valid for a parameter + * + * + * @param none + * @return SUCCESS : If the Config file read successfully + * @return errorCode : If it contains some errors + * @exception LTKErrorList::ECONFIG_FILE_RANGE The config file variable is not within the correct range + */ + int readClassifierConfig(); + + /** + * This function serves as wrapper function to the Dtw distance computation function + * (for use by clustering prototype selection) + * @param train This is an input parameter and corresponds to the training character. + * @param test This is an input parameter and corresponds to the testing character. + */ + int computeDTWDistance(const LTKShapeSample& inFirstShapeSampleFeatures, + const LTKShapeSample& inSecondShapeSampleFeatures, + float& outDTWDistance); + + /** + * computes the dtw distance between two shape feature vectors + **/ + int computeDTWDistance(const vector<LTKShapeFeaturePtr>& inFirstFeatureVector, + const vector<LTKShapeFeaturePtr>& inSecondFeatureVector, + float& outDTWDistance); + /** + * This function serves as wrapper function to the Dtw distance computation function + * (for use by recognize function) + * @param train This is an input parameter and corresponds to the training character. + * @param test This is an input parameter and corresponds to the testing character. + */ + + + /** + * Computes the euclidean distance between two shape Features + **/ + int computeEuclideanDistance(const shapeFeature& inFirstFeature, + const shapeFeature& inSecondFeature, + float& outEuclideanDistance); + /** + * This function is used to compute the Euclidean distance between two shape Features + * (for use by recognize when dtwEuclidean filter is on) + * @param train This is an input parameter and corresponds to the training character. + * @param test This is an input parameter and corresponds to the testing character. + */ + + + + + + /** + * This method creates a custom feature extractor instance and stores it's address in + * ActiveDTWShapeRecognizer::m_ltkFE. The local distance function pointer is also initialized. + * + * Semantics + * + * + * - Intialize the ActiveDTWShapeRecognizer::m_ptrFeatureExtractor with address of the feature extractor instance created + * using LTKShapeFeatureExtractorFactory::createFeatureExtractor + * + * - Cache the address of LTKShapeFeatureExtractor::getLocalDistance() in an instance variable + * + * @param none + * + * @return 0 on LTKInc::SUCCESS and 1 on LTKInc::FAILURE + * + * @exception none + */ + int initializeFeatureExtractorInstance(const LTKControlInfo& controlInfo); + + /** + * This method trains the classifier from the train list file whose path is passed as paramater. + * + * Semantics + * + * - Open the trainListFile for reading. + * + * - Open the mdt file for writing. + * + * - Write header information to the mdt file + * - ActiveDTWShapeRecognizer::m_numShapes + * - ActiveDTWShapeRecognizer::m_traceDimension + * - ActiveDTWShapeRecognizer::m_flexibilityIndex + * + * - Get a valid line from the train list file + * - Skip commented lines + * - Skip lines where number_of_tokens != 2 + * - Throw error LTKErrorList::EINITSHAPE_NONZERO, if the first shape in the list file is not zero + * - Throw error LTKErrorList::EINVALID_ORDER_LISTFILE if the shapes are not in sequential order + * + * - For every valid line get the ShapeSample from the ink file using ActiveDTWShapeRecognizer::getShapeSampleFromInkFile + * - Read ink from UNIPEN ink file + * - Skip if the trace group is empty + * - Pre process the trace group read from the ink file + * - Extract features + * + * - Push all the ShapeSamples corresponding to a shape into a vector of ShapeSample ShapeSamplesVec. + * + * - When all the ShapeSamples corresponding to a Shape have been collected, cluster them using ActiveDTWShapeRecognizer::performClustering + * + * - performClustering results in vector of clustered ShapeSamples. + * + * - computeCovarianceMatrix of clusters + * + * - computeEigenVectorsForLargeDimension for the covariance matrices of the clusters + * + * - construct shape models using cluster models and singletons + * + * - Append these clustered vector<ActiveDTWShapeModel> to the mdt file. + * + * + * @param listFilePath : string : Holds the path for train list file + * @param trainSet : ShapeSampleVector: Holds the ShapeSample for all shapes, used for LVQ only + * + * @return none + * + * @exception LTKErrorList::EFILE_OPEN_ERROR : Error in Opening a file (may be mdt file or list file) + * @exception LTKErrorList::EINVALID_NUM_OF_SHAPES : Invalid value for number of shapes + * @exception LTKErrorList::EINVALID_ORDER_LISTFILE: Invalid order of shapeId in List file + * @exception LTKErrorList::EINITSHAPE_NONZERO : Initial shapeId must not be zero + * @exception LTKErrorList::EEMPTY_EIGENVECTORS : Number of eigen vectors must be a positive number + * @exception LTKErrorList::EINVALID_NUM_OF_EIGENVECTORS : Number of eigen vector must be a positive number + */ + + int trainFromListFile(const string& listFilePath); + + /** + * This method will get the ShapeSample by giving the ink file path as input + * + * Semantics + * + * - Call the LTKShapeRecoUtil::readInkFromFile() method (Utility Method) to read the ink file + * By reading this file, an inTraceGroup was generated + * + * - Preprocess the inTraceGroup and get the preprocessed trace group + * LTKTraceGroup preprocessedTraceGroup + * + * - Extract features from the preprocessed trace group to get the ShapeSamples. + * + * + * @param path : string : The path for Ink file + * @param ShapeSample : ShapeSample : The ShapeSample generated after feature extraction + * + * @return SUCCESS : If the ShapeSample was got successfully + * @return FAILURE : Empty traces group detected for current shape + * + * @exception LTKErrorList::EINKFILE_EMPTY : Ink file is empty + * @exception LTKErrorList::EINK_FILE_OPEN : Unable to open unipen ink file + * @exception LTKErrorList::EINKFILE_CORRUPTED : Incorrect or corrupted unipen ink file. + * @exception LTKErrorList::EEMPTY_TRACE : Number of points in the trace is zero + * @exception LTKErrorList::EEMPTY_TRACE_GROUP : Number of traces in the trace group is zero + */ + int getShapeFeatureFromInkFile(const string& inkFilePath, + vector<LTKShapeFeaturePtr>& shapeFeatureVec); + + + /** + * This method will do Custering for the given ShapeSamples + * + * Semantics + * + * - If the ActiveDTWShapeRecognizer::m_prototypeReductionFactor is -1 means Automatic clustering could be done + * + * - If the ActiveDTWShapeRecognizer::m_prototypeReductionFactor is 0 means No clustering was needed + * + * - Otherwise clustering is needed based on the value of ActiveDTWShapeRecognizer::m_prototypeReductionFactor + * + * + * + * @param ShapeSamplesVec : ShapeSampleVector : Holds all the ShapeSample for a single class + * @param resultVector : int2DVector : Vector of indices of samples belonging to a cluster + * + * @return SUCCESS ; On successfully performing clustering + * @return ErrorCode ; On some error + * @exception none + */ + int performClustering(const vector<LTKShapeSample>& shapeSamplesVec, + int2DVector& outputVector); + + /** + * This method computes the covariance matrix and the mean for a given feature matrix + * + * Semantics + * + * - Computes the mean of the feature matrix + * + * - Computes the mean corrected data + * + * - Computes the covariance matrix + * + * + * + * @param featureMatrix : double2DVector : Holds all the features of a cluster + * @param covarianceMatrix : double2DVector : covariance matrix of the cluster + * @param meanFeature : doubleVector : mean feature of the cluster + * + * @return SUCCESS ; On successfully computing the covariance matrix + * @return ErrorCode ; On some error + * @exception LTKErrorList:: EEMPTY_FEATUREMATRIX, Feature matrix is empty + */ + int computeCovarianceMatrix(double2DVector& featureMatrix, + double2DVector& covarianceMatrix,doubleVector& meanFeature); + + /** + * compute the eigen vectors + * for a covariance Matrix + * @inparam covarianceMatrix,rank,nrot --> no of rotations + * @outparam eigenValueVec, eigenVectorMatrix + **/ + int computeEigenVectors(double2DVector &covarianceMatrix,const int rank, + doubleVector &eigenValueVec, double2DVector &eigenVectorMatrix, int& nrot); + + + /** + * This method will Update the Header information for the MDT file + * + * Semantics + * + * - Copy the version number to a string + * + * - Update the version info and algoName to ActiveDTWShapeRecognizer::m_headerInfo, which specifies the + * header information for MDT file + * + * + * @param none + * + * @return none + + * @exception none + */ + void updateHeaderWithAlgoInfo(); + + int preprocess (const LTKTraceGroup& inTraceGroup, LTKTraceGroup& outPreprocessedTraceGroup); + + + /** + * This append the shape model data to the mdt file + * + * Semantics + * + * - Append cluster models + * + * - Append singleton vectors + * + * + * + * @param shapeModel : ActiveDTWShapeModel : Holds clusters and singletons of a shape + * @param mdtFileHandle : ofstream : file handle for the mdt file + * + * @return SUCCESS ; On successfully appending the data to mdt file + * @return ErrorCode: + * @exception LTKErrorList:: EINVALID_FILE_HANDLE, unable to open mdt file + */ + int appendShapeModelToMDTFile(const ActiveDTWShapeModel& shapeModel,ofstream& mdtFileHandle); + + /** + * find optimal deformation parameters using bound constrained optimization + * here any third part library can be called + * we will solve the equation + * Min f(x) + * Subject to: lb <= x <= ub + * where lb -- lower bound ub --- upper bound + **/ + + /** + * This solves the optimization problem and finds the deformation parameters + * It constructs the optimal deformation, the sample in the cluster closest to the test sample + * Semantics + * + * - Solve the optimization problem + * Min f(x) + * Subject to: lb <= x <= ub + * where lb -- lower bound ub --- upper bound + * + * + * + * @param eigenValues : doubleVector : eigen values of a cluster + * @param eigenVector : double2DVector : eigen vectorsof a cluster + * @param clusterMean : doubleVector : mean of the cluster + * @param testSample : doubleVector : test sample + * @param deformationParameters : doubleVector : parameters required to construct the optimal deformation + * + * @return SUCCESS ; On successfully appending the data to mdt file + * @return ErrorCode: + * @exception LTKErrorList:: EEMPTY_EIGENVALUES, eigen values are empty + * @exception LTKErrorList:: EEMPTY_EIGENVECTORS, eigen vectors are empty + * @exception LTKErrorList:: EEMPTY_CLUSTERMEAN, cluster mean is empty + * @exception LTKErrorList:: ENUM_EIGVALUES_NOTEQUALTO_NUM_EIGVECTORS, number of eigen value is not equal to the number of eigen vectors + * @exception LTKErrorList:: EEMPTY_EIGENVECTORS, eigen vectors are empty + */ + int findOptimalDeformation(doubleVector& deformationParameters,doubleVector& eigenValues, double2DVector& eigenVector, + doubleVector& clusterMean, doubleVector& testSample); + + static void getDistance(const LTKShapeFeaturePtr& f1,const LTKShapeFeaturePtr& f2, float& distance); + + + /** + * This method computes the confidences of test sample belonging to various classes + * + * Semantics + * + * - Compute the confidence based on the values of m_nearestNeighbors and m_adaptiveKNN + * - Populate the resultVector + * - Sort the resultVector + * - + * + * @param distIndexPairVector : vector<struct NeighborInfo>: Holds the samples, classIDs and distances to the test sample + * @param resultVector : vector<LTKShapeRecoResult> : Holds the classIDs and the respective confidences + * + * @return SUCCESS: resultVector populated + * FAILURE: return ErrorCode + * @exception none + */ + int computeConfidence(); + + /** + * The comparison function object of STL's sort() method, overloaded for class LTKShapeRecoResult, used to sort the vector of LTKShapeRecoResult based on the member variable confidence + * + * Semantics + * + * - Check if the first object's confidence value is greater than the second object's confidence value + * - Return true or false + * - + * + * @param x : LTKShapeRecoResult : First object for comparison + * @param y : LTKShapeRecoResult : Second object for comparison + * + * @return true: If x.confidence > y.confidence + * false: If x.confidence <= y.confidence + * @exception none + */ + static bool sortResultByConfidence(const LTKShapeRecoResult& x, const LTKShapeRecoResult& y); + + static bool compareMap( const map<int, int>::value_type& lhs, const map<int, int>::value_type& rhs ); + + int mapFeatureExtractor(); + + int deleteFeatureExtractorInstance(); + /** + * This method extracts shape features from given TraceGroup + * + * Semantics + * + * - PreProcess tracegroup + * - Extract Features + * + * @param inTraceGroup : LTKTraceGroup : Holds TraceGroup of sample + * + * @return SUCCESS: if shapeFeatures is populated successfully + * FAILURE: return ErrorCode + * @exception none + */ + + int extractFeatVecFromTraceGroup(const LTKTraceGroup& traceGroup, + vector<LTKShapeFeaturePtr>& featureVec); + + + /** This method is used to initialize the PreProcessor + * + * Semantics + * + * - Load the preprocessor DLL using LTKLoadDLL(). + * + * - Get the proc address for creating and deleting the preprocessor instance. + * + * - Create preprocessor instance. + * + * - Start the logging for the preprocessor module. + * + * @param preprocDLLPath : string : Holds the Path of the Preprocessor DLL, + * @param errorStatus : int : Holds SUCCESS or Error Values, if occurs + * @return preprocessor instance + * + * @exception ELOAD_PREPROC_DLL Could not load preprocessor DLL + * @exception EDLL_FUNC_ADDRESS_CREATE Could not map createPreprocInst + * @exception EDLL_FUNC_ADDRESS_DELETE Could not map destroyPreprocInst + */ + int initializePreprocessor(const LTKControlInfo& controlInfo, + LTKPreprocessorInterface** preprocInstance); + + /** This method is used to deletes the PreProcessor instance + * + * Semantics + * + * - Call deleteLTKPreprocInst from the preproc.dll. + * + * - Unload the preprocessor DLL. + * + * @param ptrPreprocInstance : Holds the pointer to the LTKPreprocessorInterface + * @return none + * @exception none + */ + + int deletePreprocessor(); + + /** This method is used to Unloads the preprocessor DLL. + * + * Semantics + * + * - If m_libHandler != NULL, unload the DLL + * LTKUnloadDLL(m_libHandler); + * m_libHandler = NULL; + * + * @param none + * @return none + * @exception none + */ + int unloadPreprocessorDLL(); + + /**< @brief Pointer to LTKOSUtil interface + * <p> + * + * </p> + */ + LTKOSUtil* m_OSUtilPtr; + + int validatePreprocParameters(stringStringMap& headerSequence); + + /** + * Computes the eigen values and eigen vectors of the larger covariance matrix using the + * a smaller covariance matrix + * + * Semantics + * + * - Compute the smaller covariance matrix, using meanCorrectedData(Transpose)*meanCorrectedData(Transpose) + * + * - Compute the eigen vectors of the smaller covariance matrix + * + * - Determine the number of eigen vectors, depending on the eigen energy to be retained + * + * - Compute the eigen vectors of the larger covariance matrix + * + * - Normalizing the eigen vectors + * + * + * + * @param meanCorrectedData : double2DVector : mean corrected data + * @param covarianceMatrix : double2DVector : covariance matrix of the corresponding mean corrected data + * @param eigenValues : doubleVector : output selected eigen values + * @param eigenVector : double2DVectorr : output selected eigen vectors + * + * @return SUCCESS ; On successfully computing eigen values and eigen vectors + * @return ErrorCode: + * @exception LTKErrorList:: EEMPTY_MEANCORRECTEDDATA, empty mean corrected data + * @exception LTKErrorList:: EEMPTY_COVARIANCEMATRIX, empty covariance matrix + */ + int computeEigenVectorsForLargeDimension(double2DVector& meanCorrectedData,double2DVector& covarianceMatrix, + double2DVector& eigenVector,doubleVector& eigenValues); + + /** + * This converts the double vector to a feature vector + * It constructs the optimal deformation, the sample in the cluster closest to the test sample + * + * + * @param featureVec : doubleVector : input double feature vector + * @param shapeFeatureVec : vector<LTkShapeFeaturePtr> : output feature vector + * + * @return SUCCESS ; On successfully conversion + * @return ErrorCode: + * @exception LTKErrorList:: EINVALID_INPUT_FORMAT + */ + int convertDoubleToFeatureVector(vector<LTKShapeFeaturePtr>& shapeFeatureVec,doubleVector& featureVec); + + +}; + +#endif diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/activedtw.cfg b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/activedtw.cfg new file mode 100644 index 00000000..142470cf --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/activedtw.cfg @@ -0,0 +1,422 @@ +#------------------------------------------------------------------------------ +# activedtw.cfg +# +# Configuration file for Active-DTW Classification Method for +# Lipi Toolkit 4.0.0 +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# The standard format for the configuration entries is the name of the +# configuration parameter seperated by an equal to sign and then the value of +# the configuration parameter. For example: +# ConfigurationEntryName = value +# +# Lines starting with a # are commnet lines +# +# A cfg entry is strictly a key value pair and leaving the key without the +# value or specification of a value out of the range is not permitted +# +# If a cfg entry is not specified at all, then default values are used by the +# recognizer +#------------------------------------------------------------------------------ + +#------------------------------- +# PREPROCESSING +#------------------------------- + +#------------------------------------------------------------------------------- +# ResampTraceDimension +# +# Description: The number of target points for resampling. In other words, +# each character will be resampled to this number of points. In case of +# multistroke characters, this number of points will be distributed between +# the strokes in proportion to their lengths in proportion to their initial +# number of points. +# +# Valid values: Any integer > 0 +# Units: Points +# Default value: 60 +# Typical value: Average number of points per character in the training data set. +#------------------------------------------------------------------------------- +ResampTraceDimension = 60 + + + +#------------------------------------------------------------------------------- +# ResampPointAllocation +# +# Description: Method to be used for point allocation among different strokes +# during resampling. Two schemes have been implemented lengthbased and point +# based. In lengthbased allocation scheme, the number of points allocated to +# each stroke is proportional to the length of the stroke. Length of a stroke +# is calculated as the sum of the distances between each point in the stroke. +# In the pointbased allocation scheme, the target stroke point allocation is +# proportional to the number of points in the initial stroke. +# +# Valid value: [lengthbased | pointbased] +# Default value: lengthbased +#------------------------------------------------------------------------------- +ResampPointAllocation = lengthbased + + +#------------------------------------------------------------------------------- +# NormDotSizeThreshold +# +# Description: This threshold is used to determine whether a character is a dot. +# It is expressed in real length terms (inches) and converted internally to +# points using knowledge of the device�s spatial resolution. If the width +# and height are both less than this threshold, then all the points are replaced +# with the center of the of the normalized character, basically to represent it +# as a dot +# +# Valid values: Any real number > 0 +# Units: inches +# Default value: 0.01 +# Typical value: < 0.1 +#------------------------------------------------------------------------------- +NormDotSizeThreshold = 0.01 + +#------------------------------------------------------------------------------- +# NormLineWidthThreshold +# +# Description: This threshold is used to detect whether the character is a +# vertical or horizontal line. If only the height is less than this threshold +# then the character is detected as a horizontal line and if only the width is +# less than this threshold then the character is detected as a vertical line. +# Assuming the height is along the y-dimension and width is along the x- +# dimension, during normalization of a horizontal line only the x-coordinates +# are scaled and the y-coordinates are translated to the center of the character, +# with out scaling. Similarly for the vertical line only the y-coordinates are +# normalized and the x-coordinates are translated to the center with out scaling +# +# Valid values: Any real number > 0 +# Units: inches +# Default value: 0.01 +# Typical value: < 0.1 +#------------------------------------------------------------------------------- +NormLineWidthThreshold = 0.01 + +#------------------------------------------------------------------------------- +# NormPreserveAspectRatio +# +# Description: This parameter is used to indicate whether the aspect ratio +# has to be preserved during normalization. The aspect ratio is the calculated +# as maximum of (height/width , width/height). The aspect ratio is preserved only +# if the calculated aspect ratio is greater than the threshold value specified +# through NormPreserveAspectRatioThreshold and this configuration variable is +# set to true. If this configuration variable is set to false the aspect ratio +# is not preserved during normalization. +# +# Valid value: [true | false] +# Default value: true +#------------------------------------------------------------------------------- +NormPreserveAspectRatio = true + + +#------------------------------------------------------------------------------- +# NormPreserveAspectRatioThreshold +# +# Description: Aspect ratio is preserved during normalization if the computed +# aspect ratio (max(height/width, width/height)) is greater than this threshold +# and the configuration value NormPreserveAspectRatio is set to true. During +# aspect ratio preserving normalization, the larger of the two dimensions is +# normalized to the standard size and the other dimension is normalized +# proportional to the initial height and width ratio, so that the initial +# aspect ratio is maintained. +# +# Valid values: Any real number >= 1 +# Default value: 3 +# Typical value: >= 1.5 +#------------------------------------------------------------------------------- +NormPreserveAspectRatioThreshold = 3 + +#------------------------------------------------------------------------------- +# NormPreserveRelativeYPosition +# +# Description: The relative Y position is the mean of the y-coordinates in the +# input character. During normalization if this parameter is set to true, each +# y-coordinate of the character point is translated by the initial y-mean value, +# so that the mean of the y-coordinates remains the same before and after +# normalization. This is typically used in the word recognition context where +# each stroke of the character has to be normalized separately and the relative +# position of the strokes should be maintained even after normalization. +# +# Valid value: [true | false] +# Default value: false +#------------------------------------------------------------------------------- +NormPreserveRelativeYPosition = false + +#------------------------------------------------------------------------------- +# SmoothWindowSize +# +# Description: The configuration value specifies the length of the moving +# average filter (size of the window) for smoothing the character image. +# If this value is set to N, then each point in the input character is replaced +# by the average of value of this point, (N-1)/2 points on the right and (N-1)/2 +# on the left of this point. +# +# Valid value: Any integer > 0 +# Units: Points +# Typical value: 5 +# Default value: 3 +#------------------------------------------------------------------------------- +SmoothWindowSize = 3 + +#------------------------------------------------------------------------------- +# NNPreprocSequence +# +# Description: This variable is used to specify the sequence of preprocessing +# operations to be carried out on the input character sample before extracting +# the features. A valid preprocessing sequence can consist of combination of one +# or more of the functions selected from the valid values set mentioned below. +# The CommonPreProc prefix is used specify the default preprocessing module of +# LipiTk. The user can add his own preprocessing functions in other modules and +# specify them in the preprocessing sequence. +# +# Valid values: Any sequence formed from the following set +# CommonPreProc::normalizeSize; +# CommonPreProc::removeDuplicatePoints; +# CommonPreProc::smoothenTraceGroup; +# CommonPreProc::dehookTraces; +# CommonPreProc::normalizeOrientation; +# CommonPreProc::resampleTraceGroup; +# Default value: {CommonPreProc::normalizeSize,CommonPreProc::resampleTraceGroup,CommonPreProc::normalizeSize} +#------------------------------------------------------------------------------- +PreprocSequence={CommonPreProc::normalizeSize,CommonPreProc::resampleTraceGroup,CommonPreProc::normalizeSize} + +#--------------------------------------- +# TRAINING +#--------------------------------------- + +#------------------------------------------------------------------------------- +# NNTrainPrototypeSelectionMethod +# +# Description: This is used to specify the prototype selection method to be used +# while training the shape recognizer. When set to hier-clustering, the +# prototypes are selected using hierarchical clustering method. +# +# Valid value: [hier-clustering] +# Default value: hier-clustering +#------------------------------------------------------------------------------- +NNTrainPrototypeSelectionMethod=hier-clustering + + +#------------------------------------------------------------------------------- +# NNTrainPrototypeReductionFactorPerClass +# +# Description: This config parameter is used only when the prototype selection +# is clustering. This config parameter is used to specify the amount of the +# initial prototypes to be excluded during prototype selection. +# Set it to automatic if the number of clusters is to be determined +# automatically. Set it to none if no prototype selection is required. If the +# value of this parameter is set to a number between 1-100, say 25, then 75% +# (i.e 100-25) of the initial training data are retained as prototypes. +# This parameter can be specified only if the NNTrainNumPrototypesPerClass +# is not specified. +# +# Valid value: [automatic | none | any real number from 0-100] +# Default value: automatic +#------------------------------------------------------------------------------- +NNTrainPrototypeReductionFactorPerClass = 25 + +#------------------------------------------------------------------------------- +# NNTrainNumPrototypesPerClass +# +# Description: This config parameter is used only when the prototype selection +# is clustering. This is used to specify the number of prototypes to be selected +# from the training data. This parameter can be specified only if +# PrototypeReductionFactor is not specified. This config entry is commented as +# only one of NNTrainPrototypeReductionFactorPerClass or +# NNTrainNumPrototypesPerClass can be active in a valid cfg file. +# +# Valid value: [automatic | none | any integer from 1-N] +# (N is the number of samples # per class) +# Default value: automatic +#------------------------------------------------------------------------------- +#NNTrainNumPrototypesPerClass=100 + +# Note: Only one of either PrototypeReductionFactor or NumClusters can be +# enabled at any particular instance + +#------------------------------------------------------------------------------- +# ActiveDTWRetainPercentEigenEnergy +# +# Description: This config parameter is used to specify the amount of Eigen +# energy to be included to select the number of eigen vectors +# +# Valid value: [any integer from 0-100] +# +# Default value: 90 +#------------------------------------------------------------------------------- +ActiveDTWRetainPercentEigenEnergy= 90 + +#------------------------------------------------------------------------------- +# ActiveDTWMinClusterSize +# +# Description: This config parameter is used to specify the minimum number +# of samples required to form a cluster +# +# Valid value: [any postive integer > 1] +# +# Default value: 2 +#------------------------------------------------------------------------------- +ActiveDTWMinClusterSize = 2 + +#----------------------------------------- +# FEATURE EXTRACTION +#----------------------------------------- + +#------------------------------------------------------------------------------- +# FeatureExtractor +# +# Description: The configuration value is used to specify the feature extraction +# module to be used for feature extraction. The point float feature extraction +# module extracts the x,y,cosine and sine angle features at every point of the +# character. +# +# Valid value: [PointFloatShapeFeatureExtractor] +# Default value: PointFloatShapeFeatureExtractor +#------------------------------------------------------------------------------- +FeatureExtractor=PointFloatShapeFeatureExtractor + +#----------------------------------------- +# RECOGNITION +#----------------------------------------- + +#------------------------------------------------------------------------------- +# NNRecoDTWEuFilterOutputSize +# +# Description: This config parameter is used to set the proportion of nearest +# cluster or singleton vectors from a class (filtered based on euclidean distance) +# to be considered for calculating deformations or dtw distance. Set to 100 if +# all clusters or singletons are to be considered for calculating dtw distance. +# This is mainly used to increase the speed of recognition. +# +# Valid value: [all | any number from 1-100] +# Default Value: all +#------------------------------------------------------------------------------- +NNRecoDTWEuFilterOutputSize = 30 + +#------------------------------------------------------------------------------- +# ActiveDTWEigenSpreadValue +# +# Description: This value is used to configure the range of values the +# bound constraint optimization algorithm will take to calculate the +# optimal deformation sample +# Valid value: [greater than 0| default = 16] +#------------------------------------------------------------------------------- +ActiveDTWEigenSpreadValue = 16 + +#------------------------------------------------------------------------------- +# ActiveDTWUseSingleton +# +# Description: This value is used to configure whether singleton vectors +# from classes will be taken into consideration during the recognition +# process +# Valid value: [true | false] +# Default Value: true +#------------------------------------------------------------------------------- +ActiveDTWUseSingleton = true + +#------------------------------------------------------------------------------- +# NNRecoRejectThreshold +# +# Description: Threshold to reject the test sample. If the confidence obtained +# for the recognition of test sample is less than this threshold then the test +# sample is rejected. +# +# Valid value: Any real number from 0-1 +# Default value: 0.001 +#------------------------------------------------------------------------------- +NNRecoRejectThreshold = 0.001 + +#------------------------------------------------------------------------------- +# NNRecoNumNearestNeighbors +# +# Description: Number of nearest neighbors to be considered during recognition +# and computation of confidence. If the value is set to 1, nearest neighbor +# classifier is used, otherwise k-nearest neighbor or Adaptive k-nearest +# neighbor classifiers are used. By default, nearest neighbor classifier is used. +# +# Valid value: Any integer >= 1 +# Default value: 1 +#------------------------------------------------------------------------------- +NNRecoNumNearestNeighbors = 1 + +#------------------------------------------------------------------------------- +# NNRecoUseAdaptiveKNN +# +# Description: This parameter is used to specify whether Adaptive k-nearest +# neighbor recognizer (A-kNN) is to be used. If set to true, A-kNN recognizer is +# used, otherwise kNN recognizer is used. The A-kNN recognizer automatically +# determines the number of nearest neighbors to be considered for recognition in +# each class. If NNRecoNumNearestNeighbors is set to 1, this parameter is +# automatically set to false and the manually set value will not be considered. +# +# Valid value: [true | false] +# Default value: false +#------------------------------------------------------------------------------- +NNRecoUseAdaptiveKNN = false + +#-------------------------------------------- +# ADAPTATION +#-------------------------------------------- + +#------------------------------------------------------------------------------- +# ActiveDTWMaxClusterSize +# +# Description: This config parameter is used to specify the maximum number +# of samples a cluster is permitted to have +# +# Valid value: [any postive integer > 1 And Greater than ActiveDTWMinClusterSize] +# +# Default value: 2 +#------------------------------------------------------------------------------- +ActiveDTWMaxClusterSize = 30 + +#-------------------------------------------- +# COMMON FOR TRAINING AND RECOGNITION +#-------------------------------------------- + + +#------------------------------------------------------------------------------- +# NNDTWBandingRadius +# +# Description: This configuration parameter specifies the banding radius +# to be used for DTW computation. This is used to speed up the computation +# process. If this value is zero no banding is done. The value is specified as +# fraction of ResampTraceDimension to be used while computing the DTW +# distance. +# +# Valid values: Any real number > 0 and <= 1 +# Default Value: 0.33 +#------------------------------------------------------------------------------- +NNDTWBandingRadius=0.33 + +#------------------------------------------------------------------------------- +#ActiveDTWMDTFileUpdateFreq +# +# Description: This configuration parameter specifies the number of iterations after +# which MDT file is to be updated. +# Every call to addClass or deleteClass will add/delete the given class. These +# in-memory changes will be reflected in nn.mdt only after the specified +# number of such iterations and on application exit. +# +# Valid values: Any integer > 0 +# Default value: 5 +# Typical value: 5 +#------------------------------------------------------------------------------- +ActiveDTWMDTFileUpdateFreq = 100 + +#------------------------------------------------------------------------------- +# NNMDTFileOpenMode +# +# Description: This configuration parameter specifies the mode for +# opening the mdt file. +# +# Valid values: ascii, binary +# Default Value: ascii +#------------------------------------------------------------------------------- + +NNMDTFileOpenMode=ascii + diff --git a/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/activedtw.pro b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/activedtw.pro new file mode 100644 index 00000000..255c5512 --- /dev/null +++ b/src/plugins/lipi-toolkit/3rdparty/lipi-toolkit/src/reco/shaperec/activedtw/activedtw.pro @@ -0,0 +1,27 @@ +LIPILIBS = shaperecommon ltkcommon ltkutil featureextractorcommon +include(../../../lipiplugin.pri) + +INCLUDEPATH += \ + ../../../util/lib \ + ../featureextractor/common \ + ../common \ + +HEADERS += \ + ActiveDTW.h \ + ActiveDTWAdapt.h \ + ActiveDTWClusterModel.h \ + ActiveDTWShapeModel.h \ + ActiveDTWShapeRecognizer.h \ + +SOURCES += \ + ActiveDTW.cpp \ + ActiveDTWShapeRecognizer.cpp\ + ActiveDTWClusterModel.cpp \ + ActiveDTWShapeModel.cpp \ + ActiveDTWAdapt.cpp \ + +win32 { + DEFINES += ACTIVEDTW_EXPORTS + LIBS += Advapi32.lib + #DEF_FILE = ActiveDTW.def +} |