1 /*****************************************************************************************
2  * Copyright (c) 2006 Hewlett-Packard Development Company, L.P.
3  * Permission is hereby granted, free of charge, to any person obtaining a copy of
4  * this software and associated documentation files (the "Software"), to deal in
5  * the Software without restriction, including without limitation the rights to use,
6  * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
7  * Software, and to permit persons to whom the Software is furnished to do so,
8  * subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11 *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
16  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
17  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18  *****************************************************************************************/
19 
20 /************************************************************************
21  * SVN MACROS
22  *
23  * $LastChangedDate: 2011-02-08 16:57:52 +0530 (Tue, 08 Feb 2011) $
24  * $Revision: 834 $
25  * $Author: mnab $
26  *
27  ************************************************************************/
28 /************************************************************************
29  * FILE DESCR: Implementation for NN Shape Recognition module
30  *
31  * CONTENTS:
32  *
33  * AUTHOR:     Saravanan R.
34  *
35  w
36  * DATE:       January 23, 2004
37  * CHANGE HISTORY:
38  * Author       Date            Description of change
39  ************************************************************************/
40 
41 #include "LTKConfigFileReader.h"
42 
43 #include "NNShapeRecognizer.h"
44 
45 #include "LTKPreprocDefaults.h"
46 
47 #include "LTKHierarchicalClustering.h"
48 
49 #include "LTKPreprocessorInterface.h"
50 
51 #include "LTKShapeFeatureExtractorFactory.h"
52 
53 #include "LTKShapeFeatureExtractor.h"
54 
55 #include "LTKShapeFeature.h"
56 
57 #include "LTKVersionCompatibilityCheck.h"
58 
59 #include "LTKInkFileWriter.h"
60 #include "LTKOSUtil.h"
61 #include "LTKOSUtilFactory.h"
62 #include "LTKClassifierDefaults.h"
63 #include "NNAdapt.h"
64 #include "LTKLoggerUtil.h"
65 #include "LTKShapeRecoUtil.h"
66 #include "LTKTraceGroup.h"
67 #include "LTKErrors.h"
68 #include "LTKShapeSample.h"
69 #include "LTKException.h"
70 #include "LTKErrorsList.h"
71 #include "LTKStringUtil.h"
72 #include "LTKDynamicTimeWarping.h"
73 
74 /**********************************************************************************
75  * AUTHOR		: Saravanan R.
76  * DATE			: 23-Jan-2007
77  * NAME			: NNShapeRecognizer
78  * DESCRIPTION	: Default Constructor that initializes all data members
79  * ARGUMENTS		: none
80  * RETURNS		: none
81  * NOTES			:
82  * CHANGE HISTROY
83  * Author			Date				Description
84  *************************************************************************************/
85 
assignDefaultValues()86 void NNShapeRecognizer::assignDefaultValues()
87 {
88     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
89         "NNShapeRecognizer::assignDefaultValues()" << endl;
90 
91     m_numShapes = 0;
92     m_nnCfgFilePath = "";
93     m_nnMDTFilePath = "";
94     m_ptrPreproc = NULL;
95     m_projectTypeDynamic=false;
96     m_prototypeSelection=NN_DEF_PROTOTYPESELECTION;
97     m_prototypeReductionFactor=NN_DEF_PROTOTYPEREDUCTIONFACTOR;
98     m_prototypeDistance=NN_DEF_PROTOTYPEDISTANCE;
99     m_nearestNeighbors=NN_DEF_NEARESTNEIGHBORS;
100     m_dtwBanding=NN_DEF_BANDING;
101     m_dtwEuclideanFilter=NN_DEF_DTWEUCLIDEANFILTER;
102     m_preProcSeqn=NN_DEF_PREPROC_SEQ;
103     m_ptrFeatureExtractor=NULL;
104     m_featureExtractorName=NN_DEF_FEATURE_EXTRACTOR;
105     m_numClusters=NN_NUM_CLUST_INITIAL; // just to check that this is not what is mentioned by the user
106     m_MDTUpdateFreq=NN_DEF_MDT_UPDATE_FREQ;
107     m_prototypeSetModifyCount=0;
108     m_rejectThreshold=NN_DEF_REJECT_THRESHOLD;
109     m_adaptivekNN=false;
110     m_deleteLTKLipiPreProcessor=NULL;
111     m_MDTFileOpenMode = NN_MDT_OPEN_MODE_ASCII;
112 	m_LVQIterationScale=NN_DEF_LVQITERATIONSCALE;
113 	m_LVQInitialAlpha=NN_DEF_LVQINITIALALPHA;
114 	m_LVQDistanceMeasure=NN_DEF_LVQDISTANCEMEASURE;
115 
116     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
117         "NNShapeRecognizer::assignDefaultValues()" << endl;
118 }
119 
120 /**********************************************************************************
121  * AUTHOR		: Saravanan R.
122  * DATE			: 23-Jan-2007
123  * NAME			: initialize
124  * DESCRIPTION	: This method initializes the NN shape recognizer
125  * ARGUMENTS		: string  Holds the Project Name
126  *				  string  Holds the Profile Name
127  * RETURNS		: integer Holds error value if occurs
128  *						  Holds SUCCESS if no erros
129  * NOTES			:
130  * CHANGE HISTROY
131  * Author			Date				Description
132  *************************************************************************************/
NNShapeRecognizer(const LTKControlInfo & controlInfo)133 NNShapeRecognizer::NNShapeRecognizer(const LTKControlInfo& controlInfo):
134 m_OSUtilPtr(LTKOSUtilFactory::getInstance()),
135 m_libHandler(NULL),
136 m_libHandlerFE(NULL)
137 {
138     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
139         "NNShapeRecognizer::NNShapeRecognizer()" << endl;
140 
141 	try
142 	{
143 	    LTKControlInfo tmpControlInfo=controlInfo;
144 
145 	    string strProjectName = "";
146 	    string strProfileName = "";
147 
148 
149 	    if( (tmpControlInfo.projectName).empty() )
150 	    {
151 	        throw LTKException(EINVALID_PROJECT_NAME);
152 	    }
153 	    if( (tmpControlInfo.lipiRoot).empty() )
154 	    {
155 	        throw LTKException(ELIPI_ROOT_PATH_NOT_SET);
156 	    }
157 
158 	    if( (tmpControlInfo.profileName).empty() )
159 	    {
160 	        strProfileName = DEFAULT_PROFILE;
161 	        tmpControlInfo.profileName = strProfileName;
162 	    }
163 
164 	    if ( tmpControlInfo.toolkitVersion.empty() )
165 	    {
166 	        throw LTKException(ENO_TOOLKIT_VERSION);
167 	    }
168 
169 	    assignDefaultValues();
170 
171 	    m_lipiRootPath = tmpControlInfo.lipiRoot;
172 	    m_lipiLibPath = tmpControlInfo.lipiLib;
173 	    m_currentVersion = tmpControlInfo.toolkitVersion;
174 	    strProjectName = tmpControlInfo.projectName;
175 	    strProfileName = tmpControlInfo.profileName;
176 
177 
178 	    //Model Data file Header Information
179 	    m_headerInfo[PROJNAME] = strProjectName;
180 
181 	    //Holds the value of Number of Shapes in string format
182 	    string strNumShapes = "";
183 
184 	    string strProfileDirectory = m_lipiRootPath + PROJECTS_PATH_STRING +
185 	        strProjectName + PROFILE_PATH_STRING;
186 
187 	    //Holds the path of the Project.cfg
188 	    string projectCFGPath = strProfileDirectory + PROJECT_CFG_STRING;
189 
190 	    // Config file
191 
192 	    m_nnCfgFilePath = m_lipiRootPath + PROJECTS_PATH_STRING +
193 	        (tmpControlInfo.projectName) + PROFILE_PATH_STRING +
194 	        (tmpControlInfo.profileName) + SEPARATOR +
195 	        NN + CONFIGFILEEXT;
196 
197 
198 	    //Set the path for nn.mdt
199 	    m_nnMDTFilePath = strProfileDirectory + strProfileName + SEPARATOR + NN + DATFILEEXT;
200 
201 
202 	    //To find whether the project was dynamic or not andto read read number of shapes from project.cfg
203 	    int errorCode = m_shapeRecUtil.isProjectDynamic(projectCFGPath,
204 	            m_numShapes, strNumShapes, m_projectTypeDynamic);
205 
206 	    if( errorCode != SUCCESS)
207 	    {
208 	        LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
209 	            "NNShapeRecognizer::NNShapeRecognizer()" <<endl;
210 	        throw LTKException(errorCode);
211 	    }
212 
213 
214 	    //Set the NumShapes to the m_headerInfo
215 	    m_headerInfo[NUMSHAPES] = strNumShapes;
216 
217 	    //Currently preproc cfg also present in NN
218 	    tmpControlInfo.cfgFileName = NN;
219 	    errorCode = initializePreprocessor(tmpControlInfo,
220 	            &m_ptrPreproc);
221 
222 	    if( errorCode != SUCCESS)
223 	    {
224 	        LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
225 	            "NNShapeRecognizer::NNShapeRecognizer()" <<endl;
226 	        throw LTKException(errorCode);
227 	    }
228 
229 	    //Reading NN configuration file
230 	    errorCode = readClassifierConfig();
231 
232 	    if( errorCode != SUCCESS)
233 	    {
234 			cout<<endl<<"Encountered error in readClassifierConfig"<<endl;
235 	        LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
236 	            "NNShapeRecognizer::NNShapeRecognizer()" <<endl;
237 	        throw LTKException(errorCode);
238 	    }
239 
240 	    //Writing Feature extractor name and version into the header
241 	    m_headerInfo[FE_NAME] = m_featureExtractorName;
242 	    m_headerInfo[FE_VER] = SUPPORTED_MIN_VERSION; //FE version
243 
244 	    //Writting mdt file open mode to the mdt header
245 	    m_headerInfo[MDT_FOPEN_MODE] = m_MDTFileOpenMode;
246 
247 	    errorCode = initializeFeatureExtractorInstance(tmpControlInfo);
248 
249 	    if( errorCode != SUCCESS)
250 	    {
251 	        LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
252 	            "NNShapeRecognizer::NNShapeRecognizer()" <<endl;
253 	        throw LTKException(errorCode);
254 	    }
255 
256 	}
257 	catch(LTKException e)
258 	{
259 
260 		deletePreprocessor();
261 		m_prototypeSet.clear();
262 
263 		m_cachedShapeSampleFeatures.clearShapeSampleFeatures();
264 
265 	    //Unloading the feature Extractor instance
266 	    deleteFeatureExtractorInstance();
267 
268 		delete m_OSUtilPtr;
269 		throw e;
270 	}
271     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
272         "NNShapeRecognizer::NNShapeRecognizer()" << endl;
273 
274 }
275 
276 /**********************************************************************************
277  * AUTHOR		: Saravanan R.
278  * DATE			: 23-Jan-2007
279  * NAME			: readClassifierConfig
280  * DESCRIPTION	: Reads the NN.cfg and initializes the data members of the class
281  * ARGUMENTS		: none
282  * RETURNS		: SUCCESS   - If config file read successfully
283  *				  errorCode - If failure
284  * NOTES			:
285  * CHANGE HISTROY
286  * Author			Date				Description
287  *************************************************************************************/
readClassifierConfig()288 int NNShapeRecognizer::readClassifierConfig()
289 {
290     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
291         "NNShapeRecognizer::readClassifierConfig()" << endl;
292     string tempStringVar = "";
293     int tempIntegerVar = 0;
294     float tempFloatVar = 0.0;
295     LTKConfigFileReader *shapeRecognizerProperties = NULL;
296     int errorCode = FAILURE;
297 
298     try
299     {
300         shapeRecognizerProperties = new LTKConfigFileReader(m_nnCfgFilePath);
301     }
302     catch(LTKException e)
303     {
304         LOG(LTKLogger::LTK_LOGLEVEL_INFO)<< "Info: " <<
305             "Config file not found, using default values of the parameters" <<
306             "NNShapeRecognizer::readClassifierConfig()"<<endl;
307 
308         delete shapeRecognizerProperties;
309 
310 		return FAILURE;
311     }
312 
313     //Pre-processing sequence
314     errorCode = shapeRecognizerProperties->getConfigValue(PREPROCSEQUENCE, m_preProcSeqn);
315 
316     if(errorCode != SUCCESS)
317     {
318         LOG(LTKLogger::LTK_LOGLEVEL_INFO) << "Info: " <<
319             "Using default value of prerocessing sequence: "<< m_preProcSeqn <<
320             " NNShapeRecognizer::readClassifierConfig()"<<endl;
321 
322         m_preProcSeqn = NN_DEF_PREPROC_SEQ;
323     }
324 
325 	m_headerInfo[PREPROC_SEQ] = m_preProcSeqn;
326 
327 
328     if((errorCode = mapPreprocFunctions()) != SUCCESS)
329     {
330         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<" Error: " << errorCode <<
331             " NNShapeRecognizer::readClassifierConfig()"<<endl;
332 
333         delete shapeRecognizerProperties;
334 
335         LTKReturnError(errorCode);
336     }
337 
338     tempStringVar = "";
339     errorCode = shapeRecognizerProperties->getConfigValue(PROTOTYPESELECTION,
340             tempStringVar);
341 
342     if (errorCode == SUCCESS)
343     {
344         if( (LTKSTRCMP(tempStringVar.c_str(), PROTOTYPE_SELECTION_CLUSTERING) == 0) || (LTKSTRCMP(tempStringVar.c_str(), PROTOTYPE_SELECTION_LVQ) == 0))
345         {
346             m_prototypeSelection = tempStringVar;
347             LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) <<
348                 PROTOTYPESELECTION << " = " << tempStringVar <<
349                 "NNShapeRecognizer::readClassifierConfig()"<<endl;
350         }
351 
352         else
353         {
354             LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<
355                 "Error: " << ECONFIG_FILE_RANGE << " " <<
356                 PROTOTYPESELECTION << " : " << tempStringVar
357                 <<  " method is not supported"  <<
358                 " NNShapeRecognizer::readClassifierConfig()"<<endl;
359 
360             delete shapeRecognizerProperties;
361 
362             LTKReturnError(ECONFIG_FILE_RANGE);
363         }
364     }
365     else
366     {
367 	    LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
368             "Using default value for " << PROTOTYPESELECTION << " : " <<
369             m_prototypeSelection <<
370             " NNShapeRecognizer::readClassifierConfig()"<<endl;
371     }
372 
373 
374     tempStringVar = "";
375     errorCode = shapeRecognizerProperties->getConfigValue(PROTOREDFACTOR,
376                                                           tempStringVar);
377 
378     string tempStringVar1 = "";
379     int errorCode1 = shapeRecognizerProperties->getConfigValue(NUMCLUSTERS,
380                                                                tempStringVar1);
381 
382     if(errorCode1 == SUCCESS && errorCode == SUCCESS)
383     {
384         LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<
385             "Error: " << ECONFIG_FILE_RANGE
386             << " Cannot use both config parameters " <<
387             PROTOREDFACTOR << " and " << NUMCLUSTERS << " at the same time "<<
388             " NNShapeRecognizer::readClassifierConfig()"<<endl;
389 
390         delete shapeRecognizerProperties;
391 
392         LTKReturnError(ECONFIG_FILE_RANGE);
393     }
394 
395     if(tempStringVar != "")
396     {
397         if(LTKSTRCMP(tempStringVar.c_str(),  PROTO_RED_FACTOR_AUTOMATIC)==0)
398         {
399             //DEFINE MACRO DEF_PROTO_RED_FACTOR
400 			m_prototypeReductionFactor = -1;
401         }
402         else if(LTKSTRCMP(tempStringVar.c_str(), PROTO_RED_FACTOR_NONE)==0)
403         {
404             m_prototypeReductionFactor = 0;
405         }
406         else if(LTKSTRCMP(tempStringVar.c_str(), PROTO_RED_FACTOR_COMPLETE) == 0)
407         {
408             m_prototypeReductionFactor = 100;
409         }
410         else
411         {
412             if ( LTKStringUtil::isInteger(tempStringVar) )
413             {
414                 tempIntegerVar = atoi((tempStringVar).c_str());
415                 if(tempIntegerVar >= 0 && tempIntegerVar <=100)
416                 {
417                     m_prototypeReductionFactor = tempIntegerVar;
418 
419                     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
420                         << PROTOREDFACTOR << " is  =" << tempStringVar<<endl;
421                 }
422                 else
423                 {
424                     LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<
425                         "Error: " << ECONFIG_FILE_RANGE <<
426                         PROTOREDFACTOR << " is out of permitted range " <<
427                         " NNShapeRecognizer::readClassifierConfig()"<<endl;
428 
429                     delete shapeRecognizerProperties;
430 
431                     LTKReturnError(ECONFIG_FILE_RANGE);
432                 }
433             }
434             else
435             {
436                 LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<
437                     "Error: " << ECONFIG_FILE_RANGE <<
438                     PROTOREDFACTOR << " is out of permitted range"<<
439                     " NNShapeRecognizer::readClassifierConfig()"<<endl;
440 
441                 delete shapeRecognizerProperties;
442 
443                 LTKReturnError(ECONFIG_FILE_RANGE);
444             }
445 
446         }
447     }
448     else if(tempStringVar1 != "")
449     {
450         if(LTKSTRCMP(tempStringVar1.c_str(),  PROTO_RED_FACTOR_AUTOMATIC) == 0)
451         {
452             m_prototypeReductionFactor = -1;
453         }
454         else
455         {
456             if ( LTKStringUtil::isInteger(tempStringVar1) )
457             {
458                 tempIntegerVar = atoi((tempStringVar1).c_str());
459                 if(tempIntegerVar > 0)
460                 {
461                     m_numClusters = tempIntegerVar;
462 
463                     // m_numClusters is used in this case
464                     m_prototypeReductionFactor = NN_NUM_CLUST_INITIAL;
465 
466                     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
467                         NUMCLUSTERS << " is  = " << tempStringVar << endl;
468                 }
469                 else
470                 {
471                     LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
472                         "Error: " << ECONFIG_FILE_RANGE <<
473                         NUMCLUSTERS << " is out of permitted range "<<
474                         " NNShapeRecognizer::readClassifierConfig()"<<endl;
475 
476                     delete shapeRecognizerProperties;
477 
478                     LTKReturnError(ECONFIG_FILE_RANGE);
479                 }
480             }
481             else
482             {
483                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
484                     " Error: " << ECONFIG_FILE_RANGE <<
485                     NUMCLUSTERS << " is out of permitted range"<<
486                     " NNShapeRecognizer::readClassifierConfig()"<<endl;
487 
488                 delete shapeRecognizerProperties;
489 
490                 LTKReturnError(ECONFIG_FILE_RANGE);
491             }
492         }
493     }
494     else
495     {
496         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
497             "Assuming default value of " NUMCLUSTERS << " : " <<
498             m_numClusters << endl;
499     }
500 
501     tempStringVar = "";
502     errorCode = shapeRecognizerProperties->getConfigValue(PROTOTYPEDISTANCE,
503             tempStringVar);
504 
505     if(errorCode == SUCCESS )
506     {
507         if((LTKSTRCMP(tempStringVar.c_str(), EUCLIDEAN_DISTANCE) == 0) ||
508                 (LTKSTRCMP(tempStringVar.c_str(), DTW_DISTANCE) == 0))
509         {
510             m_prototypeDistance = tempStringVar;
511             LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
512                 "Prototype Distance Method = " <<tempStringVar<<endl;
513         }
514         else
515         {
516             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
517                 "Error: " << ECONFIG_FILE_RANGE << " " <<
518                 PROTOTYPEDISTANCE << " : " << tempStringVar <<
519                 " is not supported" <<
520                 "NNShapeRecognizer::readClassifierConfig()"<<endl;
521 
522             delete shapeRecognizerProperties;
523 
524             LTKReturnError(ECONFIG_FILE_RANGE);
525         }
526     }
527     else
528     {
529         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
530             "Using default value for " PROTOTYPEDISTANCE " : " <<
531             m_prototypeDistance << endl;
532     }
533 
534     tempStringVar = "";
535     shapeRecognizerProperties->getConfigValue(ADAPTIVE_kNN, tempStringVar);
536     if(LTKSTRCMP(tempStringVar.c_str(), "true") ==0)
537     {
538         m_adaptivekNN = true;
539         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
540             <<"Confidence computation method: " << ADAPTIVE_kNN << endl;
541     }
542     else
543     {
544         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
545             "Using default value for " << ADAPTIVE_kNN << " : " <<
546             m_adaptivekNN << endl;
547     }
548 
549     tempStringVar = "";
550     errorCode = shapeRecognizerProperties->getConfigValue(NEARESTNEIGHBORS,
551                                                           tempStringVar);
552 
553     if(errorCode == SUCCESS)
554     {
555         if ( LTKStringUtil::isInteger(tempStringVar) )
556         {
557             tempIntegerVar = atoi((tempStringVar).c_str());
558 
559             //Valid values of nearest neighbors: 1 or greater than MIN_NEARESTNEIGHBORS
560             if(tempIntegerVar > 0)
561             {
562                 // If the value of NearestNeighbors = 1, NN recognizer is used
563                 if(tempIntegerVar == 1)
564                 {
565                     m_adaptivekNN = false;
566                 }
567 
568                 // If AdaptivekNN is set to false, simply assign the value to m_nearestNeighbors
569                 // If AdaptivekNN is set, NearestNeighbors should be greater than than the
570                 // minimum no.of nearest neighbors allowed (MIN_NEARESTNEIGHBORS defined as macro)
571                 if(!m_adaptivekNN || (m_adaptivekNN && tempIntegerVar >= MIN_NEARESTNEIGHBORS))
572                 {
573                     m_nearestNeighbors = tempIntegerVar;
574                     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
575                         NEARESTNEIGHBORS << " = " <<m_nearestNeighbors<<endl;
576                 }
577             }
578             else
579             {
580                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
581                     "Error: " << ECONFIG_FILE_RANGE << NEARESTNEIGHBORS <<
582                     " is out of permitted range" <<
583                     " NNShapeRecognizer::readClassifierConfig()"<<endl;
584 
585                 delete shapeRecognizerProperties;
586 
587                 LTKReturnError(ECONFIG_FILE_RANGE);
588             }
589         }
590         else
591         {
592             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
593                 "Error: " << ECONFIG_FILE_RANGE << NEARESTNEIGHBORS <<
594                 " is out of permitted range" <<
595                 " NNShapeRecognizer::readClassifierConfig()"<<endl;
596 
597             delete shapeRecognizerProperties;
598 
599             LTKReturnError(ECONFIG_FILE_RANGE);
600         }
601     }
602     else
603     {
604         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
605             "Debug: " << "Using default value for " << NEARESTNEIGHBORS <<
606             " : " << m_nearestNeighbors << endl;
607     }
608 
609     tempStringVar = "";
610     errorCode = shapeRecognizerProperties->getConfigValue(REJECT_THRESHOLD,
611                                                           tempStringVar);
612     if(errorCode == SUCCESS)
613     {
614         if ( LTKStringUtil::isFloat(tempStringVar) )
615         {
616             tempFloatVar = LTKStringUtil::convertStringToFloat(tempStringVar);
617 
618             if(tempFloatVar  > 0 && tempFloatVar < 1)
619             {
620                 m_rejectThreshold = tempFloatVar;
621 
622                 LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
623                     REJECT_THRESHOLD << " = " <<tempStringVar <<endl;
624             }
625             else
626             {
627                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
628                     "Error: " << ECONFIG_FILE_RANGE << REJECT_THRESHOLD <<
629                     " should be in the range (0-1)" <<
630                     " NNShapeRecognizer::readClassifierConfig()"<<endl;
631 
632                 delete shapeRecognizerProperties;
633 
634                 LTKReturnError(ECONFIG_FILE_RANGE);
635             }
636         }
637         else
638         {
639             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
640                 "Error: " << ECONFIG_FILE_RANGE << REJECT_THRESHOLD <<
641                 " should be in the range (0-1)" <<
642                 " NNShapeRecognizer::readClassifierConfig()"<<endl;
643 
644             delete shapeRecognizerProperties;
645 
646             LTKReturnError(ECONFIG_FILE_RANGE);
647         }
648     }
649     else
650     {
651         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
652             "Using default value for " << REJECT_THRESHOLD <<
653             " : " << m_rejectThreshold << endl;
654     }
655 
656     tempStringVar = "";
657     errorCode = shapeRecognizerProperties->getConfigValue(DTWBANDING,
658                                                           tempStringVar);
659     if(errorCode == SUCCESS)
660     {
661         if ( LTKStringUtil::isFloat(tempStringVar) )
662         {
663             tempFloatVar = LTKStringUtil::convertStringToFloat(tempStringVar);
664 
665             if(tempFloatVar  > 0 && tempFloatVar <= 1)
666             {
667                 m_dtwBanding = tempFloatVar;
668                 LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
669                     DTWBANDING << " = " <<m_dtwBanding<<endl;
670             }
671             else
672             {
673                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
674                     "Error: "<< ECONFIG_FILE_RANGE << DTWBANDING <<
675                     " is out of permitted range" <<
676                     " NNShapeRecognizer::readClassifierConfig()"<<endl;
677 
678                 delete shapeRecognizerProperties;
679 
680                 LTKReturnError(ECONFIG_FILE_RANGE);
681             }
682         }
683         else
684         {
685             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
686                 "Error: "<< ECONFIG_FILE_RANGE <<
687                 " DTWBANDING is out of permitted range" <<
688                 " NNShapeRecognizer::readClassifierConfig()"<<endl;
689 
690             delete shapeRecognizerProperties;
691 
692             LTKReturnError(ECONFIG_FILE_RANGE);
693         }
694     }
695     else
696     {
697         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
698             "Using default value for " << DTWBANDING << " : " <<
699             m_dtwBanding << endl;
700     }
701 
702     tempStringVar = "";
703     errorCode = shapeRecognizerProperties->getConfigValue(DTWEUCLIDEANFILTER,
704                                                           tempStringVar);
705     if(errorCode == SUCCESS)
706     {
707         if(LTKSTRCMP(tempStringVar.c_str(), DTW_EU_FILTER_ALL) == 0)
708         {
709             m_dtwEuclideanFilter = EUCLIDEAN_FILTER_OFF;
710         }
711         else
712         {
713             if ( LTKStringUtil::isInteger(tempStringVar) )
714             {
715                 tempIntegerVar = atoi((tempStringVar).c_str());
716 
717 				if(tempIntegerVar > 0 && tempIntegerVar <= 100)
718 				{
719 				    m_dtwEuclideanFilter = tempIntegerVar;
720                     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
721                         DTWEUCLIDEANFILTER << " is  = "<<
722                         m_dtwEuclideanFilter<<endl;
723 
724 
725 				}
726                 else
727                 {
728                     LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
729                         "Error: " << ECONFIG_FILE_RANGE <<
730                         DTWEUCLIDEANFILTER << " is out of permitted range " <<
731                         " NNShapeRecognizer::readClassifierConfig()"<<endl;
732 
733                     delete shapeRecognizerProperties;
734 
735                     LTKReturnError(ECONFIG_FILE_RANGE);
736                 }
737             }
738             else
739             {
740                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
741                     "Error: " << ECONFIG_FILE_RANGE << DTWEUCLIDEANFILTER <<
742                     " is out of permitted range"<<
743                     " NNShapeRecognizer::readClassifierConfig()"<<endl;
744 
745                 delete shapeRecognizerProperties;
746 
747                 LTKReturnError(ECONFIG_FILE_RANGE);
748             }
749         }
750     }
751     else
752     {
753         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
754             "Using default value for " << DTWEUCLIDEANFILTER <<
755             " : " << m_dtwEuclideanFilter << endl;
756     }
757 
758     tempStringVar = "";
759     errorCode = shapeRecognizerProperties->getConfigValue(FEATUREEXTRACTOR,
760                                                           tempStringVar);
761     if(errorCode == SUCCESS)
762     {
763         m_featureExtractorName = tempStringVar;
764         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
765             FEATUREEXTRACTOR << " = "<<tempStringVar<<endl;
766     }
767     else
768     {
769         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
770             "Using default value for " << FEATUREEXTRACTOR << " : " <<
771             m_featureExtractorName << endl;
772     }
773 	//LVQ Paramaters
774 	//LVQ Iteration Scale
775 	errorCode = shapeRecognizerProperties->getConfigValue(LVQITERATIONSCALE,
776 			tempStringVar);
777 	if(errorCode == SUCCESS)
778 	{
779 		m_LVQIterationScale=atoi((tempStringVar).c_str());
780 
781 		if(!((m_LVQIterationScale>0)&& LTKStringUtil::isInteger(tempStringVar)))
782 		{
783 			LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
784                         "Error: " << ECONFIG_FILE_RANGE <<
785                         LVQITERATIONSCALE << " should be a positive integer " <<
786                         " NNShapeRecognizer::readClassifierConfig()"<<endl;
787 
788             delete shapeRecognizerProperties;
789 
790             LTKReturnError(ECONFIG_FILE_RANGE);
791 		}
792 	}
793 	else
794 	{
795 		m_LVQIterationScale = NN_DEF_LVQITERATIONSCALE;
796 		LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) <<
797             "Using default value for LVQIterationScale: " << m_LVQIterationScale <<
798             " NNShapeRecognizer::readClassifierConfig()"<<endl;
799 
800 	}
801 	//LVQ Initial Alpha
802 	tempStringVar="";
803 	errorCode = shapeRecognizerProperties->getConfigValue(LVQINITIALALPHA,
804 			tempStringVar);
805 
806 	if(errorCode == SUCCESS)
807 	{
808         m_LVQInitialAlpha = LTKStringUtil::convertStringToFloat(tempStringVar);
809 
810 		if((m_LVQInitialAlpha>1)||(m_LVQInitialAlpha<0))
811 		{
812 			LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
813                         "Error: " << ECONFIG_FILE_RANGE <<
814                         LVQINITIALALPHA << " is out of permitted range " <<
815                         " NNShapeRecognizer::readClassifierConfig()"<<endl;
816 
817             delete shapeRecognizerProperties;
818 
819             LTKReturnError(ECONFIG_FILE_RANGE);
820 		}
821 
822 	}
823 	else
824 	{
825 		m_LVQInitialAlpha = NN_DEF_LVQINITIALALPHA ;
826 		LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) <<
827             "Using default value for LVQInitialAlpha: " << m_LVQInitialAlpha <<
828             " NNShapeRecognizer::readClassifierConfig()"<<endl;
829 	}
830 	//LVQ Distance Measure
831 	tempStringVar = "";
832     errorCode = shapeRecognizerProperties->getConfigValue(LVQDISTANCEMEASURE,
833             tempStringVar);
834 
835     if(errorCode == SUCCESS )
836     {
837         if((LTKSTRCMP(tempStringVar.c_str(), EUCLIDEAN_DISTANCE) == 0) ||
838                 (LTKSTRCMP(tempStringVar.c_str(), DTW_DISTANCE) == 0))
839         {
840             m_LVQDistanceMeasure = tempStringVar;
841             LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
842                 "LVQ Prototype Distance Method = " <<tempStringVar<<endl;
843         }
844         else
845         {
846             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
847                 "Error: " << ECONFIG_FILE_RANGE << " " <<
848                 LVQDISTANCEMEASURE << " : " << tempStringVar <<
849                 " is not supported" <<
850                 "NNShapeRecognizer::readClassifierConfig()"<<endl;
851 
852             delete shapeRecognizerProperties;
853 
854             LTKReturnError(ECONFIG_FILE_RANGE);
855         }
856     }
857     else
858     {
859         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
860             "Using default value for " LVQDISTANCEMEASURE " : " <<
861             m_prototypeDistance << endl;
862     }
863 
864     tempStringVar = "";
865     errorCode = shapeRecognizerProperties->getConfigValue(MDT_UPDATE_FREQUENCY,
866                                                           tempStringVar);
867 
868     if(errorCode == SUCCESS)
869     {
870         if ( LTKStringUtil::isInteger(tempStringVar) )
871         {
872             m_MDTUpdateFreq = atoi(tempStringVar.c_str());
873             if(m_MDTUpdateFreq<=0)
874             {
875                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
876                     "Error: " << ECONFIG_FILE_RANGE << MDT_UPDATE_FREQUENCY <<
877                     " should be zero or a positive integer" <<
878                     " NNShapeRecognizer::readClassifierConfig()"<<endl;
879 
880                 delete shapeRecognizerProperties;
881 
882                 LTKReturnError(ECONFIG_FILE_RANGE);
883             }
884         }
885         else
886         {
887             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
888                 "Error: " << ECONFIG_FILE_RANGE << MDT_UPDATE_FREQUENCY <<
889                 " should be zero or a positive integer" <<
890                 " NNShapeRecognizer::readClassifierConfig()"<<endl;
891 
892             delete shapeRecognizerProperties;
893 
894             LTKReturnError(ECONFIG_FILE_RANGE);
895         }
896     }
897     else
898     {
899         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
900             "Using default value for " << MDT_UPDATE_FREQUENCY <<
901             " : " << m_MDTUpdateFreq << endl;
902     }
903 
904     tempStringVar = "";
905     errorCode = shapeRecognizerProperties->getConfigValue(MDT_FILE_OPEN_MODE,
906                                                           tempStringVar);
907 
908     if(errorCode == SUCCESS)
909     {
910         if ( tempStringVar == NN_MDT_OPEN_MODE_ASCII ||
911              tempStringVar == NN_MDT_OPEN_MODE_BINARY )
912         {
913             m_MDTFileOpenMode = tempStringVar;
914         }
915         else
916         {
917             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
918                 "Error: " << ECONFIG_FILE_RANGE << MDT_FILE_OPEN_MODE <<
919                 " should be ascii or binary" <<
920                 " NNShapeRecognizer::readClassifierConfig()"<<endl;
921 
922             delete shapeRecognizerProperties;
923 
924             LTKReturnError(ECONFIG_FILE_RANGE);
925         }
926     }
927     else
928     {
929         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
930             "Using default value for " << MDT_FILE_OPEN_MODE <<
931             " : " << m_MDTFileOpenMode << endl;
932     }
933 
934 	tempStringVar = "";
935     errorCode = shapeRecognizerProperties->getConfigValue(SIZETHRESHOLD,
936                                                        tempStringVar);
937 	if(errorCode == SUCCESS)
938     {
939 			m_headerInfo[DOT_SIZE_THRES] = tempStringVar;
940 	}
941 
942 	tempStringVar = "";
943 	errorCode = shapeRecognizerProperties->getConfigValue(ASPECTRATIOTHRESHOLD,
944                                                        tempStringVar);
945    	if(errorCode == SUCCESS)
946     {
947 			m_headerInfo[ASP_RATIO_THRES] = tempStringVar;
948 	}
949 
950 	tempStringVar = "";
951 	errorCode = shapeRecognizerProperties->getConfigValue(DOTTHRESHOLD,
952                                                        tempStringVar);
953     if(errorCode == SUCCESS)
954     {
955 		m_headerInfo[DOT_THRES] = tempStringVar;
956 	}
957 
958 	tempStringVar = "";
959 	errorCode = shapeRecognizerProperties->getConfigValue(PRESERVERELATIVEYPOSITION,
960                                            tempStringVar);
961 
962 	if(errorCode == SUCCESS)
963     {
964 		m_headerInfo[PRESER_REL_Y_POS] = tempStringVar;
965 	}
966 
967 	tempStringVar = "";
968 	errorCode = shapeRecognizerProperties->getConfigValue(PRESERVEASPECTRATIO,
969                                            tempStringVar);
970 
971 	if(errorCode == SUCCESS)
972     {
973 		m_headerInfo[PRESER_ASP_RATIO] = tempStringVar;
974 	}
975 
976     tempStringVar = "";
977 	errorCode = shapeRecognizerProperties->getConfigValue(SIZETHRESHOLD,
978                                            tempStringVar);
979 
980 	if(errorCode == SUCCESS)
981     {
982 		m_headerInfo[NORM_LN_WID_THRES] = tempStringVar;
983 	}
984 
985     tempStringVar = "";
986 	errorCode = shapeRecognizerProperties->getConfigValue(RESAMPLINGMETHOD,
987                                            tempStringVar);
988 
989 	if(errorCode == SUCCESS)
990     {
991 		m_headerInfo[RESAMP_POINT_ALLOC] = tempStringVar;
992 	}
993 
994     tempStringVar = "";
995 	errorCode = shapeRecognizerProperties->getConfigValue(SMOOTHFILTERLENGTH,
996                                            tempStringVar);
997 
998 	if(errorCode == SUCCESS)
999     {
1000 		m_headerInfo[SMOOTH_WIND_SIZE] = tempStringVar;
1001 	}
1002 
1003     tempStringVar = "";
1004     LTKStringUtil::convertIntegerToString(m_ptrPreproc->getTraceDimension(),
1005                                           tempStringVar);
1006 
1007     m_headerInfo[TRACE_DIM] = tempStringVar;
1008 
1009     delete shapeRecognizerProperties;
1010 
1011     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1012         "NNShapeRecognizer::readClassifierConfig()" << endl;
1013 
1014     return SUCCESS;
1015 }
1016 
1017 /**********************************************************************************
1018  * AUTHOR		: Saravanan R
1019  * DATE          		: 23-Jan-2007
1020  * NAME          		: mapPreprocFunctions
1021  * DESCRIPTION   	: Maps the module name and its function names in the preprocessing
1022  sequence.
1023  * ARGUMENTS     	: none
1024  * RETURNS       	: SUCCESS on successful,
1025  *				  errorNumbers on Failure.
1026  * NOTES         	:
1027  * CHANGE HISTROY
1028  * Author            Date                Description
1029  *************************************************************************************/
mapPreprocFunctions()1030 int NNShapeRecognizer::mapPreprocFunctions()
1031 {
1032     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1033         "NNShapeRecognizer::mapPreprocFunctions()" << endl;
1034 
1035     stringStringMap preProcSequence;
1036 
1037     stringStringPair tmpPair;
1038 
1039     stringVector moduleFuncNames;
1040     stringVector modFuncs;
1041     stringVector funcNameTokens;
1042 
1043     string module = "", funName = "", sequence = "";
1044     string::size_type indx;
1045 
1046     LTKTraceGroup local_inTraceGroup;
1047 
1048     LTKStringUtil::tokenizeString(m_preProcSeqn,  DELEMITER_SEQUENCE,  funcNameTokens);
1049 
1050     int numFunctions = funcNameTokens.size();
1051 
1052     if(numFunctions == 0)
1053     {
1054         LOG( LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<
1055             "Wrong preprocessor sequence in cfg file : " + m_preProcSeqn <<
1056             " NNShapeRecognizer::mapPreprocFunctions()"<<endl;
1057 
1058         LTKReturnError(EINVALID_PREPROC_SEQUENCE);
1059     }
1060 
1061     for (indx = 0; indx < numFunctions ; indx++)
1062     {
1063         moduleFuncNames.push_back(funcNameTokens[indx]);
1064     }
1065 
1066     int numModuleFunctions = moduleFuncNames.size();
1067 
1068     for(indx=0; indx < numModuleFunctions ; indx++)
1069     {
1070         sequence = moduleFuncNames[indx];
1071 
1072         LTKStringUtil::tokenizeString(sequence,  DELEMITER_FUNC,  modFuncs);
1073 
1074         if(modFuncs.size() >= 2)
1075         {
1076             module = modFuncs.at(0);
1077 
1078             funName =  modFuncs.at(1);
1079 
1080             if(!module.compare("CommonPreProc"))
1081             {
1082                 FN_PTR_PREPROCESSOR pPreprocFunc = NULL;
1083                 pPreprocFunc = m_ptrPreproc->getPreprocptr(funName);
1084                 if(pPreprocFunc!= NULL)
1085                 {
1086                     tmpPair.first = module;
1087                     tmpPair.second = funName;
1088                     m_preprocSequence.push_back(tmpPair);
1089                 }
1090                 else
1091                 {
1092                     LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_PREPROC_SEQUENCE << " " <<
1093                         "Wrong preprocessor sequence entry in cfg file : " <<funName<<
1094                         " NNShapeRecognizer::mapPreprocFunctions()"<<endl;
1095                     LTKReturnError(EINVALID_PREPROC_SEQUENCE);
1096                 }
1097             }
1098             else
1099             {
1100                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_PREPROC_SEQUENCE << " " <<
1101                     "Wrong preprocessor sequence entry in cfg file  : " << module<<
1102                     " NNShapeRecognizer::mapPreprocFunctions()"<<endl;
1103                 LTKReturnError(EINVALID_PREPROC_SEQUENCE);
1104             }
1105         }
1106         else
1107         {
1108             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_PREPROC_SEQUENCE << " " <<
1109                 "Wrong preprocessor sequence entry in cfg file  : "<<module<<
1110                 " NNShapeRecognizer::mapPreprocFunctions()"<<endl;
1111             LTKReturnError(EINVALID_PREPROC_SEQUENCE);
1112         }
1113     }
1114 
1115     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1116         "NNShapeRecognizer::mapPreprocFunctions()" << endl;
1117 
1118     return SUCCESS;
1119 }
1120 
1121 /**********************************************************************************
1122  * AUTHOR		: Saravanan R.
1123  * DATE			: 23-Jan-2004
1124  * NAME			: ~NNShapeRecognizer
1125  * DESCRIPTION	: destructor
1126  * ARGUMENTS		:
1127  * RETURNS		:
1128  * NOTES			:
1129  * CHANGE HISTROY
1130  * Author			Date				Description
1131  *************************************************************************************/
~NNShapeRecognizer()1132 NNShapeRecognizer::~NNShapeRecognizer()
1133 {
1134 
1135     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1136         "NNShapeRecognizer::~NNShapeRecognizer()" << endl;
1137 
1138     deleteAdaptInstance();
1139 
1140 	int returnStatus = SUCCESS;
1141     //To update MDT File
1142     if(m_prototypeSetModifyCount >0)
1143     {
1144         m_prototypeSetModifyCount = m_MDTUpdateFreq-1;
1145 
1146         returnStatus = writePrototypeSetToMDTFile();
1147         if(returnStatus != SUCCESS)
1148         {
1149             LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " <<
1150                 " NNShapeRecognizer::~NNShapeRecognizer()" << endl;
1151              throw LTKException(returnStatus);
1152 
1153         }
1154     }
1155 
1156     m_neighborInfoVec.clear();
1157 
1158     returnStatus = deletePreprocessor();
1159     if(returnStatus != SUCCESS)
1160     {
1161         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " <<
1162             " NNShapeRecognizer::~NNShapeRecognizer()" << endl;
1163         throw LTKException(returnStatus);
1164     }
1165 
1166     m_prototypeSet.clear();
1167 
1168 	m_cachedShapeSampleFeatures.clearShapeSampleFeatures();
1169 
1170     //Unloading the feature Extractor instance
1171     returnStatus = deleteFeatureExtractorInstance();
1172     if(returnStatus != SUCCESS)
1173     {
1174         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " <<  returnStatus << " " <<
1175             " NNShapeRecognizer::~NNShapeRecognizer()" << endl;
1176         throw LTKException(returnStatus);
1177     }
1178 
1179     delete m_OSUtilPtr;
1180     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1181         "NNShapeRecognizer::~NNShapeRecognizer()" << endl;
1182 
1183 
1184 }
1185 
1186 
1187 /**********************************************************************************
1188  * AUTHOR		: Saravanan R.
1189  * DATE			: 25-Jan-2004
1190  * NAME			: train
1191  * DESCRIPTION	:
1192  * ARGUMENTS		:
1193  * RETURNS		:
1194  * NOTES			:
1195  * CHANGE HISTROY
1196  * Author			Date				Description
1197  *************************************************************************************/
train(const string & trainingInputFilePath,const string & mdtHeaderFilePath,const string & comment,const string & dataset,const string & trainFileType)1198 int NNShapeRecognizer::train(const string& trainingInputFilePath,
1199         const string& mdtHeaderFilePath,
1200         const string &comment,const string &dataset,
1201         const string &trainFileType)
1202 {
1203     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1204         "NNShapeRecognizer::train()" << endl;
1205 
1206     int returnStatus = SUCCESS;
1207 
1208 
1209     if(comment.empty() != true)
1210     {
1211         m_headerInfo[COMMENT] = comment;
1212     }
1213 
1214     if(dataset.empty() != true)
1215     {
1216         m_headerInfo[DATASET] = dataset;
1217     }
1218 
1219     //Check the prototype Selection method and call accordingly
1220 
1221     if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_LVQ) == 0)
1222     {
1223         returnStatus = trainLVQ(trainingInputFilePath, mdtHeaderFilePath, trainFileType);
1224 
1225         if(returnStatus != SUCCESS)
1226         {
1227             LTKReturnError(returnStatus);
1228         }
1229 
1230     }
1231 
1232     if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_CLUSTERING) == 0)
1233     {
1234         returnStatus = trainClustering(trainingInputFilePath,
1235                 mdtHeaderFilePath,
1236                 trainFileType);
1237 
1238         if(returnStatus != SUCCESS)
1239         {
1240             LTKReturnError(returnStatus);
1241         }
1242     }
1243 
1244     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1245         "NNShapeRecognizer::train()" << endl;
1246     return SUCCESS;
1247 }
1248 
1249 /**********************************************************************************
1250  * AUTHOR		: Saravanan R.
1251  * DATE			: 23-Jan-2007
1252  * NAME			: trainClustering
1253  * DESCRIPTION	: This function is the train method using Clustering prototype
1254  *				  selection technique.
1255  * ARGUMENTS		:
1256  * RETURNS		: SUCCESS : if training done successfully
1257  *				  errorCode : if traininhas some errors
1258  * NOTES			:
1259  * CHANGE HISTROY
1260  * Author			Date				Description
1261  *************************************************************************************/
trainClustering(const string & trainingInputFilePath,const string & mdtHeaderFilePath,const string & inFileType)1262 int NNShapeRecognizer::trainClustering(const string& trainingInputFilePath,
1263         const string &mdtHeaderFilePath,
1264         const string& inFileType)
1265 {
1266     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1267         "NNShapeRecognizer::trainClustering()" << endl;
1268 
1269     //Time at the beginning of Train Clustering
1270     m_OSUtilPtr->recordStartTime();
1271 
1272     int returnStatus = SUCCESS;
1273 
1274     if(LTKSTRCMP(inFileType.c_str(), INK_FILE) == 0)
1275     {
1276         //If the Input file is UNIPEN Ink file
1277         returnStatus = trainFromListFile(trainingInputFilePath);
1278         if(returnStatus != SUCCESS)
1279         {
1280             LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Error: " <<
1281                 getErrorMessage(returnStatus) <<
1282                 " NNShapeRecognizer::trainClustering()" << endl;
1283             LTKReturnError(returnStatus);
1284         }
1285     }
1286     else if(LTKSTRCMP(inFileType.c_str(), FEATURE_FILE) == 0)
1287     {
1288         //If the Input file is Feature file
1289         returnStatus = trainFromFeatureFile(trainingInputFilePath);
1290         if(returnStatus != SUCCESS)
1291         {
1292             LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Error: " <<
1293                 getErrorMessage(returnStatus) <<
1294                 " NNShapeRecognizer::trainClustering()" << endl;
1295             LTKReturnError(returnStatus);
1296         }
1297 
1298 		PreprocParametersForFeatureFile(m_headerInfo);
1299     }
1300 
1301     //Updating the Header Information
1302     updateHeaderWithAlgoInfo();
1303 
1304     //Adding header information	and checksum generation
1305     LTKCheckSumGenerate cheSumGen;
1306 
1307     returnStatus = cheSumGen.addHeaderInfo(mdtHeaderFilePath,
1308             m_nnMDTFilePath,
1309             m_headerInfo);
1310 
1311     if(returnStatus != SUCCESS)
1312     {
1313         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Error: " <<
1314             getErrorMessage(returnStatus) <<
1315             " NNShapeRecognizer::trainClustering()" << endl;
1316 
1317         LTKReturnError(returnStatus);
1318     }
1319 
1320     //Time at the end of Train Clustering
1321     m_OSUtilPtr->recordEndTime();
1322 
1323     string timeTaken = "";
1324     m_OSUtilPtr->diffTime(timeTaken);
1325 
1326     cout << "Time Taken  = " << timeTaken << endl;
1327 
1328     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1329         "NNShapeRecognizer::trainClustering()" << endl;
1330 
1331     return SUCCESS;
1332 }
1333 
1334 /**********************************************************************************
1335  * AUTHOR		: Saravanan R.
1336  * DATE			: 23-Jan-2007
1337  * NAME			: appendPrototypesToMDTFile
1338  * DESCRIPTION	:
1339  * ARGUMENTS		:
1340  * RETURNS		: none
1341  * NOTES			:
1342  * CHANGE HISTROY
1343  * Author			Date				Description
1344  *************************************************************************************/
appendPrototypesToMDTFile(const vector<LTKShapeSample> & prototypeVec,ofstream & mdtFileHandle)1345 int NNShapeRecognizer::appendPrototypesToMDTFile(const vector<LTKShapeSample>& prototypeVec,
1346         ofstream & mdtFileHandle)
1347 {
1348 
1349     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1350         "NNShapeRecognizer::appendPrototypesToMDTFile()" << endl;
1351 
1352     //iterators to iterate through the result vector
1353     vector<LTKShapeSample>::const_iterator sampleFeatureIter = prototypeVec.begin();
1354     vector<LTKShapeSample>::const_iterator sampleFeatureIterEnd = prototypeVec.end();
1355 
1356     string strFeature = "";
1357 
1358     if(!mdtFileHandle)
1359     {
1360         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_FILE_HANDLE << " " <<
1361             "Invalid file handle for MDT file"<<
1362             " NNShapeRecognizer::appendPrototypesToMDTFile()" << endl;
1363         LTKReturnError(EINVALID_FILE_HANDLE);
1364     }
1365 
1366 
1367     for(; sampleFeatureIter != sampleFeatureIterEnd; sampleFeatureIter++)
1368     {
1369         //Write the class Id
1370         int classId = (*sampleFeatureIter).getClassID();
1371 
1372         if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
1373         {
1374             mdtFileHandle << classId << " ";
1375         }
1376         else
1377         {
1378             mdtFileHandle.write((char*) &classId,sizeof(int));
1379         }
1380 
1381         const vector<LTKShapeFeaturePtr>& shapeFeatureVector = (*sampleFeatureIter).getFeatureVector();
1382 
1383         if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_BINARY )
1384         {
1385             int numberOfFeatures = shapeFeatureVector.size();
1386             int featureDimension = shapeFeatureVector[0]->getFeatureDimension();
1387 
1388             mdtFileHandle.write((char *)(&numberOfFeatures), sizeof(int));
1389             mdtFileHandle.write((char *)(&featureDimension), sizeof(int));
1390 
1391             floatVector floatFeatureVector;
1392             m_shapeRecUtil.shapeFeatureVectorToFloatVector(shapeFeatureVector,
1393                                                            floatFeatureVector);
1394 
1395             int vectorSize = floatFeatureVector.size();
1396 
1397             for (int i=0; i< vectorSize; i++)
1398             {
1399                 float floatValue = floatFeatureVector[i];
1400                 mdtFileHandle.write((char *)(&floatValue), sizeof(float));
1401             }
1402         }
1403         else
1404         {
1405 
1406             vector<LTKShapeFeaturePtr>::const_iterator shapeFeatureIter = shapeFeatureVector.begin();
1407             vector<LTKShapeFeaturePtr>::const_iterator shapeFeatureIterEnd = shapeFeatureVector.end();
1408 
1409             for(; shapeFeatureIter != shapeFeatureIterEnd; ++shapeFeatureIter)
1410             {
1411                 (*shapeFeatureIter)->toString(strFeature);
1412                 mdtFileHandle << strFeature << FEATURE_EXTRACTOR_DELIMITER;
1413             }
1414 
1415             mdtFileHandle << "\n";
1416         }
1417 
1418     }
1419 
1420     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1421         "NNShapeRecognizer::appendPrototypesToMDTFile()" << endl;
1422 
1423     return SUCCESS;
1424 }
1425 
1426 /**********************************************************************************
1427  * AUTHOR		: Saravanan R.
1428  * DATE			: 23-Jan-2007
1429  * NAME			: preprocess
1430  * DESCRIPTION	: calls the required pre-processing functions from the LTKPreprocessor library
1431  * ARGUMENTS		: inTraceGroup - reference to the input trace group
1432  *				  outPreprocessedTraceGroup - pre-processed inTraceGroup
1433  * RETURNS		: SUCCESS on successful pre-processing operation
1434  * NOTES			:
1435  * CHANGE HISTROY
1436  * Author			Date				Description
1437  *************************************************************************************/
preprocess(const LTKTraceGroup & inTraceGroup,LTKTraceGroup & outPreprocessedTraceGroup)1438 int NNShapeRecognizer::preprocess (const LTKTraceGroup& inTraceGroup,
1439         LTKTraceGroup& outPreprocessedTraceGroup)
1440 {
1441     int errorCode;
1442 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1443         "NNShapeRecognizer::preprocess()" << endl;
1444 
1445     int indx = 0;
1446 
1447     string module = "";
1448     string funName = "" ;
1449 
1450     LTKTraceGroup local_inTraceGroup;
1451 
1452     local_inTraceGroup = inTraceGroup;
1453 
1454     if(m_preprocSequence.size() != 0)
1455     {
1456         while(indx < m_preprocSequence.size())
1457         {
1458             module = m_preprocSequence.at(indx).first;
1459             funName =  m_preprocSequence.at(indx).second;
1460 
1461             FN_PTR_PREPROCESSOR pPreprocFunc = NULL;
1462             pPreprocFunc = m_ptrPreproc->getPreprocptr(funName);
1463 
1464             if(pPreprocFunc!= NULL)
1465             {
1466                 outPreprocessedTraceGroup.emptyAllTraces();
1467 
1468 
1469                 if((errorCode = (m_ptrPreproc->*(pPreprocFunc))
1470                             (local_inTraceGroup,outPreprocessedTraceGroup)) != SUCCESS)
1471                 {
1472                     LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<"Error: "<<  errorCode << " " <<
1473                         " NNShapeRecognizer::preprocess()" << endl;
1474                     LTKReturnError(errorCode);
1475                 }
1476 
1477                 local_inTraceGroup = outPreprocessedTraceGroup;
1478             }
1479             indx++;
1480         }
1481     }
1482     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Exiting NNShapeRecognizer::preprocess()"<<endl;
1483     return SUCCESS;
1484 }
1485 
1486 /**********************************************************************************
1487  * AUTHOR		: Saravanan R.
1488  * DATE			: 23-Jan-2007
1489  * NAME			: calculateMedian
1490  * DESCRIPTION	:
1491  * ARGUMENTS		:
1492  * RETURNS		:
1493  * NOTES			:
1494  * CHANGE HISTROY
1495  * Author			Date				Description
1496  *************************************************************************************/
1497 
calculateMedian(const int2DVector & clusteringResult,const float2DVector & distanceMatrix,vector<int> & outMedianIndexVec)1498 int NNShapeRecognizer::calculateMedian(const int2DVector& clusteringResult,
1499         const float2DVector& distanceMatrix, vector<int>& outMedianIndexVec)
1500 
1501 {
1502     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1503         "NNShapeRecognizer::calculateMedian()" << endl;
1504 
1505 
1506 
1507 
1508     int clusteringResultSize = clusteringResult.size();
1509 
1510     for (int clusterID = 0; clusterID < clusteringResultSize ; clusterID++)
1511     {
1512 		double minDist = FLT_MAX;
1513 		int medianIndex = -1;
1514 		for (int clusMem = 0; clusMem < clusteringResult[clusterID].size(); clusMem++)// for each element of the cluster
1515 		{
1516 			double dist = 0;
1517 			for(int otherClusMem = 0; otherClusMem < clusteringResult[clusterID].size(); otherClusMem++)
1518 			{
1519 				if(clusteringResult[clusterID][clusMem] != clusteringResult[clusterID][otherClusMem])
1520 				{
1521 					if(clusteringResult[clusterID][otherClusMem] > clusteringResult[clusterID][clusMem])
1522 					{
1523 						int tempi = clusteringResult[clusterID][clusMem];
1524 						int tempj = clusteringResult[clusterID][otherClusMem];
1525 						dist += distanceMatrix[tempi][tempj-tempi-1];
1526 					}
1527 					else
1528 					{
1529 						int tempi = clusteringResult[clusterID][otherClusMem];
1530 						int tempj = clusteringResult[clusterID][clusMem];
1531 						dist += distanceMatrix[tempi][tempj-tempi-1];
1532 					}
1533 				}
1534 			}
1535 			if(dist < minDist)
1536 			{
1537 				minDist = dist;
1538 				medianIndex = clusteringResult[clusterID][clusMem];
1539 
1540 			}
1541 
1542 		}
1543 		outMedianIndexVec.push_back(medianIndex);
1544 	}
1545     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1546         "NNShapeRecognizer::calculateMedian()" << endl;
1547 
1548     return SUCCESS;
1549 }
1550 
1551 /**********************************************************************************
1552  * AUTHOR		: Ramnath. K
1553  * DATE			: 19-05-2005
1554  * NAME			: computerDTWDistanceClusteringWrapper
1555  * DESCRIPTION	: Wrapper function to the function whichcomputes DTW distance between
1556  two characters
1557  * ARGUMENTS		: train character, test character
1558  * RETURNS		: DTWDistance
1559  * NOTES			:
1560  * CHANGE HISTROY
1561  * Author			Date				Description
1562  *************************************************************************************/
computeDTWDistance(const LTKShapeSample & inFirstShapeSampleFeatures,const LTKShapeSample & inSecondShapeSampleFeatures,float & outDTWDistance)1563 int NNShapeRecognizer::computeDTWDistance(
1564         const LTKShapeSample& inFirstShapeSampleFeatures,
1565         const LTKShapeSample& inSecondShapeSampleFeatures,
1566         float& outDTWDistance)
1567 
1568 {
1569     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1570         "NNShapeRecognizer::computeDTWDistance()" << endl;
1571 
1572     const vector<LTKShapeFeaturePtr>& firstFeatureVec = inFirstShapeSampleFeatures.getFeatureVector();
1573     const vector<LTKShapeFeaturePtr>& secondFeatureVec = inSecondShapeSampleFeatures.getFeatureVector();
1574 
1575     int errorCode = m_dtwObj.computeDTW(firstFeatureVec, secondFeatureVec, getDistance,outDTWDistance,
1576             m_dtwBanding, FLT_MAX, FLT_MAX);
1577 
1578     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "DTWDistance: " <<
1579         outDTWDistance << endl;
1580 
1581     if (errorCode != SUCCESS )
1582     {
1583         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Error: "<<
1584             getErrorMessage(errorCode) <<
1585             " NNShapeRecognizer::computeDTWDistance()" << endl;
1586         LTKReturnError(errorCode);
1587     }
1588 
1589     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1590         "NNShapeRecognizer::computeDTWDistance()" << endl;
1591 
1592     return SUCCESS;
1593 }
1594 
1595 
1596 /**********************************************************************************
1597  * AUTHOR		: Sridhar Krishna
1598  * DATE			: 24-04-2006
1599  * NAME			: computeEuclideanDistance
1600  * DESCRIPTION	: computes euclidean distance between two characters
1601  * ARGUMENTS		: LTKShapeFeaturePtrtor - 2
1602  * RETURNS		: euclidean distance
1603  * NOTES			:
1604  * CHANGE HISTROY
1605  * Author			Date				Description
1606  *************************************************************************************/
computeEuclideanDistance(const LTKShapeSample & inFirstShapeSampleFeatures,const LTKShapeSample & inSecondShapeSampleFeatures,float & outEuclideanDistance)1607 int NNShapeRecognizer::computeEuclideanDistance(
1608         const LTKShapeSample& inFirstShapeSampleFeatures,
1609         const LTKShapeSample& inSecondShapeSampleFeatures,
1610         float& outEuclideanDistance)
1611 {
1612     const vector<LTKShapeFeaturePtr>& firstFeatureVec = inFirstShapeSampleFeatures.getFeatureVector();
1613     const vector<LTKShapeFeaturePtr>& secondFeatureVec = inSecondShapeSampleFeatures.getFeatureVector();
1614 
1615     int firstFeatureVectorSize = firstFeatureVec.size();
1616     int secondFeatureVectorSize = secondFeatureVec.size();
1617 
1618     if(firstFeatureVectorSize != secondFeatureVectorSize)
1619     {
1620         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EUNEQUAL_LENGTH_VECTORS << " " <<
1621             getErrorMessage(EUNEQUAL_LENGTH_VECTORS) <<
1622             " NNShapeRecognizer::computeEuclideanDistance()" << endl;
1623 
1624         LTKReturnError(EUNEQUAL_LENGTH_VECTORS);
1625     }
1626 
1627     for(int i = 0; i < firstFeatureVectorSize; ++i)
1628     {
1629         float tempDistance = 0.0f;
1630         getDistance(firstFeatureVec[i],
1631                 secondFeatureVec[i],
1632                 tempDistance);
1633         outEuclideanDistance += tempDistance;
1634     }
1635 
1636     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1637         "NNShapeRecognizer::computeEuclideanDistance()" << endl;
1638     return SUCCESS;
1639 }
1640 
1641 
1642 /**********************************************************************************
1643  * AUTHOR		: Saravanan. R
1644  * DATE			: 23-01-2007
1645  * NAME			: loadModelData
1646  * DESCRIPTION	: loads the reference model file into memory
1647  * ARGUMENTS		:
1648  * RETURNS		: SUCCESS on successful loading of the reference model file
1649  * NOTES			:
1650  * CHANGE HISTROY
1651  * Author			Date				Description
1652  *************************************************************************************/
loadModelData()1653 int NNShapeRecognizer::loadModelData()
1654 {
1655     int errorCode;
1656 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1657         "NNShapeRecognizer::loadModelData()" << endl;
1658 
1659     int numofShapes = 0;
1660 
1661     // variable for shape Id
1662     int classId = -1;
1663 
1664     //Algorithm version
1665     string algoVersionReadFromMDT = "";
1666 
1667 //    int iMajor, iMinor, iBugfix = 0;
1668 
1669     stringStringMap headerSequence;
1670     LTKCheckSumGenerate cheSumGen;
1671 
1672     if(errorCode = cheSumGen.readMDTHeader(m_nnMDTFilePath,headerSequence))
1673     {
1674         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
1675             " NNShapeRecognizer::loadModelData()" << endl;
1676         LTKReturnError(errorCode);
1677     }
1678 
1679 	// printing the headerseqn
1680 	stringStringMap::const_iterator iter = headerSequence.begin();
1681 	stringStringMap::const_iterator endIter = headerSequence.end();
1682 
1683 	for(; iter != endIter; iter++)
1684 	{
1685 		LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Debug: header seqn"<<
1686             iter->first << " : " <<
1687             iter->second << endl;
1688 	}
1689 
1690     string featureExtractor = headerSequence[FE_NAME];
1691 
1692     if(LTKSTRCMP(m_featureExtractorName.c_str(), featureExtractor.c_str()) != 0)
1693     {
1694         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
1695             "Value of FeatureExtractor parameter in config file ("<<
1696             m_featureExtractorName<<") does not match with the value in MDT file ("<<
1697             featureExtractor<<")"<<
1698             " NNShapeRecognizer::loadModelData()" << endl;
1699         LTKReturnError(ECONFIG_MDT_MISMATCH);
1700     }
1701 
1702     string feVersion = headerSequence[FE_VER];
1703 
1704     // comparing the mdt open mode read from cfg file with value in the mdt header
1705     string mdtOpenMode = headerSequence[MDT_FOPEN_MODE];
1706 
1707     if (LTKSTRCMP(m_MDTFileOpenMode.c_str(), mdtOpenMode.c_str()) != 0)
1708     {
1709         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
1710             "Value of NNMDTFileOpenMode parameter in config file ("<<
1711             m_MDTFileOpenMode <<") does not match with the value in MDT file ("<<
1712             mdtOpenMode<<")"<<
1713             " NNShapeRecognizer::loadModelData()" << endl;
1714         LTKReturnError(ECONFIG_MDT_MISMATCH);
1715     }
1716 
1717 
1718     // validating preproc parameters
1719     int iErrorCode = validatePreprocParameters(headerSequence);
1720     if (iErrorCode != SUCCESS )
1721     {
1722     	LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
1723             "Values of NNMDTFileOpenMode parameter in config file does not match with "
1724             <<"the values in MDT file " << "NNShapeRecognizer::loadModelData()" << endl;
1725 
1726         LTKReturnError(ECONFIG_MDT_MISMATCH);
1727     }
1728 
1729     // Version comparison START
1730     algoVersionReadFromMDT = headerSequence[RECVERSION].c_str();
1731 
1732     LTKVersionCompatibilityCheck verTempObj;
1733     string supportedMinVersion(SUPPORTED_MIN_VERSION);
1734     string currentVersionStr(m_currentVersion);
1735 
1736     bool compatibilityResults = verTempObj.checkCompatibility(supportedMinVersion,
1737             currentVersionStr,
1738             algoVersionReadFromMDT);
1739 
1740     if(compatibilityResults == false)
1741     {
1742         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINCOMPATIBLE_VERSION << " " <<
1743             " Incompatible version"<<
1744             " NNShapeRecognizer::loadModelData()" << endl;
1745         LTKReturnError(EINCOMPATIBLE_VERSION);
1746     }
1747     // Version comparison END
1748 
1749     //Input Stream for Model Data file
1750     ifstream mdtFileHandle;
1751 
1752     if (m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
1753     {
1754         mdtFileHandle.open(m_nnMDTFilePath.c_str(), ios::in);
1755     }
1756     else
1757     {
1758         mdtFileHandle.open(m_nnMDTFilePath.c_str(), ios::in | ios::binary);
1759     }
1760 
1761     //If error while opening, return an error
1762     if(!mdtFileHandle)
1763     {
1764         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EMODEL_DATA_FILE_OPEN << " " <<
1765             " Unable to open model data file : " <<m_nnMDTFilePath<<
1766             " NNShapeRecognizer::loadModelData()" << endl;
1767         LTKReturnError(EMODEL_DATA_FILE_OPEN);
1768     }
1769 
1770     mdtFileHandle.seekg(atoi(headerSequence[HEADERLEN].c_str()),ios::beg);
1771 
1772     //Read the number of shapes
1773     if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
1774     {
1775         mdtFileHandle >> numofShapes;
1776     }
1777     else
1778     {
1779         mdtFileHandle.read((char*) &numofShapes,
1780                             atoi(headerSequence[SIZEOFSHORTINT].c_str()));
1781     }
1782 
1783     if(!m_projectTypeDynamic && m_numShapes != numofShapes)
1784     {
1785         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< ECONFIG_MDT_MISMATCH << " " <<
1786             " Value of NumShapes parameter in config file ("<<m_numShapes<<
1787             ") does not match with the value in MDT file ("<<numofShapes<<")"<<
1788             " NNShapeRecognizer::loadModelData()" << endl;
1789         LTKReturnError(ECONFIG_MDT_MISMATCH);
1790     }
1791 
1792     if(m_projectTypeDynamic)
1793     {
1794         m_numShapes = numofShapes;
1795     }
1796 
1797     // validating the header values
1798 
1799     stringVector tokens;
1800     stringVector classToken;
1801 
1802     string strFeatureVector = "";
1803 
1804     LTKShapeSample shapeSampleFeatures;
1805 
1806     int floatSize = atoi(headerSequence[SIZEOFFLOAT].c_str());
1807 
1808 	int intSize = atoi(headerSequence[SIZEOFINT].c_str());
1809 
1810 
1811 	if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
1812 	{
1813 		while(getline(mdtFileHandle, strFeatureVector, NEW_LINE_DELIMITER ))
1814 		{
1815 			LTKStringUtil::tokenizeString(strFeatureVector,
1816 					CLASSID_FEATURES_DELIMITER,  classToken);
1817 
1818 			if(classToken.size() != 2)
1819 				continue;
1820 
1821 			classId = atoi((classToken[0]).c_str());
1822 
1823 			if(classId == -1)
1824 				continue;
1825 
1826 			LTKStringUtil::tokenizeString(classToken[1],  FEATURE_EXTRACTOR_DELIMITER,  tokens);
1827 
1828 			vector<LTKShapeFeaturePtr> shapeFeatureVector;
1829 			LTKShapeFeaturePtr shapeFeature;
1830 
1831 			for(int i = 0; i < tokens.size(); ++i)
1832 			{
1833 				shapeFeature = m_ptrFeatureExtractor->getShapeFeatureInstance();
1834 
1835 				if (shapeFeature->initialize(tokens[i]) != SUCCESS)
1836 				{
1837 					LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_INPUT_FORMAT << " " <<
1838 						"Number of features extracted from a trace is not correct"<<
1839 						" NNShapeRecognizer::loadModelData()" << endl;
1840 
1841 					LTKReturnError(EINVALID_INPUT_FORMAT);
1842 				}
1843 
1844 				shapeFeatureVector.push_back(shapeFeature);
1845 			}
1846 			//Set the feature vector and class id to the shape sample features
1847 			shapeSampleFeatures.setFeatureVector(shapeFeatureVector);
1848 			shapeSampleFeatures.setClassID(classId);
1849 
1850 			//cout << "load mdt class id :" << classId << endl;
1851 			//Adding all shape sample feature to the prototypeset
1852 			m_prototypeSet.push_back(shapeSampleFeatures);
1853 			//Add to Map
1854 			if(	m_shapeIDNumPrototypesMap.find(classId)==m_shapeIDNumPrototypesMap.end())
1855 			{
1856 				m_shapeIDNumPrototypesMap[classId] = 1;
1857 			}
1858 			else
1859 			{
1860 				++(m_shapeIDNumPrototypesMap[classId]);
1861 			}
1862 
1863 
1864 			//Clearing the vectors
1865 			shapeFeatureVector.clear();
1866 			tokens.clear();
1867 			classToken.clear();
1868 			classId = -1;
1869 			strFeatureVector = "";
1870 
1871 
1872 		}
1873 	}
1874 
1875 	else
1876 	{
1877 		floatVector floatFeatureVectorBuffer;
1878 
1879 		while(!mdtFileHandle.eof())
1880 		{
1881 			mdtFileHandle.read((char*) &classId, intSize);
1882 
1883 			if ( mdtFileHandle.fail() )
1884 			{
1885 				break;
1886 			}
1887 
1888 			int numberOfFeatures;
1889 			int featureDimension;
1890 
1891 			mdtFileHandle.read((char*) &numberOfFeatures, intSize);
1892 			mdtFileHandle.read((char*) &featureDimension, intSize);
1893 
1894 			m_prototypeSet.push_back(shapeSampleFeatures);
1895 			LTKShapeSample &shapeSampleFeaturesRef = m_prototypeSet.back();
1896 			shapeSampleFeaturesRef.setClassID(classId);
1897 
1898 			// Read all features in one batch
1899 			size_t floatFeatureVectorElementCount = numberOfFeatures * featureDimension;
1900 			floatFeatureVectorBuffer.resize(floatFeatureVectorElementCount);
1901 			mdtFileHandle.read((char*) &floatFeatureVectorBuffer.front(), floatFeatureVectorElementCount * floatSize);
1902 			if ( mdtFileHandle.fail() )
1903 			{
1904 				break;
1905 			}
1906 
1907 			int featureIndex = 0;
1908 
1909 			vector<LTKShapeFeaturePtr>& shapeFeatureVector = shapeSampleFeaturesRef.getFeatureVectorRef();
1910 			shapeFeatureVector.reserve(numberOfFeatures);
1911 			floatVector::const_pointer floatFeatureVectorData = floatFeatureVectorBuffer.data();
1912 			LTKShapeFeaturePtr shapeFeature;
1913 
1914 			for ( ; featureIndex < numberOfFeatures ; featureIndex++)
1915 			{
1916 
1917 				shapeFeature = m_ptrFeatureExtractor->getShapeFeatureInstance();
1918 
1919 				if (shapeFeature->initialize(floatFeatureVectorData + featureIndex * featureDimension, featureDimension) != SUCCESS)
1920 				{
1921 					LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<
1922 						EINVALID_INPUT_FORMAT << " " <<
1923 						"Number of features extracted from a trace is not correct"<<
1924 						" NNShapeRecognizer::loadModelData()" << endl;
1925 
1926 					LTKReturnError(EINVALID_INPUT_FORMAT);
1927 				}
1928 
1929 				shapeFeatureVector.push_back(shapeFeature);
1930 
1931 			}
1932 
1933 			//Add to Map
1934 			intIntMap::iterator mapEntry;
1935 			if(	(mapEntry = m_shapeIDNumPrototypesMap.find(classId))==m_shapeIDNumPrototypesMap.end())
1936 			{
1937 				m_shapeIDNumPrototypesMap[classId] = 1;
1938 			}
1939 			else
1940 			{
1941 				++mapEntry->second;
1942 			}
1943 		}
1944 	}
1945 
1946 	mdtFileHandle.close();
1947 
1948     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
1949         "NNShapeRecognizer::loadModelData()" << endl;
1950 
1951     return SUCCESS;
1952 }
1953 
1954 /**********************************************************************************
1955  * AUTHOR		: Saravanan R.
1956  * DATE			: 2-Mar-2007
1957  * NAME			: sortDist
1958  * DESCRIPTION	:
1959  * ARGUMENTS		:
1960  * RETURNS		:
1961  * NOTES			:
1962  * CHANGE HISTROY
1963  * Author			Date				Description
1964  *************************************************************************************/
sortDist(const NeighborInfo & x,const NeighborInfo & y)1965 bool NNShapeRecognizer::sortDist(const NeighborInfo& x, const NeighborInfo& y)
1966 {
1967     return (x.distance) < (y.distance);
1968 }
1969 
1970 /**********************************************************************************
1971  * AUTHOR		: Saravanan. R
1972  * DATE			: 23-01-2007
1973  * NAME			: recognize
1974  * DESCRIPTION	: recognizes the incoming tracegroup
1975  * ARGUMENTS		: inTraceGroup - trace group to be recognized
1976  *				  screenContext - screen context
1977  *				  subSetOfClasses - subset of classes whose samples will be compared with traceGroup
1978  *				  confThreshold - classes with confidence below this threshold are not returned, valid range of confThreshold: (0,1)
1979  *				  numChoices - maximum number of choices to be returned
1980  *				  outResultVector - result of recognition
1981  * RETURNS		: SUCCESS on successful running of the code
1982  * NOTES			:
1983  * CHANGE HISTROY
1984  * Author : 	Date				Description
1985  *************************************************************************************/
recognize(const LTKTraceGroup & traceGroup,const LTKScreenContext & screenContext,const vector<int> & inSubSetOfClasses,float confThreshold,int numChoices,vector<LTKShapeRecoResult> & outResultVector)1986 int NNShapeRecognizer::recognize(const LTKTraceGroup& traceGroup,
1987         const LTKScreenContext& screenContext,
1988         const vector<int>& inSubSetOfClasses,
1989         float confThreshold,
1990         int  numChoices,
1991         vector<LTKShapeRecoResult>& outResultVector)
1992 {
1993 	int errorCode;
1994 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
1995         "NNShapeRecognizer::recognize()" << endl;
1996 
1997 
1998     //Check for empty traces in traceGroup
1999 
2000     if(traceGroup.containsAnyEmptyTrace())
2001     {
2002         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<EEMPTY_TRACE << " " <<
2003             " Input trace is empty"<<
2004             " NNShapeRecognizer::recognize()" << endl;
2005         LTKReturnError(EEMPTY_TRACE);
2006     }
2007 
2008 
2009     //Contains TraceGroup after Preprocessing is done
2010     LTKTraceGroup preprocessedTraceGroup;
2011 
2012 
2013     //Preprocess the traceGroup
2014     if( preprocess(traceGroup, preprocessedTraceGroup) != SUCCESS)
2015     {
2016         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
2017             getErrorMessage(errorCode)<<
2018             " NNShapeRecognizer::recognize()" << endl;
2019         LTKReturnError(errorCode);
2020     }
2021 
2022     //Extract the shapeSample from preprocessedTraceGroup
2023     if(!m_ptrFeatureExtractor)
2024     {
2025         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< ENULL_POINTER << " " <<
2026             " m_ptrFeatureExtractor is NULL"<<
2027             " NNShapeRecognizer::recognize()" << endl;
2028         LTKReturnError(ENULL_POINTER);
2029     }
2030 
2031     vector<LTKShapeFeaturePtr> shapeFeatureVec;
2032     errorCode = m_ptrFeatureExtractor->extractFeatures(preprocessedTraceGroup,
2033             shapeFeatureVec);
2034 
2035     if (errorCode != SUCCESS)
2036     {
2037         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
2038             " NNShapeRecognizer::recognize()" << endl;
2039 
2040         LTKReturnError(errorCode);
2041     }
2042 
2043 	// call recognize with featureVector
2044 
2045 	if(recognize( shapeFeatureVec, inSubSetOfClasses, confThreshold,
2046 			numChoices, outResultVector) != SUCCESS)
2047 	{
2048 		LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
2049             getErrorMessage(errorCode)<<
2050             " NNShapeRecognizer::recognize()" << endl;
2051         LTKReturnError(errorCode);
2052 
2053 	}
2054 
2055 
2056 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
2057         "NNShapeRecognizer::recognize()" << endl;
2058 
2059     return SUCCESS;
2060 
2061 }
2062 
2063 
recognize(const vector<LTKShapeFeaturePtr> & shapeFeatureVector,const vector<int> & inSubSetOfClasses,float confThreshold,int numChoices,vector<LTKShapeRecoResult> & outResultVector)2064 int NNShapeRecognizer::recognize(const vector<LTKShapeFeaturePtr>& shapeFeatureVector,
2065 			const vector<int>& inSubSetOfClasses,
2066 			float confThreshold,
2067 			int  numChoices,
2068 			vector<LTKShapeRecoResult>& outResultVector)
2069 {
2070 	int errorCode;
2071     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
2072         "NNShapeRecognizer::recognize()" << endl;
2073 
2074     m_cancelRecognition = false;
2075 
2076     m_cachedShapeSampleFeatures.setFeatureVector(shapeFeatureVector);
2077 
2078     //Creating a local copy of input inSubSetOfClasses, as it is const, STL's unique function modifies it!!!
2079     vector<int> subSetOfClasses = inSubSetOfClasses;
2080 
2081 	int numPrototypes = m_prototypeSet.size();
2082 
2083     /*********Validation for m_prototypeSet ***************************/
2084     if ( numPrototypes == 0 )
2085     {
2086         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EPROTOTYPE_SET_EMPTY << " " <<
2087             " getErrorMessage(EPROTOTYPE_SET_EMPTY) "<<
2088             " NNShapeRecognizer::recognize()" << endl;
2089         LTKReturnError(EPROTOTYPE_SET_EMPTY); //modify
2090     }
2091 
2092 	int dtwEuclideanFilter = (m_dtwEuclideanFilter == EUCLIDEAN_FILTER_OFF)?
2093                                               EUCLIDEAN_FILTER_OFF : (int)((m_dtwEuclideanFilter * numPrototypes) / 100);
2094 
2095 	if(dtwEuclideanFilter == 0)
2096 		dtwEuclideanFilter = EUCLIDEAN_FILTER_OFF;
2097 
2098 	if( dtwEuclideanFilter != EUCLIDEAN_FILTER_OFF && dtwEuclideanFilter < m_nearestNeighbors)
2099 	{
2100 
2101 		LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<
2102 			"Error: " << ECONFIG_FILE_RANGE <<
2103 			DTWEUCLIDEANFILTER << " is out of permitted range " <<
2104 			" NNShapeRecognizer::recognize()"<<endl;
2105 
2106 		LTKReturnError(ECONFIG_FILE_RANGE);
2107 		//	dtwEuclideanFilter = EUCLIDEAN_FILTER_OFF;
2108 	}
2109 
2110 	/******************************************************************/
2111     /*******************VALIDATING INPUT ARGUMENTS*********************/
2112     /******************************************************************/
2113 
2114     // Validating numChoices: valid values: {-1, (0,m_numShapes]}
2115     if(numChoices <= 0 && numChoices != NUM_CHOICES_FILTER_OFF)
2116     {
2117         LOG(LTKLogger::LTK_LOGLEVEL_INFO)<<
2118             "numChoices ("<<numChoices<<")<=0, setting it to off (-1)"<<endl;
2119         numChoices = -1;
2120     }
2121 
2122     if(!m_projectTypeDynamic && numChoices > m_numShapes)
2123     {
2124         LOG(LTKLogger::LTK_LOGLEVEL_INFO)<<
2125             "numChoices ("<<numChoices<<") > numShapes ("<<
2126             m_numShapes<<"), using numShapes "<<m_numShapes<<" instead"<<endl;
2127         numChoices = m_numShapes;
2128     }
2129 
2130 
2131     //Validating confThreshold: valid values: [0,1]
2132     if(confThreshold > 1 || confThreshold < 0)
2133     {
2134 
2135         LOG(LTKLogger::LTK_LOGLEVEL_INFO)<<
2136             "Invalid value of confThreshold, valid values are: [0,1]"<<endl;
2137         LTKReturnError(ECONFIG_FILE_RANGE);
2138     }
2139 
2140 
2141 
2142     /*****************************************************************************************/
2143     /*********************** DECLARING IMPORTANT LOCAL VARIABLES *****************************/
2144     /*****************************************************************************************/
2145 
2146     //Variable to store the DTW distance.
2147     float dtwDistance = 0.0f;
2148 
2149     //Variable to store the Euclidean distance.
2150     float euclideanDistance = 0.0f;
2151 
2152 
2153     // begin and end iterators for m_prototypeSet
2154     vector<LTKShapeSample>::iterator prototypeSetIter = m_prototypeSet.begin();
2155     vector<LTKShapeSample>::iterator prototypeSetIterEnd = m_prototypeSet.end();
2156 
2157     //iterator for iterating the input shape subset vector
2158 
2159     vector<int>::iterator subSetOfClassesIter;
2160 
2161     int prototypeIndexOffset=0;
2162 
2163     int numPrototypesForSubset=0;
2164 
2165     if(subSetOfClasses.size()>0)
2166     {
2167         sort(subSetOfClasses.begin(),subSetOfClasses.end());
2168         subSetOfClasses.erase(unique(subSetOfClasses.begin(),subSetOfClasses.end()),subSetOfClasses.end());
2169     }
2170 
2171 	// Clearing cached Variables
2172     m_vecRecoResult.clear();
2173     m_neighborInfoVec.clear();
2174 
2175     //Temporary variable to be used to populate distIndexPairVector
2176     struct NeighborInfo tempPair;
2177 
2178 
2179     /***************End of declarations and initializations of variables**************/
2180 
2181 
2182 
2183     /***************************************************************/
2184     /*************** Computation of Distance ***********************/
2185     /***************************************************************/
2186 
2187 
2188     if(subSetOfClasses.size()>0)
2189     {
2190         vector<int>::iterator tempSubsetIter = subSetOfClasses.begin();
2191         vector<int>::iterator tempSubsetIterEnd = subSetOfClasses.end();
2192 
2193         for(; tempSubsetIter!= tempSubsetIterEnd; ++tempSubsetIter)
2194         {
2195             if(m_shapeIDNumPrototypesMap.find(*tempSubsetIter)==m_shapeIDNumPrototypesMap.end())
2196             {
2197                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_SHAPEID << " " <<
2198                     "Invalid class ID in the shape subset vector:"<<(*tempSubsetIter)<<
2199                     " NNShapeRecognizer::recognize()" << endl;
2200                 LTKReturnError(EINVALID_SHAPEID);
2201             }
2202             else
2203             {
2204                 numPrototypesForSubset = numPrototypesForSubset + m_shapeIDNumPrototypesMap[*tempSubsetIter];
2205             }
2206         }
2207 
2208         if(dtwEuclideanFilter!= EUCLIDEAN_FILTER_OFF)
2209         {
2210             if(numPrototypesForSubset < dtwEuclideanFilter)
2211             {
2212                 LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) <<
2213                     "Number of prototypes corresponding to subset of classes asked for is less than Euclidean filter size; switching Euclidean filter off" << endl;
2214                 dtwEuclideanFilter = EUCLIDEAN_FILTER_OFF;
2215             }
2216         }
2217 
2218         subSetOfClassesIter=subSetOfClasses.begin();
2219     }
2220     // If Euclidean filter size >= size of the m_prototypeSet, do not use twEuclideanFilter
2221     else if(subSetOfClasses.size()==0 && dtwEuclideanFilter >= m_prototypeSet.size())
2222     {
2223         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) <<
2224             "dtwEuclideanFilter >= m_prototypeSet.size(), switching Euclidean filter off" << endl;
2225         dtwEuclideanFilter = EUCLIDEAN_FILTER_OFF;
2226     }
2227 
2228     // If the distance metric is Euclidean, compute the distances of test sample to all the samples in the prototype set
2229     if(LTKSTRCMP(m_prototypeDistance.c_str(), EUCLIDEAN_DISTANCE) == 0)
2230     {
2231         for (int j = 0; prototypeSetIter != prototypeSetIterEnd; )
2232         {
2233 
2234             if(subSetOfClasses.size()>0)
2235             {
2236                 if((*prototypeSetIter).getClassID()<(*subSetOfClassesIter))
2237                 {
2238                     j=j + m_shapeIDNumPrototypesMap[(*prototypeSetIter).getClassID()];
2239                     prototypeSetIter=prototypeSetIter +
2240                         m_shapeIDNumPrototypesMap[(*prototypeSetIter).getClassID()];
2241 
2242                     continue;
2243                 }
2244 
2245 
2246             }
2247             if(subSetOfClasses.size()==0 || (*prototypeSetIter).getClassID()==(*subSetOfClassesIter))
2248             {
2249                 while(subSetOfClasses.size()==0 || (*prototypeSetIter).getClassID()==(*subSetOfClassesIter))
2250                 {
2251 					euclideanDistance = 0.0f;
2252                     errorCode = computeEuclideanDistance(*prototypeSetIter,
2253                             m_cachedShapeSampleFeatures,
2254                             euclideanDistance);
2255 
2256                     if(errorCode == SUCCESS && m_cancelRecognition)
2257                         return SUCCESS;
2258 
2259                     if(errorCode != SUCCESS)
2260                     {
2261                         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
2262                             " NNShapeRecognizer::recognize()" << endl;
2263 
2264                         LTKReturnError(errorCode);
2265 
2266                     }
2267 
2268                     tempPair.distance = euclideanDistance;
2269                     tempPair.classId = (*prototypeSetIter).getClassID();
2270                     tempPair.prototypeSetIndex = j;
2271 
2272                     m_neighborInfoVec.push_back(tempPair);
2273                     ++prototypeSetIter;
2274                     ++j;
2275 
2276                     if(prototypeSetIter==m_prototypeSet.end())
2277                     {
2278                         break;
2279                     }
2280                 }
2281 
2282                 if(subSetOfClasses.size()>0)
2283                 {
2284                     ++subSetOfClassesIter;
2285                     if(subSetOfClassesIter==subSetOfClasses.end())
2286                     {
2287                         break;
2288                     }
2289                 }
2290             }
2291         }
2292     }
2293     // If the distance metric is DTW
2294     else if(LTKSTRCMP(m_prototypeDistance.c_str(), DTW_DISTANCE) == 0)
2295     {
2296         vector<bool> filterVector(m_prototypeSet.size(), true);
2297 
2298         // If Euclidean Filter is specified, find Euclidean distance to all the samples in the prototypeset,
2299         // choose the top dtwEuclideanFilter number of prototypes, to which the DTW distance will be computed.
2300         if(dtwEuclideanFilter != EUCLIDEAN_FILTER_OFF)
2301         {
2302             vector <struct NeighborInfo> eucDistIndexPairVector;
2303 
2304             filterVector.assign(m_prototypeSet.size(), false);
2305 
2306 
2307             for (int j = 0; prototypeSetIter != prototypeSetIterEnd;)
2308             {
2309                 if(subSetOfClasses.size()>0)
2310                 {
2311                     if((*prototypeSetIter).getClassID()<(*subSetOfClassesIter))
2312                     {
2313 
2314                         j=j + m_shapeIDNumPrototypesMap[(*prototypeSetIter).getClassID()];
2315                         prototypeSetIter = prototypeSetIter + m_shapeIDNumPrototypesMap
2316                             [(*prototypeSetIter).getClassID()];
2317 
2318                         continue;
2319                     }
2320                 }
2321                 if(subSetOfClasses.size()==0 || (*prototypeSetIter).getClassID()==(*subSetOfClassesIter))
2322                 {
2323                     while(subSetOfClasses.size()==0 ||
2324                             (*prototypeSetIter).getClassID()==(*subSetOfClassesIter))
2325                     {
2326 						euclideanDistance = 0.0f;
2327                         errorCode = computeEuclideanDistance(*prototypeSetIter,
2328                                 m_cachedShapeSampleFeatures,
2329                                 euclideanDistance);
2330 
2331                         if(errorCode == SUCCESS && m_cancelRecognition)
2332                             return SUCCESS;
2333 
2334                         if(errorCode != SUCCESS)
2335                         {
2336                             LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
2337                                 " NNShapeRecognizer::recognize()" << endl;
2338 
2339                             LTKReturnError(errorCode);
2340                         }
2341 
2342 
2343                         tempPair.distance = euclideanDistance;
2344                         tempPair.classId = (*prototypeSetIter).getClassID();
2345                         tempPair.prototypeSetIndex = j;
2346 
2347                         eucDistIndexPairVector.push_back(tempPair);
2348                         ++prototypeSetIter;
2349                         ++j;
2350 
2351                         if(prototypeSetIter==m_prototypeSet.end())
2352                         {
2353                             break;
2354                         }
2355                     }
2356 
2357                     if(subSetOfClasses.size()>0)
2358                     {
2359                         ++subSetOfClassesIter;
2360                         if(subSetOfClassesIter==subSetOfClasses.end())
2361                         {
2362                             break;
2363                         }
2364                     }
2365                 }
2366             }
2367 
2368             //Sort the eucDistIndexPairVector in ascending order of distance, and used only top dtwEuclideanFilter for DTW distance computation
2369             sort(eucDistIndexPairVector.begin(), eucDistIndexPairVector.end(), sortDist);
2370 
2371             for (int z = 0; z < dtwEuclideanFilter; ++z )
2372             {
2373                 int prototypeSetIndex = eucDistIndexPairVector[z].prototypeSetIndex ;
2374                 filterVector[prototypeSetIndex] = true;
2375             }
2376         }
2377         else
2378         {
2379             if(subSetOfClasses.size()>0)
2380             {
2381                 filterVector.assign(m_prototypeSet.size(), false);
2382 
2383                 for(map<int,int>::iterator shapeIDNumPrototypesMapIter=m_shapeIDNumPrototypesMap.begin();
2384                         shapeIDNumPrototypesMapIter!=m_shapeIDNumPrototypesMap.end();)
2385                 {
2386                     if(shapeIDNumPrototypesMapIter->first<(*subSetOfClassesIter))
2387                     {
2388 
2389                         prototypeIndexOffset=prototypeIndexOffset +
2390                             shapeIDNumPrototypesMapIter->second;
2391 
2392                         ++shapeIDNumPrototypesMapIter;
2393 
2394                         continue;
2395                     }
2396                     else if(shapeIDNumPrototypesMapIter->first==(*subSetOfClassesIter))
2397                     {
2398                         while(m_prototypeSet[prototypeIndexOffset].getClassID()==
2399 							(*subSetOfClassesIter))
2400                         {
2401                             filterVector[prototypeIndexOffset]=true;
2402                             ++prototypeIndexOffset;
2403 							if( prototypeIndexOffset == m_prototypeSet.size())								break;                        }
2404 						 if(subSetOfClassesIter==subSetOfClasses.end())                        {                            break;                        }                        //filterVector.assign(filterVector.begin()+prototypeIndexOffset,filterVector.begin()+prototypeIndexOffset+shapeIDNumPrototypesMapIter->second,true);
2405                         ++shapeIDNumPrototypesMapIter;
2406                         ++subSetOfClassesIter;
2407                         if(subSetOfClassesIter==subSetOfClasses.end())
2408                         {
2409                             break;
2410                         }
2411 
2412                     }
2413                 }
2414             }
2415         }
2416 
2417 
2418         //Iterate through all the prototypes, and compute DTW distance to the prototypes for which corresponding entry in filterVector is true
2419         for (int i = 0 ; i < m_prototypeSet.size(); ++i )
2420         {
2421 
2422             if(filterVector[i])
2423             {
2424 				dtwDistance = 0.0f;
2425                 errorCode = computeDTWDistance(m_prototypeSet[i],
2426                         m_cachedShapeSampleFeatures,
2427                         dtwDistance);
2428 
2429                 if(errorCode == SUCCESS && m_cancelRecognition)
2430                     return SUCCESS;
2431 
2432                 if(errorCode != SUCCESS)
2433                 {
2434                     LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
2435                         " NNShapeRecognizer::recognize()" << endl;
2436 
2437                     LTKReturnError(errorCode);
2438                 }
2439 
2440                 tempPair.distance = dtwDistance;
2441                 tempPair.classId = (m_prototypeSet[i]).getClassID();
2442                 tempPair.prototypeSetIndex = i;
2443                 m_neighborInfoVec.push_back(tempPair);
2444             }
2445         }
2446 
2447         filterVector.clear();
2448 
2449     }
2450     else
2451     {
2452         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< ECONFIG_FILE_RANGE << " " <<
2453             "The selected prototype distance method \""<<
2454             m_prototypeDistance<<"\" is not supported "<<
2455             " NNShapeRecognizer::recognize()" << endl;
2456         LTKReturnError(ECONFIG_FILE_RANGE);
2457     }
2458 
2459 
2460     //Sort the distIndexPairVector based on distances, in ascending order.
2461     sort(m_neighborInfoVec.begin(), m_neighborInfoVec.end(), sortDist);
2462 
2463     //Reject the sample if the similarity of the nearest sample is lower than m_rejectThreshold specified by the user.
2464     if(SIMILARITY(m_neighborInfoVec[0].distance) <= m_rejectThreshold)
2465     {
2466 
2467         m_vecRecoResult.clear();
2468         LOG(LTKLogger::LTK_LOGLEVEL_INFO)<<"Test sample too distinct, rejecting the sample"<<endl;
2469         return SUCCESS;
2470     }
2471 
2472     //Compute the confidences of the classes appearing in distIndexPairVector
2473     //outResultVector is an output argument, populated in computeConfidence()
2474     if((errorCode = computeConfidence()) != SUCCESS)
2475     {
2476         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
2477             " NNShapeRecognizer::recognize()" << endl;
2478         LTKReturnError(errorCode);
2479     }
2480 
2481     // Temporary result vector to store the results based on confThreshold and numChoices specified by the user.
2482     vector<LTKShapeRecoResult> tempResultVector;
2483 
2484     //If confThreshold is specified, get the entries from resultVector with confidence >= confThreshold
2485     if(confThreshold != CONF_THRESHOLD_FILTER_OFF)
2486     {
2487         for(int i = 0 ; i < m_vecRecoResult.size() ; i++)
2488         {
2489             if( m_vecRecoResult[i].getConfidence() >= confThreshold)
2490             {
2491                 tempResultVector.push_back(m_vecRecoResult[i]);
2492             }
2493         }
2494         m_vecRecoResult.clear();
2495         m_vecRecoResult = tempResultVector;
2496         tempResultVector.clear();
2497     }
2498     //Check if outResultVector is empty, if so, log
2499     if(m_vecRecoResult.size() == 0)
2500     {
2501         LOG(LTKLogger::LTK_LOGLEVEL_INFO) <<
2502             "Size of the result vector is empty, could not satisfy confThreshold criteria"<<endl;
2503     }
2504 
2505     //If numChoices is specified, get the top numChoices entries from outResultVector
2506     if(numChoices != NUM_CHOICES_FILTER_OFF)
2507     {
2508         //Get the entries from outResultVector only if size of resultVector > numChoices
2509         if(m_vecRecoResult.size() > numChoices)
2510         {
2511             for( int i = 0 ; i < numChoices ; ++i)
2512                 tempResultVector.push_back(m_vecRecoResult[i]);
2513             m_vecRecoResult.clear();
2514             m_vecRecoResult = tempResultVector;
2515             tempResultVector.clear();
2516         }
2517 
2518     }
2519 
2520     if(m_cancelRecognition)
2521         m_vecRecoResult.clear();
2522 
2523     outResultVector = m_vecRecoResult;
2524 
2525     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
2526         "NNShapeRecognizer::recognize()" << endl;
2527 
2528     return SUCCESS;
2529 
2530 }
2531 
2532 /**********************************************************************************
2533  * AUTHOR		: Saravanan. R
2534  * DATE			: 23-Jan-2007
2535  * NAME			: unloadModelData
2536  * DESCRIPTION	:
2537  * ARGUMENTS		:
2538  * RETURNS		: SUCCESS
2539  * NOTES			:
2540  * CHANGE HISTROY
2541  * Author			Date				Description
2542  *************************************************************************************/
unloadModelData()2543 int NNShapeRecognizer::unloadModelData()
2544 {
2545 
2546     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
2547         "NNShapeRecognizer::unloadModelData()" << endl;
2548 
2549     int returnStatus = SUCCESS;
2550 
2551     //Update MDT file with any modification, if available in memory
2552     if(m_prototypeSetModifyCount >0)
2553     {
2554         m_prototypeSetModifyCount = m_MDTUpdateFreq-1;
2555 
2556         returnStatus = writePrototypeSetToMDTFile();
2557         if(returnStatus != SUCCESS)
2558         {
2559             LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " <<
2560                 " NNShapeRecognizer::unloadModelData()" << endl;
2561         }
2562         m_prototypeSetModifyCount = 0;
2563     }
2564 
2565     //Clearing the prototypSet
2566     m_prototypeSet.clear();
2567     m_shapeIDNumPrototypesMap.clear();
2568 
2569     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
2570         "NNShapeRecognizer::unloadModelData()" << endl;
2571 
2572     return SUCCESS;
2573 }
2574 
2575 /**********************************************************************************
2576  * AUTHOR		: Saravanan. R
2577  * DATE			: 27-Feb-2007
2578  * NAME			: setDeviceContext
2579  * DESCRIPTION	: New Function - Not yet added
2580  * ARGUMENTS		:
2581  * RETURNS		: SUCCESS
2582  * NOTES			:
2583  * CHANGE HISTROY
2584  * Author			Date				Description
2585  *************************************************************************************/
setDeviceContext(const LTKCaptureDevice & deviceInfo)2586 int NNShapeRecognizer::setDeviceContext(const LTKCaptureDevice& deviceInfo)
2587 {
2588     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
2589         "NNShapeRecognizer::setDeviceContext()" << endl;
2590 
2591     if(m_ptrPreproc == NULL)
2592     {
2593 		int returnStatus = ECREATE_PREPROC;
2594         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " <<
2595             " NNShapeRecognizer::setDeviceContext()" << endl;
2596         LTKReturnError(returnStatus);
2597     }
2598 
2599 	m_ptrPreproc->setCaptureDevice(deviceInfo);
2600 
2601     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
2602         "NNShapeRecognizer::setDeviceContext()" << endl;
2603 
2604     return SUCCESS;
2605 }
2606 
2607 /******************************************************************************
2608  * AUTHOR		: Nidhi sharma
2609  * DATE			: 22-02-2007
2610  * NAME			: peformClustering
2611  * DESCRIPTION	: This method will do Custering for the given ShapeSamples
2612  * ARGUMENTS		:
2613  * RETURNS		: medianIndex
2614  * NOTES			:
2615  * CHANGE HISTROY
2616  * Author			Date				Description
2617  ******************************************************************************/
performClustering(const vector<LTKShapeSample> & shapeSamplesVec,vector<LTKShapeSample> & outClusteredShapeSampleVec)2618 int NNShapeRecognizer::performClustering(const vector<LTKShapeSample> & shapeSamplesVec,
2619         vector<LTKShapeSample>& outClusteredShapeSampleVec)
2620 
2621 {
2622 	int errorCode;
2623     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
2624         "NNShapeRecognizer::performClustering()" << endl;
2625 
2626     intVector tempVec;
2627     int2DVector outputVector;
2628     float2DVector distanceMatrix;
2629     int sampleCount=shapeSamplesVec.size();
2630     int returnStatus = SUCCESS;
2631 
2632     if(m_prototypeReductionFactor == -1)
2633     {
2634         //find number of clusters automatically
2635         //this is done when either of NumClusters or PrototypeReducrion factor is set
2636         //to automatic
2637         LTKHierarchicalClustering<LTKShapeSample,NNShapeRecognizer> hc(shapeSamplesVec,AVERAGE_LINKAGE,AVG_SIL);
2638         if(LTKSTRCMP(m_prototypeDistance.c_str(), DTW_DISTANCE) == 0)
2639         {
2640             returnStatus = hc.cluster(this,&NNShapeRecognizer::computeDTWDistance);
2641             if(returnStatus != SUCCESS)
2642             {
2643                 LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " <<
2644                     " NNShapeRecognizer::performClustering()" << endl;
2645                 LTKReturnError(returnStatus);
2646             }
2647         }
2648         else if(LTKSTRCMP(m_prototypeDistance.c_str(), EUCLIDEAN_DISTANCE) == 0)
2649         {
2650             returnStatus = hc.cluster(this,&NNShapeRecognizer::computeEuclideanDistance);
2651             if(returnStatus != SUCCESS)
2652             {
2653                 LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " <<
2654                     " NNShapeRecognizer::performClustering()" << endl;
2655                 LTKReturnError(returnStatus);
2656             }
2657         }
2658 
2659         //Cluster results are populated in an outputVector
2660         hc.getClusterResult(outputVector);
2661         distanceMatrix = hc.getProximityMatrix();
2662 
2663     }
2664     else if(m_prototypeReductionFactor == 0|| m_numClusters >= sampleCount)
2665     {
2666         //case where clustering is not required every sample is a cluster by itself
2667         outClusteredShapeSampleVec = shapeSamplesVec;
2668     }
2669     else
2670     {
2671         //clustering has to be performed
2672         int numClusters;
2673         if(m_numClusters == NN_NUM_CLUST_INITIAL)
2674         {
2675             numClusters = (100-m_prototypeReductionFactor)*sampleCount/100;
2676             if(numClusters == 0)
2677             {
2678                 numClusters = 1;
2679             }
2680         }
2681         else if(m_prototypeReductionFactor == NN_NUM_CLUST_INITIAL)
2682         {
2683             numClusters = m_numClusters;
2684         }
2685 
2686 	try
2687 	{
2688         LTKHierarchicalClustering<LTKShapeSample,NNShapeRecognizer>
2689             hc(shapeSamplesVec,numClusters, AVERAGE_LINKAGE);
2690 
2691 
2692         if(numClusters == 1)
2693         {
2694             int tempVar;
2695             if(LTKSTRCMP(m_prototypeDistance.c_str(), DTW_DISTANCE) == 0)
2696             {
2697                 hc.computeProximityMatrix(this, &NNShapeRecognizer::computeDTWDistance);
2698             }
2699             else if(LTKSTRCMP(m_prototypeDistance.c_str(), EUCLIDEAN_DISTANCE) == 0)
2700             {
2701                 hc.computeProximityMatrix(this, &NNShapeRecognizer::computeEuclideanDistance);
2702             }
2703 
2704             for(tempVar=0;tempVar<shapeSamplesVec.size();tempVar++)
2705             {
2706                 tempVec.push_back(tempVar);
2707             }
2708 
2709             outputVector.push_back(tempVec);
2710             tempVec.clear();
2711         }
2712         else
2713         {
2714             if(LTKSTRCMP(m_prototypeDistance.c_str(), DTW_DISTANCE) == 0)
2715             {
2716                 returnStatus = hc.cluster(this,&NNShapeRecognizer::computeDTWDistance);
2717                 if(returnStatus != SUCCESS)
2718                 {
2719                     LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " <<
2720                         " NNShapeRecognizer::performClustering()" << endl;
2721                     LTKReturnError(returnStatus);
2722                 }
2723 
2724             }
2725             else if(LTKSTRCMP(m_prototypeDistance.c_str(), EUCLIDEAN_DISTANCE) == 0)
2726             {
2727                 returnStatus = hc.cluster(this,&NNShapeRecognizer::computeEuclideanDistance);
2728                 if(returnStatus != SUCCESS)
2729                 {
2730                     LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << returnStatus << " " <<
2731                         " NNShapeRecognizer::performClustering()" << endl;
2732                     LTKReturnError(returnStatus);
2733                 }
2734 
2735 
2736             }
2737 
2738             //Cluster results are populated in an outputVector
2739             hc.getClusterResult(outputVector);
2740         }
2741         distanceMatrix = hc.getProximityMatrix();
2742     }
2743 	catch(LTKException e)
2744 	{
2745 		errorCode = e.getErrorCode();
2746                 LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
2747                     " NNShapeRecognizer::performClustering()" << endl;
2748 		LTKReturnError(errorCode);
2749 	}
2750     }
2751 
2752     if((m_prototypeReductionFactor != 0 && m_prototypeReductionFactor != NN_NUM_CLUST_INITIAL)||
2753             (m_numClusters>0 && m_numClusters<sampleCount))
2754     {
2755 
2756 	    vector<int> medianIndexVec;
2757 
2758 	    errorCode = calculateMedian(outputVector, distanceMatrix, medianIndexVec);
2759 
2760             if(errorCode != SUCCESS)
2761             {
2762                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode <<
2763                     " NNShapeRecognizer::performClustering()" << endl;
2764                 LTKReturnError(errorCode);
2765 
2766             }
2767 
2768 	    for(int numMedians = 0 ; numMedians < medianIndexVec.size() ; numMedians++)
2769 	    {
2770             	outClusteredShapeSampleVec.push_back(shapeSamplesVec[medianIndexVec[numMedians]]);
2771 	    }
2772 	    /*
2773         int medianIndex = 0;
2774         for (int clusNum = 0; clusNum < outputVector.size(); clusNum++)
2775         {
2776 
2777             errorCode = calculateMedian(outputVector, distanceMatrix, clusNum,medianIndex);
2778             if(errorCode != SUCCESS)
2779             {
2780                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<
2781                     "Error computing median, calculateMedian()" <<
2782                     " NNShapeRecognizer::performClustering()" << endl;
2783                 LTKReturnError(errorCode);
2784 
2785             }
2786             outClusteredShapeSampleVec.push_back(shapeSamplesVec[medianIndex]);
2787         }
2788 	*/
2789     }
2790 
2791     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
2792         "NNShapeRecognizer::performClustering()" << endl;
2793 
2794     return SUCCESS;
2795 }
2796 
2797 /******************************************************************************
2798  * AUTHOR		: Nidhi sharma
2799  * DATE			: 22-02-2007
2800  * NAME			: getShapeSampleFromInkFile
2801  * DESCRIPTION	: This method will get the ShapeSample by giving the ink
2802  *				  file path as input
2803  * ARGUMENTS		:
2804  * RETURNS		: SUCCESS
2805  * NOTES			:
2806  * CHANGE HISTROY
2807  * Author			Date				Description
2808  ******************************************************************************/
getShapeFeatureFromInkFile(const string & inkFilePath,vector<LTKShapeFeaturePtr> & shapeFeatureVec)2809 int NNShapeRecognizer::getShapeFeatureFromInkFile(const string& inkFilePath,
2810         vector<LTKShapeFeaturePtr>& shapeFeatureVec)
2811 {
2812 	int errorCode;
2813     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
2814         "NNShapeRecognizer::getShapeFeatureFromInkFile()" << endl;
2815 
2816     if ( inkFilePath.empty() )
2817         return FAILURE;
2818 
2819     LTKCaptureDevice captureDevice;
2820     LTKScreenContext screenContext;
2821 
2822     LTKTraceGroup inTraceGroup, preprocessedTraceGroup;
2823     inTraceGroup.emptyAllTraces();
2824 
2825     int returnVal = m_shapeRecUtil.readInkFromFile(inkFilePath,
2826             m_lipiRootPath, inTraceGroup,
2827             captureDevice, screenContext);
2828 
2829     if (returnVal!= SUCCESS)
2830     {
2831         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<returnVal<<
2832             " NNShapeRecognizer::getShapeFeatureFromInkFile()" << endl;
2833         LTKReturnError(returnVal);
2834     }
2835 
2836     m_ptrPreproc->setCaptureDevice(captureDevice);
2837     m_ptrPreproc->setScreenContext(screenContext);
2838 
2839     preprocessedTraceGroup.emptyAllTraces();
2840 
2841     //Preprocessing to be done for the trace group that was read
2842     if( preprocess(inTraceGroup, preprocessedTraceGroup) != SUCCESS )
2843     {
2844         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
2845             " NNShapeRecognizer::getShapeFeatureFromInkFile()" << endl;
2846         LTKReturnError(errorCode);
2847     }
2848 
2849     errorCode = m_ptrFeatureExtractor->extractFeatures(preprocessedTraceGroup,
2850             shapeFeatureVec);
2851 
2852     if (errorCode != SUCCESS)
2853     {
2854         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
2855             " NNShapeRecognizer::getShapeFeatureFromInkFile()" << endl;
2856         LTKReturnError(errorCode);
2857     }
2858 
2859     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
2860         "NNShapeRecognizer::getShapeFeatureFromInkFile()" << endl;
2861 
2862     return SUCCESS;
2863 }
2864 
2865 /******************************************************************************
2866  * AUTHOR		: Saravanan
2867  * DATE			: 22-02-2007
2868  * NAME			: trainFromListFile
2869  * DESCRIPTION	: This method will do the training by giving the Train List
2870  *				  file as input
2871  * ARGUMENTS		:
2872  * RETURNS		: none
2873  * NOTES			:
2874  * CHANGE HISTROY
2875  * Author			Date				Description
2876  ******************************************************************************/
trainFromListFile(const string & listFilePath)2877 int NNShapeRecognizer::trainFromListFile(const string& listFilePath)
2878 {
2879     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
2880         "NNShapeRecognizer::trainFromListFile()" << endl;
2881 
2882 
2883     //Count for the no. of samples read for a shape
2884     int sampleCount = 0;
2885 
2886     //Count of the no. of shapes read so far
2887     int shapeCount = 0;
2888 
2889     //Flag to skip reading a newline in the list file, when a new class starts
2890     bool lastshapeIdFlag = false;
2891 
2892     //Ink File Path
2893     string path = "";
2894 
2895     //Line from the list file
2896     string line = "";
2897 
2898     //Line is split into tokens
2899     stringVector tokens;
2900 
2901     //Flag is set when EOF is reached
2902     bool eofFlag = false;
2903 
2904     //ID for each shapes
2905     int shapeId = -1;
2906 
2907     //classId of the character
2908     int prevClassId = -1;
2909 
2910     //Indicates the first class
2911     bool initClassFlag = false;
2912 
2913     LTKShapeSample shapeSampleFeatures;
2914 
2915     vector<LTKShapeSample> shapeSamplesVec;
2916 
2917     vector<LTKShapeSample> clusteredShapeSampleVec;
2918 
2919     ofstream mdtFileHandle;
2920     ifstream listFileHandle;
2921 
2922     vector<LTKShapeFeaturePtr> shapeFeature;
2923 
2924     //Get the Instance of LTKShapeFeatureExtractor
2925     //initializeFeatureExtractorInstance();
2926 
2927     //Opening the train list file for reading mode
2928     listFileHandle.open(listFilePath.c_str(), ios::in);
2929 
2930     //Throw an error if unable to open the training list file
2931     if(!listFileHandle)
2932     {
2933         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< ETRAINLIST_FILE_OPEN << " " <<
2934             getErrorMessage(ETRAINLIST_FILE_OPEN)<<
2935             " NNShapeRecognizer::trainFromListFile()" << endl;
2936         LTKReturnError(ETRAINLIST_FILE_OPEN);
2937     }
2938 
2939     //Open the Model data file for writing mode
2940     if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
2941     {
2942         mdtFileHandle.open(m_nnMDTFilePath.c_str(), ios::out);
2943     }
2944     else
2945     {
2946         mdtFileHandle.open(m_nnMDTFilePath.c_str(),ios::out|ios::binary);
2947     }
2948 
2949     //Throw an error if unable to open the Model data file
2950     if(!mdtFileHandle)
2951     {
2952         listFileHandle.close();
2953         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EMODEL_DATA_FILE_OPEN << " " <<
2954             getErrorMessage(EMODEL_DATA_FILE_OPEN)<<
2955             " NNShapeRecognizer::trainFromListFile()" << endl;
2956 
2957         listFileHandle.close();
2958 
2959         LTKReturnError(EMODEL_DATA_FILE_OPEN);
2960     }
2961 
2962     if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
2963     {
2964         //Write the number of Shapes
2965         mdtFileHandle << m_numShapes << endl;
2966     }
2967     else
2968     {
2969         mdtFileHandle.write((char*) &m_numShapes, sizeof(unsigned short));
2970     }
2971 
2972     int errorCode = SUCCESS;
2973     while(!listFileHandle.eof())
2974 	{
2975 		// Not a sample of a new class
2976 		if( lastshapeIdFlag == false )
2977 		{
2978 			//Get the line from the list file
2979 			getline(listFileHandle, line, NEW_LINE_DELIMITER);
2980 
2981 			path  = "";
2982 
2983 			//Check if EOF is reached
2984 			if( listFileHandle.eof() )
2985 			{
2986 				eofFlag = true;
2987 			}
2988 
2989 			//Skip commented line
2990 			if ( line[0] == COMMENTCHAR )
2991 			{
2992 				continue;
2993 			}
2994 
2995 			if (eofFlag == false)
2996 			{
2997 				//Tokenize the string
2998 				errorCode = LTKStringUtil::tokenizeString(line,  LIST_FILE_DELIMITER,  tokens);
2999 
3000 				if( errorCode != SUCCESS )
3001 				{
3002 					LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
3003 						" NNShapeRecognizer::trainFromListFile()" << endl;
3004 
3005 					listFileHandle.close();
3006 					mdtFileHandle.close();
3007 
3008 					LTKReturnError(errorCode);
3009 				}
3010 
3011 
3012 				//Tokens must be of size 2, one is pathname and other is shapeId
3013 				//If the end of file not reached then continue the looping
3014 				if( tokens.size() != 2 && eofFlag == false )
3015 					continue;
3016 
3017 				//Tokens[0] indicates the path name
3018 				path = tokens[0];
3019 
3020 				//Tokens[1] indicates the shapeId
3021 				shapeId = atoi( tokens[1].c_str() );
3022 
3023 				if(shapeId < 0)
3024 				{
3025 					LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<<
3026 						"The NNShapeRecognizer requires training file class Ids to be positive integers and listed in the increasing order"<<
3027 						" NNShapeRecognizer::trainFromListFile()" << endl;
3028 					errorCode = EINVALID_SHAPEID;
3029 					break;
3030 				}
3031 				else if(shapeId < prevClassId)
3032 				{
3033 					LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<<
3034 						"Shape IDs in the train list file should be in the increasing order. Please use scripts/validateListFile.pl to generate list files." <<
3035 						" NNShapeRecognizer::trainFromListFile()" << endl;
3036 					errorCode = EINVALID_ORDER_LISTFILE;
3037 					break;
3038 				}
3039 
3040 
3041 				//This condition is used to handle the first sample in the file
3042 				if( initClassFlag == false )
3043 				{
3044 					initClassFlag = true;
3045 					prevClassId=shapeId;
3046 				}
3047 			}
3048 		}
3049 		else //Sample of a new class; do not read the next line during this iteration
3050 		{
3051 			//flag unset to read next line during the next iteration
3052 			lastshapeIdFlag = false;
3053 		}
3054 
3055 		// Sample from the same class, extract features, and push the extracted features to shapeSamplesVec
3056 		if( shapeId == prevClassId && ! path.empty())
3057 		{
3058 			if( getShapeFeatureFromInkFile(path, shapeFeature) != SUCCESS )
3059 			{
3060 				LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<
3061 					"Error extracting features from the ink file: " <<
3062 					path << ", extracting features from the next sample."<<
3063 					" NNShapeRecognizer::trainFromListFile()" << endl;
3064 				continue;
3065 			}
3066 
3067 			shapeSampleFeatures.setFeatureVector(shapeFeature);
3068 			shapeSampleFeatures.setClassID(shapeId);
3069 
3070 			++sampleCount;
3071 			shapeSamplesVec.push_back(shapeSampleFeatures);
3072 
3073 			shapeFeature.clear();
3074 
3075 			//All the samples are pushed to m_trainSet used only for trainLVQ
3076 
3077 			if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_LVQ)
3078 					== 0 && m_prototypeReductionFactor != 0)
3079 				m_trainSet.push_back(shapeSampleFeatures);
3080 		}
3081 
3082 		// Sample of new class seen, or end of list file reached; train all the samples of previous class ID
3083 		if( shapeId != prevClassId || eofFlag == true )
3084 		{
3085 			LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) <<
3086 				"Training for class : " << prevClassId << endl;
3087 
3088 			//Increase shape count only if there are atleast one sample per class
3089 			if( sampleCount > 0 )
3090 				shapeCount++;
3091 
3092 			//check that shapecount must not be greater than specified number
3093 			//of shapes, if projecttype was not dynamic
3094 			if( !m_projectTypeDynamic && shapeCount > m_numShapes )
3095 			{
3096 				errorCode = EINVALID_NUM_OF_SHAPES;
3097 				break;
3098 			}
3099 
3100 			if( shapeCount > 0 && sampleCount > 0 )
3101 			{
3102 				// No LVQ training being done?
3103 				errorCode = performClustering(shapeSamplesVec,
3104 						clusteredShapeSampleVec);
3105 				if( errorCode != SUCCESS )
3106 				{
3107 					LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
3108 						" NNShapeRecognizer::trainFromListFile()" << endl;
3109 
3110 					listFileHandle.close();
3111 					mdtFileHandle.close();
3112 					LTKReturnError(errorCode);
3113 				}
3114 
3115 				if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_LVQ) == 0)
3116 				{
3117 					//Push all the samples after clustering into prototypeSet
3118 					for( int i = 0; i < clusteredShapeSampleVec.size(); ++i )
3119 					{
3120 						m_prototypeSet.push_back(clusteredShapeSampleVec[i]);
3121 					}
3122 				}
3123 				else if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_CLUSTERING) == 0)
3124 				{
3125 					//Writing results to the MDT file
3126 					errorCode = appendPrototypesToMDTFile(clusteredShapeSampleVec, mdtFileHandle);
3127 					if( errorCode != SUCCESS )
3128 					{
3129 						LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<errorCode << " " <<
3130 							" NNShapeRecognizer::trainFromListFile()" << endl;
3131 
3132 						listFileHandle.close();
3133 						mdtFileHandle.close();
3134 						LTKReturnError(errorCode);
3135 					}
3136 
3137 				}
3138 
3139 				//Clearing the shapeSampleVector and clusteredShapeSampleVector
3140 				clusteredShapeSampleVec.clear();
3141 				shapeSamplesVec.clear();
3142 
3143 				//Resetting sampleCount for the next class
3144 				sampleCount = 0;
3145 
3146 				//Set the flag so that the already read line of next class in the list file is not lost
3147 				lastshapeIdFlag = true;
3148 
3149 				prevClassId = shapeId;
3150 
3151 			}
3152 		}
3153 	}//End of while
3154 
3155     //Closing the Train List file and Model Data file
3156     listFileHandle.close();
3157     mdtFileHandle.close();
3158 
3159     if(!m_projectTypeDynamic && shapeCount != m_numShapes)
3160     {
3161         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EINVALID_NUM_OF_SHAPES << " " <<
3162             getErrorMessage(EINVALID_NUM_OF_SHAPES)<<
3163             " NNShapeRecognizer::trainFromListFile()" << endl;
3164         LTKReturnError(EINVALID_NUM_OF_SHAPES);
3165     }
3166     if(errorCode != SUCCESS)
3167     {
3168         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
3169             " NNShapeRecognizer::trainFromListFile()" << endl;
3170         LTKReturnError(errorCode);
3171 
3172     }
3173 
3174     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
3175         "NNShapeRecognizer::trainFromListFile()" << endl;
3176 
3177     return SUCCESS;
3178 
3179 }
3180 
3181 
3182 /******************************************************************************
3183 * AUTHOR		: Saravanan
3184 * DATE			: 23-03-2007
3185 * NAME			: getShapeSampleFromString
3186 * DESCRIPTION	: This method get the Shape Sample Feature from a given line
3187 * ARGUMENTS		:
3188 * RETURNS		: none
3189 * NOTES			: w
3190 * CHANGE HISTROY
3191 * Author			Date				Description
3192 ******************************************************************************/
getShapeSampleFromString(const string & inString,LTKShapeSample & outShapeSample)3193 int NNShapeRecognizer::getShapeSampleFromString(const string& inString, LTKShapeSample& outShapeSample)
3194 {
3195     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
3196         "NNShapeRecognizer::getShapeSampleFromString()" << endl;
3197 
3198 
3199     //Line is split into tokens
3200     stringVector tokens;
3201 
3202     //Class Id
3203     int classId = -1;
3204 
3205     //Feature Vector string
3206     string strFeatureVector = "";
3207 
3208     //Tokenize the string
3209     int errorCode = LTKStringUtil::tokenizeString(inString, EMPTY_STRING,  tokens);
3210     if(errorCode != SUCCESS)
3211     {
3212 	    LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<"Error: "<< errorCode << " " <<
3213 		    " NNShapeRecognizer::getShapeSampleFromString()" << endl;
3214 	    LTKReturnError(errorCode);
3215     }
3216 
3217 
3218     //Tokens must be of size 2, one is classId and other is Feature Vector
3219     if( tokens.size() != 2)
3220         return FAILURE;
3221 
3222     //Tokens[0] indicates the path name
3223     classId = atoi(tokens[0].c_str());
3224 
3225     //Tokens[1] indicates the shapeId
3226     strFeatureVector = tokens[1];
3227 
3228     errorCode = LTKStringUtil::tokenizeString(strFeatureVector,  FEATURE_EXTRACTOR_DELIMITER,  tokens);
3229     if(errorCode != SUCCESS)
3230     {
3231 	    LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<"Error: "<< errorCode << " " <<
3232 		    " NNShapeRecognizer::getShapeSampleFromString()" << endl;
3233 	    LTKReturnError(errorCode);
3234     }
3235 
3236 
3237 
3238     vector<LTKShapeFeaturePtr> shapeFeatureVector;
3239     LTKShapeFeaturePtr shapeFeature;
3240 
3241     for(int i = 0; i < tokens.size(); ++i)
3242     {
3243         shapeFeature = m_ptrFeatureExtractor->getShapeFeatureInstance();
3244         if(shapeFeature->initialize(tokens[i]) != SUCCESS)
3245         {
3246             LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<"Error: "<< EINVALID_INPUT_FORMAT << " " <<
3247                 "Number of features extracted from a trace is not correct" <<
3248                 " NNShapeRecognizer::getShapeSampleFromString()" << endl;
3249             LTKReturnError(EINVALID_INPUT_FORMAT);
3250         }
3251         shapeFeatureVector.push_back(shapeFeature);
3252     }
3253 
3254     //Set the feature vector and class id to the shape sample features
3255     outShapeSample.setFeatureVector(shapeFeatureVector);
3256     outShapeSample.setClassID(classId);
3257 
3258     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
3259         "NNShapeRecognizer::getShapeSampleFromString()" << endl;
3260 
3261     return SUCCESS;
3262 }
3263 
3264 /******************************************************************************
3265 * AUTHOR		: Saravanan
3266 * DATE			: 22-02-2007
3267 * NAME			: initializeFeatureExtractorInstance
3268 * DESCRIPTION	: This method get the Instance of the Feature Extractor
3269 *				  from LTKShapeFeatureExtractorFactory
3270 * ARGUMENTS		:
3271 * RETURNS		: none
3272 * NOTES			:
3273 * CHANGE HISTROY
3274 * Author			Date				Description
3275 ******************************************************************************/
initializeFeatureExtractorInstance(const LTKControlInfo & controlInfo)3276 int NNShapeRecognizer::initializeFeatureExtractorInstance(const LTKControlInfo& controlInfo)
3277 {
3278 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
3279 		"NNShapeRecognizer::initializeFeatureExtractorInstance()" << endl;
3280 
3281 
3282 	LTKShapeFeatureExtractorFactory factory;
3283 	int errorCode = factory.createFeatureExtractor(m_featureExtractorName,
3284 			m_lipiRootPath,
3285 			m_lipiLibPath,
3286 			&m_libHandlerFE,
3287 			controlInfo,
3288 			&m_ptrFeatureExtractor);
3289 
3290 	if(errorCode != SUCCESS)
3291 	{
3292 		LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EFTR_EXTR_NOT_EXIST << " " <<
3293 			" NNShapeRecognizer::initializeFeatureExtractorInstance()" << endl;
3294 		LTKReturnError(errorCode);
3295 	}
3296 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
3297 		"NNShapeRecognizer::initializeFeatureExtractorInstance()" << endl;
3298 
3299 	return SUCCESS;
3300 }
3301 
3302 /******************************************************************************
3303 * AUTHOR		: Saravanan
3304 * DATE			: 26-03-2007
3305 * NAME			: deleteFeatureExtractorInstance
3306 * DESCRIPTION	: This method unloads the Feature extractor instance
3307 * ARGUMENTS		: none
3308 * RETURNS		: none
3309 * NOTES			:
3310 * CHANGE HISTROY
3311 * Author			Date				Description
3312 ******************************************************************************/
deleteFeatureExtractorInstance()3313 int NNShapeRecognizer::deleteFeatureExtractorInstance()
3314 {
3315     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
3316         "NNShapeRecognizer::deleteFeatureExtractorInstance()" << endl;
3317 
3318     if (m_ptrFeatureExtractor != NULL)
3319     {
3320         typedef int (*FN_PTR_DELETE_SHAPE_FEATURE_EXTRACTOR)(LTKShapeFeatureExtractor *obj);
3321         FN_PTR_DELETE_SHAPE_FEATURE_EXTRACTOR deleteFeatureExtractor;
3322         void * functionHandle = NULL;
3323 
3324         // Map createpreprocessor and deletePreprocessor functions
3325         int returnVal = m_OSUtilPtr->getFunctionAddress(m_libHandlerFE,
3326                                                 DELETE_SHAPE_FEATURE_EXTRACTOR,
3327                                                 &functionHandle);
3328         // Could not map the createLipiPreprocessor function from the DLL
3329     	if(returnVal != SUCCESS)
3330     	{
3331     	    LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<
3332                 "Error: "<< EDLL_FUNC_ADDRESS_DELETE_FEATEXT << " " <<
3333                 getErrorMessage(EDLL_FUNC_ADDRESS_DELETE_FEATEXT) <<
3334                 " NNShapeRecognizer::deleteFeatureExtractorInstance()" << endl;
3335 
3336             LTKReturnError(EDLL_FUNC_ADDRESS_DELETE_FEATEXT);
3337     	}
3338 
3339         deleteFeatureExtractor = (FN_PTR_DELETE_SHAPE_FEATURE_EXTRACTOR)functionHandle;
3340 
3341         deleteFeatureExtractor(m_ptrFeatureExtractor);
3342 
3343         m_ptrFeatureExtractor = NULL;
3344 
3345         // unload feature extractor dll
3346         if(m_libHandlerFE != NULL)
3347     	{
3348             //Unload the DLL
3349     		m_OSUtilPtr->unloadSharedLib(m_libHandlerFE);
3350     		m_libHandlerFE = NULL;
3351 
3352     	}
3353     }
3354 
3355     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
3356         "NNShapeRecognizer::deleteFeatureExtractorInstance()" << endl;
3357 
3358     return SUCCESS;
3359 }
3360 
3361 /******************************************************************************
3362 * AUTHOR		: Saravanan
3363 * DATE			: 22-02-2007
3364 * NAME			: updateHeaderWithAlgoInfo
3365 * DESCRIPTION	: This method will Update the Header information for the MDT file
3366 * ARGUMENTS		:
3367 * RETURNS		: none
3368 * NOTES			:
3369 * CHANGE HISTROY
3370 * Author			Date				Description
3371 ******************************************************************************/
updateHeaderWithAlgoInfo()3372 void NNShapeRecognizer::updateHeaderWithAlgoInfo()
3373 {
3374     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
3375         "NNShapeRecognizer::updateHeaderWithAlgoInfo()" << endl;
3376 
3377     m_headerInfo[RECVERSION] = m_currentVersion;
3378     string algoName = NN;
3379     m_headerInfo[RECNAME] = algoName;
3380 
3381     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
3382         "NNShapeRecognizer::updateHeaderWithAlgoInfo()" << endl;
3383 
3384 }
3385 
3386 
3387 /******************************************************************************
3388 * AUTHOR		: Saravanan
3389 * DATE			: 19-03-2007
3390 * NAME			: getDistance
3391 * DESCRIPTION	:
3392 * ARGUMENTS		:
3393 * RETURNS		:
3394 * NOTES			:
3395 * CHANGE HISTROY
3396 * Author			Date				Description
3397 ******************************************************************************/
getDistance(const LTKShapeFeaturePtr & f1,const LTKShapeFeaturePtr & f2,float & distance)3398 void NNShapeRecognizer::getDistance(const LTKShapeFeaturePtr& f1,
3399     const LTKShapeFeaturePtr& f2,
3400     float& distance)
3401 {
3402     f1->getDistance(f2, distance);
3403 }
3404 
3405 /******************************************************************************
3406  * AUTHOR		: Tarun Madan
3407  * DATE			: 11-06-2007
3408  * NAME			: getFeaturesFromTraceGroup
3409  * DESCRIPTION	: 1. PreProcess 2. Extract Features 3.Add to PrototypeSet
3410  *				  4. Add to MDT
3411  * ARGUMENTS		:
3412  * RETURNS		:
3413  * NOTES			:
3414  * CHANGE HISTROY
3415  * Author			Date				Description
3416  ******************************************************************************/
extractFeatVecFromTraceGroup(const LTKTraceGroup & inTraceGroup,vector<LTKShapeFeaturePtr> & featureVec)3417 int NNShapeRecognizer::extractFeatVecFromTraceGroup(const LTKTraceGroup& inTraceGroup,
3418         vector<LTKShapeFeaturePtr>& featureVec)
3419 {
3420 	int errorCode;
3421 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
3422         "NNShapeRecognizer::extractFeatVecFromTraceGroup()" << endl;
3423 
3424     LTKTraceGroup preprocessedTraceGroup; 	//TraceGroup after Preprocessing
3425 
3426     //Check for empty traces in inTraceGroup
3427     if(inTraceGroup.containsAnyEmptyTrace())
3428     {
3429         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EEMPTY_TRACE << " " <<
3430             getErrorMessage(EEMPTY_TRACE) <<
3431             " NNShapeRecognizer::extractFeatVecFromTraceGroup()" << endl;
3432         LTKReturnError(EEMPTY_TRACE);
3433     }
3434 
3435     //Preprocess the inTraceGroup
3436     if(preprocess(inTraceGroup, preprocessedTraceGroup) != SUCCESS)
3437     {
3438         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
3439             " NNShapeRecognizer::extractFeatVecFromTraceGroup()" << endl;
3440         LTKReturnError(errorCode);
3441     }
3442 
3443     errorCode = m_ptrFeatureExtractor->extractFeatures(preprocessedTraceGroup,
3444             featureVec);
3445 
3446     if (errorCode != SUCCESS)
3447     {
3448         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
3449             " NNShapeRecognizer::extractFeatVecFromTraceGroup()" << endl;
3450         LTKReturnError(errorCode);
3451     }
3452 
3453     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
3454         <<"Exiting NNShapeRecognizer::extractFeatVecFromTraceGroup()" << endl;
3455     return SUCCESS;
3456 }
3457 
3458 /******************************************************************************
3459  * AUTHOR		: Tarun Madan
3460  * DATE			: 07-06-2007
3461  * NAME			: addClass
3462  * DESCRIPTION	: 1. PreProcess 2. Extract Features 3.Add to PrototypeSet
3463  *				  4. Add to MDT
3464  * ARGUMENTS		:
3465  * RETURNS		:
3466  * NOTES			:
3467  * CHANGE HISTROY
3468  * Author			Date				Description
3469  ******************************************************************************/
addClass(const LTKTraceGroup & sampleTraceGroup,int & shapeID)3470 int NNShapeRecognizer::addClass(const LTKTraceGroup& sampleTraceGroup, int& shapeID)
3471 {
3472     // Should be moved to nnInternal
3473     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
3474         "NNShapeRecognizer::addClass()" << endl;
3475 
3476     LTKShapeSample shapeSampleFeatures;
3477 
3478     if(!m_projectTypeDynamic)
3479     {
3480         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EPROJ_NOT_DYNAMIC << " " <<
3481             "Not allowed to ADD shapes to a project with fixed number of shapes"<<
3482             " NNShapeRecognizer::addClass()" << endl;
3483 
3484         LTKReturnError(EPROJ_NOT_DYNAMIC);
3485     }
3486 
3487     //Compute ClassID
3488     int tempShapeID;
3489     if(m_shapeIDNumPrototypesMap.size()>0)
3490     {
3491         map<int,int>::reverse_iterator m_shapeIDNumPrototypesMapIter;
3492         m_shapeIDNumPrototypesMapIter = m_shapeIDNumPrototypesMap.rbegin();
3493         tempShapeID = m_shapeIDNumPrototypesMapIter->first;
3494         shapeID = tempShapeID+1;
3495     }
3496     else
3497     {
3498         shapeID = LTK_START_SHAPEID;
3499     }
3500 
3501     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<< "New ShapeID = "<<shapeID<<endl;
3502     //Calculate Features
3503     int errorCode = SUCCESS;
3504     vector<LTKShapeFeaturePtr> tempFeatureVec;
3505 
3506     errorCode = extractFeatVecFromTraceGroup(sampleTraceGroup,tempFeatureVec);
3507     if(errorCode != SUCCESS)
3508     {
3509         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
3510             " NNShapeRecognizer::addClass()" << endl;
3511         LTKReturnError(errorCode);
3512     }
3513 
3514     shapeSampleFeatures.setFeatureVector(tempFeatureVec);
3515 
3516     shapeSampleFeatures.setClassID(shapeID);
3517 
3518     //Update m_prototypeSet
3519     errorCode = insertSampleToPrototypeSet(shapeSampleFeatures);
3520     if(errorCode != SUCCESS)
3521     {
3522         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
3523             " NNShapeRecognizer::addClass()" << endl;
3524         LTKReturnError(errorCode);
3525     }
3526 
3527     //Update m_shapeIDNumPrototypesMap
3528     m_shapeIDNumPrototypesMap[shapeID]= 1;
3529 
3530 
3531     //Update MDT File
3532     errorCode = writePrototypeSetToMDTFile();
3533     if(errorCode != SUCCESS)
3534     {
3535         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
3536             " NNShapeRecognizer::addClass()" << endl;
3537         LTKReturnError(errorCode);
3538     }
3539 
3540 
3541     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
3542         <<"Exiting NNShapeRecognizer::addClass"<<endl;
3543     return SUCCESS;
3544 }
3545 /******************************************************************************
3546 * AUTHOR		: Anish Kumar
3547 * DATE			: 07-06-2007
3548 * NAME			: addSample
3549 * DESCRIPTION	: Add Sample to given class
3550 * ARGUMENTS		:
3551 * RETURNS		:
3552 * NOTES			:
3553 * CHANGE HISTROY
3554 * Author			Date				Description
3555 ******************************************************************************/
addSample(const LTKTraceGroup & sampleTraceGroup,int shapeID)3556 int NNShapeRecognizer::addSample(const LTKTraceGroup& sampleTraceGroup, int shapeID)
3557 {
3558 	// Should be moved to nnInternal
3559 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
3560 		"NNShapeRecognizer::addSample()" << endl;
3561 
3562 	LTKShapeSample shapeSampleFeatures;
3563 
3564 	if(!m_projectTypeDynamic)
3565 	{
3566 		LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EPROJ_NOT_DYNAMIC << " " <<
3567 			"Not allowed to ADD shapes to a project with fixed number of shapes"<<
3568 			" NNShapeRecognizer::addSample()" << endl;
3569 
3570 		LTKReturnError(EPROJ_NOT_DYNAMIC);
3571 	}
3572 
3573 	//Calculate Features
3574 	int errorCode = SUCCESS;
3575 	vector<LTKShapeFeaturePtr> tempFeatureVec;
3576 
3577 	errorCode = extractFeatVecFromTraceGroup(sampleTraceGroup,tempFeatureVec);
3578 	if(errorCode != SUCCESS)
3579 	{
3580 		LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
3581 			" NNShapeRecognizer::addSample()" << endl;
3582 		LTKReturnError(errorCode);
3583 	}
3584 
3585 	shapeSampleFeatures.setFeatureVector(tempFeatureVec);
3586 
3587 	shapeSampleFeatures.setClassID(shapeID);
3588 
3589 	//Update m_prototypeSet
3590 	errorCode = insertSampleToPrototypeSet(shapeSampleFeatures);
3591 	if(errorCode != SUCCESS)
3592 	{
3593 		LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
3594 			" NNShapeRecognizer::addSample()" << endl;
3595 		LTKReturnError(errorCode);
3596 	}
3597 
3598 	//Update m_shapeIDNumPrototypesMap
3599 	int currentNum = m_shapeIDNumPrototypesMap[shapeID];
3600 	m_shapeIDNumPrototypesMap[shapeID]= currentNum+1;
3601 
3602 	//Update MDT File
3603 	errorCode = writePrototypeSetToMDTFile();
3604 	if(errorCode != SUCCESS)
3605 	{
3606 		LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
3607 			" NNShapeRecognizer::addSample()" << endl;
3608 		LTKReturnError(errorCode);
3609 	}
3610 
3611 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
3612 		<<"Exiting NNShapeRecognizer::addSample"<<endl;
3613 	return SUCCESS;
3614 }
3615 
3616 /******************************************************************************
3617  * AUTHOR		: Tarun Madan
3618  * DATE			: 07-06-2007
3619  * NAME			: deleteClass
3620  * DESCRIPTION	:
3621  * ARGUMENTS		:
3622  * RETURNS		:
3623  * NOTES			:
3624  * CHANGE HISTROY
3625  * Author			Date				Description
3626  ******************************************************************************/
deleteClass(int shapeID)3627 int NNShapeRecognizer::deleteClass(int shapeID)
3628 {
3629     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
3630         "Entering NNShapeRecognizer::deleteClass" <<endl;
3631 
3632     LTKShapeSample shapeSampleFeatures;
3633     vector<LTKShapeSample>::iterator prototypeSetIter;
3634 
3635     int prototypeSetSize = m_prototypeSet.size();
3636 
3637     if(!m_projectTypeDynamic)
3638     {
3639         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EPROJ_NOT_DYNAMIC << " " <<
3640             "Not allowed to delete shapes to a project with fixed number of Shapes"<<
3641             " NNShapeRecognizer::deleteClass()" << endl;
3642 
3643         LTKReturnError(EPROJ_NOT_DYNAMIC);
3644     }
3645 
3646     //Validate Input Parameters - shapeID
3647     if(m_shapeIDNumPrototypesMap.find(shapeID) ==m_shapeIDNumPrototypesMap.end())
3648     {
3649         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EINVALID_SHAPEID << " " <<
3650             "shapeID is not valid"<<
3651             " NNShapeRecognizer::deleteClass()" << endl;
3652 
3653         LTKReturnError(EINVALID_SHAPEID);
3654     }
3655 
3656     //Update m_prototypeSet
3657     int k =0;
3658     for (int i=0;i<prototypeSetSize;i++)
3659     {
3660         prototypeSetIter = m_prototypeSet.begin() + k;
3661         int classId = (*prototypeSetIter).getClassID();
3662 
3663         if(classId == shapeID)
3664         {
3665             m_prototypeSet.erase(prototypeSetIter);
3666             continue;
3667         }
3668         k++;
3669         prototypeSetIter++;
3670     }
3671     //Update m_shapeIDNumPrototypesMap
3672     m_shapeIDNumPrototypesMap.erase(shapeID);
3673 
3674     //Update MDT File
3675     int returnStatus = writePrototypeSetToMDTFile();
3676 
3677     if(returnStatus != SUCCESS)
3678     {
3679         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: " << returnStatus << " " <<
3680             "Exiting NNShapeRecognizer::deleteClass" <<endl;
3681         LTKReturnError(returnStatus);
3682     }
3683 
3684     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
3685         "Exiting NNShapeRecognizer::deleteClass" <<endl;
3686 
3687     return SUCCESS;
3688 }
3689 
3690 /******************************************************************************
3691  * AUTHOR		: Tarun Madan
3692  * DATE			: 09-06-2007
3693  * NAME			: writePrototypeSetToMDTFile
3694  * DESCRIPTION	: Creates a MDTFile with updated m_prototypeSet
3695  * ARGUMENTS		:
3696  * RETURNS		:
3697  * NOTES			:
3698  * CHANGE HISTROY
3699  * Author			Date				Description
3700  ******************************************************************************/
writePrototypeSetToMDTFile()3701 int NNShapeRecognizer::writePrototypeSetToMDTFile()
3702 {
3703 
3704     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
3705         "NNShapeRecognizer::writePrototypeSetToMDTFile()" << endl;
3706 
3707     int returnStatus = SUCCESS;
3708 
3709     //Flush to MDT only after m_MDTUpdateFreq modifications
3710     m_prototypeSetModifyCount++;
3711     if(m_prototypeSetModifyCount == m_MDTUpdateFreq)
3712     {
3713         m_prototypeSetModifyCount = 0;
3714 
3715         ofstream mdtFileHandle;
3716         vector<LTKShapeSample> vecShapeSampleFeatures;
3717         LTKShapeSample shapeSampleFeatures;
3718 
3719         vector<LTKShapeSample>::iterator prototypeSetIter;
3720 
3721         int prototypeSetSize = m_prototypeSet.size();
3722 
3723         //Open the Model data file for writing mode
3724         if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
3725         {
3726             mdtFileHandle.open(m_nnMDTFilePath.c_str(), ios::out);
3727         }
3728         else
3729         {
3730             mdtFileHandle.open(m_nnMDTFilePath.c_str(),ios::out|ios::binary);
3731         }
3732 
3733 
3734         //Throw an error if unable to open the Model data file
3735         if(!mdtFileHandle)
3736         {
3737             LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EMODEL_DATA_FILE_OPEN << " " <<
3738                 getErrorMessage(EMODEL_DATA_FILE_OPEN) <<
3739                 " NNShapeRecognizer::writePrototypeSetToMDTFile()" << endl;
3740 
3741             LTKReturnError(EMODEL_DATA_FILE_OPEN);
3742         }
3743 
3744 
3745         if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
3746         {
3747             //Write the number of Shapes
3748             mdtFileHandle << 0 << endl; //Representing Dynamic
3749         }
3750         else
3751         {
3752             int numShapes = 0;
3753             mdtFileHandle.write((char*) &numShapes, sizeof(unsigned short));
3754         }
3755         prototypeSetIter = m_prototypeSet.begin();
3756 
3757         for (int i=0;i<prototypeSetSize;i++)
3758         {
3759             int classId = (*prototypeSetIter).getClassID();
3760             shapeSampleFeatures.setClassID(classId);
3761             shapeSampleFeatures.setFeatureVector((*prototypeSetIter).getFeatureVector());
3762 
3763             vecShapeSampleFeatures.push_back(shapeSampleFeatures);
3764             prototypeSetIter++;
3765         }
3766 
3767         returnStatus = appendPrototypesToMDTFile(vecShapeSampleFeatures,mdtFileHandle);
3768 
3769         if(returnStatus != SUCCESS)
3770         {
3771             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< returnStatus << " " <<
3772                 " NNShapeRecognizer::writePrototypeSetToMDTFile()" << endl;
3773 
3774             LTKReturnError(returnStatus);
3775         }
3776 
3777         mdtFileHandle.close();
3778 
3779         //Updating the Header Information
3780         updateHeaderWithAlgoInfo();
3781 
3782         //Adding header information	and checksum generation
3783         string strModelDataHeaderInfoFile = "";
3784         LTKCheckSumGenerate cheSumGen;
3785 
3786         returnStatus = cheSumGen.addHeaderInfo(
3787                 strModelDataHeaderInfoFile,
3788                 m_nnMDTFilePath,
3789                 m_headerInfo
3790                 );
3791 
3792         if(returnStatus != SUCCESS)
3793         {
3794             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<<  returnStatus << " " <<
3795                 " NNShapeRecognizer::writePrototypeSetToMDTFile()" << endl;
3796 
3797             LTKReturnError(returnStatus);
3798         }
3799 
3800         vecShapeSampleFeatures.clear();
3801     }
3802 
3803     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
3804         <<"Exiting NNShapeRecognizer::writePrototypeSetToMDTFile"<<endl;
3805 
3806     return SUCCESS;
3807 }
3808 
3809 /******************************************************************************
3810  * AUTHOR		: Tarun Madan
3811  * DATE			: 09-06-2007
3812  * NAME			: Add Sample to m_prototypeSet
3813  * DESCRIPTION	: Add  LTKShapeSample to m_prototypeSet
3814  *
3815  * ARGUMENTS		:
3816  * RETURNS		:
3817  * NOTES			:
3818  * CHANGE HISTROY
3819  * Author			Date				Description
3820  ******************************************************************************/
insertSampleToPrototypeSet(const LTKShapeSample & shapeSampleFeatures)3821 int NNShapeRecognizer::insertSampleToPrototypeSet(const LTKShapeSample &shapeSampleFeatures)
3822 {
3823     //Error??
3824 
3825     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
3826         "Entering NNShapeRecognizer::insertSampleToPrototypeSet"<<endl;
3827 
3828     vector<LTKShapeSample>::iterator prototypeSetIter;
3829     int classID = shapeSampleFeatures.getClassID();
3830     int maxClassID;
3831 
3832     int prototypeSize = m_prototypeSet.size();
3833     if(prototypeSize > 0)
3834     {
3835         maxClassID = m_prototypeSet.at(prototypeSize-1).getClassID();
3836     }
3837     else
3838     {
3839         maxClassID = LTK_START_SHAPEID;
3840     }
3841 
3842     prototypeSetIter = m_prototypeSet.begin();
3843 
3844     if(classID >= maxClassID)
3845     {
3846         m_prototypeSet.push_back(shapeSampleFeatures);
3847     }
3848     else
3849     {
3850         for(;prototypeSetIter!=m_prototypeSet.end();)
3851         {
3852             int currentClassId = (*prototypeSetIter).getClassID();
3853 
3854             if(currentClassId >= classID)
3855             {
3856                 m_prototypeSet.insert(prototypeSetIter,shapeSampleFeatures);
3857                 break;
3858             }
3859             int count = m_shapeIDNumPrototypesMap[currentClassId];
3860             prototypeSetIter = prototypeSetIter + count; //To point to first sample of next classID
3861         }
3862     }
3863     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Exiting NNShapeRecognizer::insertSampleToPrototypeSet"<<endl;
3864 
3865     return SUCCESS;
3866 }
3867 
3868 /******************************************************************************
3869  * AUTHOR                : Vandana Roy
3870  * DATE                  : 05-07-2007
3871  * NAME                  : computeConfidence
3872  * DESCRIPTION   :
3873  * ARGUMENTS             :
3874  * RETURNS               :
3875  * NOTES                 :
3876  * CHANGE HISTROY
3877  * Author                        Date                            Description
3878  ******************************************************************************/
computeConfidence()3879 int NNShapeRecognizer::computeConfidence()
3880 {
3881     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
3882         "NNShapeRecognizer::computeConfidence()" << endl;
3883 
3884     /******************************************************************/
3885     /*******************VALIDATING INPUT ARGUMENTS*********************/
3886     /******************************************************************/
3887     if(m_neighborInfoVec.empty())
3888     {
3889         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< ENEIGHBOR_INFO_VECTOR_EMPTY << " " <<
3890             getErrorMessage(ENEIGHBOR_INFO_VECTOR_EMPTY) <<
3891             " NNShapeRecognizer::computeConfidence()" << endl;
3892 
3893         LTKReturnError(ENEIGHBOR_INFO_VECTOR_EMPTY);
3894     }
3895     // Temporary vector to store the recognition results
3896     LTKShapeRecoResult outResult;
3897     vector<pair<int,float> > classIdSimilarityPairVec;
3898     pair<int, float> classIdSimilarityPair;
3899 
3900     // Temporary vector to store the distinct classes appearing in distIndexPairVector
3901     intVector distinctClassVector;
3902     intVector::iterator distinctClassVectorIter;
3903 
3904     vector <LTKShapeRecoResult>::iterator resultVectorIter = m_vecRecoResult.begin();
3905     vector <LTKShapeRecoResult>::iterator resultVectorIterEnd = m_vecRecoResult.end();
3906 
3907     // Variable to store sum of distances to all the prototypes in distIndexPairVector
3908     float similaritySum = 0.0f;
3909     // Temporary variable to store the confidence value.
3910     float confidence = 0.0f;
3911 
3912     // Confidence computation for the NN (1-NN) Classifier
3913     if(m_nearestNeighbors == 1)
3914     {
3915         vector <struct NeighborInfo>::iterator distIndexPairIter = m_neighborInfoVec.begin();
3916         vector <struct NeighborInfo>::iterator distIndexPairIterEnd = m_neighborInfoVec.end();
3917 
3918 
3919         for(; distIndexPairIter != distIndexPairIterEnd; ++distIndexPairIter)
3920         {
3921             //Check if the class is already present in distinctClassVector
3922             //The complexity of STL's find() is linear, with atmost last-first comparisons for equality
3923             distinctClassVectorIter = find(distinctClassVector.begin(), distinctClassVector.end(), (*distIndexPairIter).classId);
3924 
3925             //The distinctClassVectorIter will point to distinctClassVector.end() if the class is not present in distinctClassVector
3926             if(distinctClassVectorIter == distinctClassVector.end())
3927             {
3928                 //outResult.setShapeId( (*distIndexPairIter).classId );
3929                 classIdSimilarityPair.first = (*distIndexPairIter).classId ;
3930                 float similarityValue = SIMILARITY((*distIndexPairIter).distance);
3931                 //outResult.setConfidence(similarityValue);
3932                 classIdSimilarityPair.second = similarityValue;
3933                 similaritySum += similarityValue;
3934                 //m_vecRecoResult.push_back(outResult);
3935                 classIdSimilarityPairVec.push_back(classIdSimilarityPair);
3936                 distinctClassVector.push_back((*distIndexPairIter).classId);
3937             }
3938         }
3939 
3940         int classIdSimilarityPairVecSize = classIdSimilarityPairVec.size();
3941         for( int i = 0 ; i < classIdSimilarityPairVecSize ; ++i)
3942         {
3943             int classID = classIdSimilarityPairVec[i].first;
3944             confidence = classIdSimilarityPairVec[i].second;
3945             confidence /= similaritySum;
3946             outResult.setConfidence(confidence);
3947             outResult.setShapeId(classID);
3948             if(confidence > 0)
3949             m_vecRecoResult.push_back(outResult);
3950 
3951         }
3952         classIdSimilarityPairVec.clear();
3953 
3954     }
3955     // Computing confidence for k-NN classifier, implementation of the confidence measure described in paper (cite)
3956     else
3957     {
3958         if(m_nearestNeighbors >= m_neighborInfoVec.size())
3959         {
3960             LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) <<
3961                 "m_nearestNeighbors >= m_prototypeSet.size(), using distIndexPairVector.size() for m_nearestNeighbors instead" << endl;
3962             m_nearestNeighbors = m_neighborInfoVec.size();
3963         }
3964 //        vector<pair<int,float> > classIdSimilarityPairVec;
3965   //      pair<int, float> classIdSimilarityPair;
3966 
3967         // Variable to store the maximum of the number of samples per class.
3968         int maxClassSize = (max_element(m_shapeIDNumPrototypesMap.begin(), m_shapeIDNumPrototypesMap.end(), &compareMap))->second;
3969         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "maxClassSize: " <<maxClassSize<< endl;
3970 
3971         // Vector to store the cumulative similarity values
3972         vector<float> cumulativeSimilaritySum;
3973 
3974         // Populate the values in cumulativeSimilaritySum vector for the top m_nearestNeighbors prototypes
3975         // Assumption is m_nearestNeighbors >= MIN_NEARESTNEIGHBORS and
3976 		// m_nearestNeighbors < dtwEuclideanFilter, validation done in recognize()
3977 
3978         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Displaying cumulativeSimilaritySum..." << endl;
3979         int i = 0;
3980         for( i = 0 ; i < m_nearestNeighbors ; ++i)
3981         {
3982             //outResult.setShapeId(m_neighborInfoVec[i].classId);
3983             classIdSimilarityPair.first = m_neighborInfoVec[i].classId;
3984             float similarityValue = SIMILARITY((m_neighborInfoVec[i]).distance);
3985 //            outResult.setConfidence(similarityValue);
3986             classIdSimilarityPair.second = similarityValue;
3987 //            classIdSimilarityPairVector.push_back(outResult);
3988             classIdSimilarityPairVec.push_back(classIdSimilarityPair);
3989             similaritySum += similarityValue;
3990             cumulativeSimilaritySum.push_back(similaritySum);
3991 
3992             // Logging the cumulative similarity values for debugging
3993             LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "classID:" <<
3994                 m_neighborInfoVec[i].classId << " confidence:" <<
3995                 similarityValue << endl;
3996 
3997             LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << i << ": " << similaritySum << endl;
3998         }
3999 
4000 //        for(i = 0 ; i < classIdSimilarityPairVector.size() ; ++i)
4001         for(i = 0 ; i < classIdSimilarityPairVec.size() ; ++i)
4002         {
4003 //            int classID = classIdSimilarityPairVector[i].getShapeId();
4004             int classID = classIdSimilarityPairVec[i].first;
4005 
4006             int finalNearestNeighbors = 0;
4007 
4008             //Check if the class is already present in distinctClassVector
4009             distinctClassVectorIter = find(distinctClassVector.begin(), distinctClassVector.end(), classID);
4010 
4011             //The distinctClassVectorIter will point to distinctClassVector.end() if the class is not present in distinctClassVector
4012             if(distinctClassVectorIter == distinctClassVector.end())
4013             {
4014                 distinctClassVector.push_back(classID);
4015                 confidence = 0.0f;
4016 
4017                 //If the confidence is based on Adaptive k-NN scheme,
4018                 //Computing number of nearest neighbours for the class to be used for computation of confidence
4019                 if(m_adaptivekNN == true )
4020                 {
4021 
4022                     int sizeProportion = (int)ceil(1.0*m_nearestNeighbors*m_shapeIDNumPrototypesMap[classID]/maxClassSize);
4023                     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"sizeProportion of class " <<classID<<" is "<<sizeProportion<<endl;
4024 
4025                     // Computing min(sizeProportion, m_shapeIDNumPrototypesMap[classID])
4026                     int upperBound = (sizeProportion < m_shapeIDNumPrototypesMap[classID]) ? sizeProportion:m_shapeIDNumPrototypesMap[classID];
4027                     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"upperBound: " <<upperBound<<endl;
4028 
4029                     // Computing max(upperBound, MIN_NEARESTNEIGHBORS)
4030                     finalNearestNeighbors = (MIN_NEARESTNEIGHBORS > upperBound) ? MIN_NEARESTNEIGHBORS:upperBound;
4031                 }
4032                 //Else, compute kNN based confidence
4033                 else if(m_adaptivekNN == false)
4034                 {
4035                     finalNearestNeighbors = m_nearestNeighbors;
4036                 }
4037                 else
4038                 {
4039                     LOG(LTKLogger::LTK_LOGLEVEL_ERR) <<"Error: " << ECONFIG_FILE_RANGE << " " <<
4040 			"m_adaptivekNN should be true or false" <<
4041 			" NNShapeRecognizer::computeConfidence()" << endl;
4042                     LTKReturnError(ECONFIG_FILE_RANGE);
4043                 }
4044 
4045 
4046                 LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"finalNearestNeighbors: " <<finalNearestNeighbors<<endl;
4047 
4048                 for( int j = 0 ; j < finalNearestNeighbors ; ++j)
4049                 {
4050                     if(classID == classIdSimilarityPairVec[j].first)
4051                     {
4052                         confidence += classIdSimilarityPairVec[j].second;
4053                     }
4054                 }
4055                 confidence /= cumulativeSimilaritySum[finalNearestNeighbors-1];
4056 
4057                 outResult.setShapeId(classID);
4058                 outResult.setConfidence(confidence);
4059 
4060                 if(confidence > 0)
4061                 {
4062                     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"classId: " <<classID<<" confidence: "<<confidence<<endl;
4063 
4064                     m_vecRecoResult.push_back(outResult);
4065                 }
4066             }
4067         }
4068         classIdSimilarityPairVec.clear();
4069     }
4070 
4071     //Sort the result vector in descending order of confidence
4072     sort(m_vecRecoResult.begin(), m_vecRecoResult.end(), sortResultByConfidence);
4073 
4074     //Logging the results at info level
4075     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Printing the Classes and respective Confidences" <<endl;
4076 
4077     for( int i=0; i < m_vecRecoResult.size() ; i++)
4078     {
4079         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Class ID: " <<m_vecRecoResult[i].getShapeId()
4080             <<" Confidence: "<<m_vecRecoResult[i].getConfidence()
4081             <<endl;
4082     }
4083 
4084     distinctClassVector.clear();
4085 
4086     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
4087         "NNShapeRecognizer::computeConfidence()" << endl;
4088 
4089     return SUCCESS;
4090 }
4091 
4092 /******************************************************************************
4093  * AUTHOR                : Vandana Roy
4094  * DATE                  : 05-07-2007
4095  * NAME                  : sortResultByConfidence
4096  * DESCRIPTION  	 : Sort the LTKShapeRecoResult vector based on the Confidence value
4097  * ARGUMENTS             :
4098  * RETURNS               :
4099  * NOTES                 :
4100  * CHANGE HISTROY
4101  * Author                        Date                            Description
4102  ******************************************************************************/
4103 
sortResultByConfidence(const LTKShapeRecoResult & x,const LTKShapeRecoResult & y)4104 bool NNShapeRecognizer::sortResultByConfidence(const LTKShapeRecoResult& x, const LTKShapeRecoResult& y)
4105 {
4106     return (x.getConfidence()) > (y.getConfidence());
4107 }
4108 /******************************************************************************
4109  * AUTHOR                : Vandana Roy
4110  * DATE                  : 05-07-2007
4111  * NAME                  : compareMap
4112  * DESCRIPTION  	 : Sort the STL's map based on the 'value'(second) field
4113  * ARGUMENTS             :
4114  * RETURNS               :
4115  * NOTES                 :
4116  * CHANGE HISTROY
4117  * Author                        Date                            Description
4118  ******************************************************************************/
4119 
compareMap(const map<int,int>::value_type & lhs,const map<int,int>::value_type & rhs)4120 bool NNShapeRecognizer::compareMap( const map<int, int>::value_type& lhs, const map<int, int>::value_type& rhs )
4121 {
4122     return lhs.second < rhs.second;
4123 }
4124 
4125 /******************************************************************************
4126  * AUTHOR		: Tarun Madan
4127  * DATE			: 08-07-2007
4128  * NAME			: getTraceGroup
4129  * DESCRIPTION	:
4130  *
4131  * ARGUMENTS		:
4132  * RETURNS		:
4133  * NOTES			:
4134  * CHANGE HISTROY
4135  * Author			Date				Description
4136  ******************************************************************************/
getTraceGroups(int shapeID,int numberOfTraceGroups,vector<LTKTraceGroup> & outTraceGroups)4137 int NNShapeRecognizer::getTraceGroups(int shapeID, int numberOfTraceGroups,
4138         vector<LTKTraceGroup> &outTraceGroups)
4139 {
4140     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
4141         <<"Entering NNShapeRecognizer::getTraceGroups"
4142         <<endl;
4143 
4144     if(m_shapeIDNumPrototypesMap.find(shapeID) == m_shapeIDNumPrototypesMap.end())
4145     {
4146         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EINVALID_SHAPEID << " " <<
4147             getErrorMessage(EINVALID_SHAPEID) <<
4148             " NNShapeRecognizer::getTraceGroups()" << endl;
4149         LTKReturnError(EINVALID_SHAPEID);
4150     }
4151 
4152     if(m_shapeIDNumPrototypesMap[shapeID] < numberOfTraceGroups)
4153     {
4154         numberOfTraceGroups = m_shapeIDNumPrototypesMap[shapeID];
4155         LOG(LTKLogger::LTK_LOGLEVEL_INFO)
4156             << "Number of TraceGroup in PrototypeSet is less than specified."
4157             << "Returning all TraceGroups :"
4158             << numberOfTraceGroups <<endl;
4159     }
4160 
4161     vector<LTKShapeSample>::iterator prototypeSetIter = m_prototypeSet.begin();
4162     int counter =0;
4163     for(;prototypeSetIter!=m_prototypeSet.end();)
4164     {
4165         int currentShapeId = (*prototypeSetIter).getClassID();
4166 
4167         if(currentShapeId == shapeID)
4168         {
4169             LTKTraceGroup traceGroup;
4170 
4171             int errorCode = m_ptrFeatureExtractor->convertFeatVecToTraceGroup(
4172                     (*prototypeSetIter).getFeatureVector(),
4173                     traceGroup);
4174             if(errorCode != SUCCESS)
4175             {
4176                 LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
4177                     " NNShapeRecognizer::getTraceGroups()" << endl;
4178 
4179                 LTKReturnError(errorCode);
4180             }
4181             outTraceGroups.push_back(traceGroup);
4182 
4183             counter++;
4184             if(counter==numberOfTraceGroups)
4185                 break;
4186 
4187             prototypeSetIter++;
4188         }
4189         else
4190         {
4191             //To point to first sample of next classID
4192             int offset = m_shapeIDNumPrototypesMap[currentShapeId];
4193             prototypeSetIter = prototypeSetIter + offset;
4194         }
4195 
4196     }
4197 
4198     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)
4199         <<"Exiting NNShapeRecognizer::getTraceGroups"
4200         <<endl;
4201     return SUCCESS;
4202 }
4203 
4204 /***********************************************************************************
4205  * AUTHOR		: Saravanan. R
4206  * DATE			: 19-01-2007
4207  * NAME			: initializePreprocessor
4208  * DESCRIPTION	: This method is used to initialize the PreProcessor
4209  * ARGUMENTS		: preprocDLLPath : string : Holds the Path of the Preprocessor DLL,
4210  *				  returnStatus    : int    : Holds SUCCESS or Error Values, if occurs
4211  * RETURNS		: preprocessor instance
4212  * NOTES			:
4213  * CHANGE HISTROY
4214  * Author			Date				Description
4215  *************************************************************************************/
initializePreprocessor(const LTKControlInfo & controlInfo,LTKPreprocessorInterface ** preprocInstance)4216 int NNShapeRecognizer::initializePreprocessor(const LTKControlInfo& controlInfo,
4217         LTKPreprocessorInterface** preprocInstance)
4218 {
4219     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
4220         "NNShapeRecognizer::initializePreprocessor()" << endl;
4221 
4222     FN_PTR_CREATELTKLIPIPREPROCESSOR createLTKLipiPreProcessor = NULL;
4223     int errorCode;
4224 
4225     // Load the DLL with path=preprocDLLPath
4226     void* functionHandle = NULL;
4227 
4228     int returnVal = m_OSUtilPtr->loadSharedLib(controlInfo.lipiLib, PREPROC, &m_libHandler);
4229 
4230 
4231 	if(returnVal != SUCCESS)
4232     {
4233         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<<  ELOAD_PREPROC_DLL << " " <<
4234             getErrorMessage(ELOAD_PREPROC_DLL) <<
4235             " NNShapeRecognizer::initializePreprocessor()" << endl;
4236         LTKReturnError(ELOAD_PREPROC_DLL);
4237     }
4238 
4239     // Map createpreprocessor and deletePreprocessor functions
4240     returnVal = m_OSUtilPtr->getFunctionAddress(m_libHandler,
4241                                             CREATEPREPROCINST,
4242                                             &functionHandle);
4243     // Could not map the createLipiPreprocessor function from the DLL
4244 	if(returnVal != SUCCESS)
4245     {
4246         //Unload the dll
4247         unloadPreprocessorDLL();
4248         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EDLL_FUNC_ADDRESS_CREATE << " " <<
4249             getErrorMessage(EDLL_FUNC_ADDRESS_CREATE) <<
4250             " NNShapeRecognizer::initializePreprocessor()" << endl;
4251 
4252         LTKReturnError(EDLL_FUNC_ADDRESS_CREATE);
4253     }
4254 
4255     createLTKLipiPreProcessor = (FN_PTR_CREATELTKLIPIPREPROCESSOR)functionHandle;
4256 
4257     functionHandle = NULL;
4258 
4259     // Map createpreprocessor and deletePreprocessor functions
4260     returnVal = m_OSUtilPtr->getFunctionAddress(m_libHandler,
4261                                             DESTROYPREPROCINST,
4262                                             &functionHandle);
4263     // Could not map the createLipiPreprocessor function from the DLL
4264 	if(returnVal != SUCCESS)
4265     {
4266         //Unload the dll
4267         unloadPreprocessorDLL();
4268 
4269         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EDLL_FUNC_ADDRESS_CREATE << " " <<
4270             getErrorMessage(EDLL_FUNC_ADDRESS_CREATE) <<
4271             " NNShapeRecognizer::initializePreprocessor()" << endl;
4272         LTKReturnError(EDLL_FUNC_ADDRESS_CREATE);
4273 	}
4274 
4275     m_deleteLTKLipiPreProcessor = (FN_PTR_DELETELTKLIPIPREPROCESSOR)functionHandle;
4276 
4277     // Create preprocessor instance
4278     errorCode = createLTKLipiPreProcessor(controlInfo, preprocInstance);
4279 
4280     if(errorCode!=SUCCESS)
4281     {
4282         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<<  errorCode << " " <<
4283             " NNShapeRecognizer::initializePreprocessor()" << endl;
4284         LTKReturnError(errorCode);
4285     }
4286 
4287     // Could not create a LTKLipiPreProcessor
4288     if(*preprocInstance == NULL)
4289     {
4290         // Unload the DLL
4291         unloadPreprocessorDLL();
4292 
4293         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< ECREATE_PREPROC << " " <<
4294             getErrorMessage(ECREATE_PREPROC) <<
4295             " NNShapeRecognizer::initializePreprocessor()" << endl;
4296         LTKReturnError(ECREATE_PREPROC);
4297     }
4298 
4299     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
4300         "NNShapeRecognizer::initializePreprocessor()" << endl;
4301 
4302     return SUCCESS;
4303 
4304 }
4305 
4306 /**********************************************************************************
4307  * AUTHOR		: Saravanan R.
4308  * DATE			: 23-Jan-2007
4309  * NAME			: trainLvq
4310  * DESCRIPTION	: This function is the train method using LVQ
4311  * ARGUMENTS		:
4312  * RETURNS		: SUCCESS : if training done successfully
4313  *				  errorCode : if traininhas some errors
4314  * NOTES			:
4315  * CHANGE HISTROY
4316  * Author	Naveen Sundar G		Date				Description
4317  * Balaji MNA                   13th Jan, 2011      Prototype set must be emptied before
4318  *                                                  returning from call to LVQ train
4319  *************************************************************************************/
trainLVQ(const string & inputFilePath,const string & strModelDataHeaderInfoFile,const string & inFileType)4320 int NNShapeRecognizer::trainLVQ(const string& inputFilePath,
4321 		const string &strModelDataHeaderInfoFile,
4322 		const string& inFileType)
4323 {
4324     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
4325         "NNShapeRecognizer::trainLVQ()" << endl;
4326     //Time calculation requirements
4327 
4328     int errorCode = SUCCESS;
4329     m_OSUtilPtr->recordStartTime();
4330 
4331     //Time at the beginning of Train LVQ
4332     if(LTKSTRCMP(inFileType.c_str(), INK_FILE) == 0)
4333     {
4334         //If the Input file is UNIPEN Ink file
4335         errorCode = trainFromListFile(inputFilePath);
4336         if(errorCode != SUCCESS)
4337         {
4338             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
4339                 " NNShapeRecognizer::trainLVQ()" << endl;
4340 
4341             LTKReturnError(errorCode);
4342         }
4343     }
4344     else if(LTKSTRCMP(inFileType.c_str(), FEATURE_FILE) == 0)
4345     {
4346         //If the Input file is Feature file
4347         errorCode = trainFromFeatureFile(inputFilePath);
4348         if(errorCode != SUCCESS)
4349         {
4350             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
4351                 " NNShapeRecognizer::trainLVQ()" << endl;
4352 
4353             LTKReturnError(errorCode);
4354         }
4355 		PreprocParametersForFeatureFile(m_headerInfo);
4356 
4357     }
4358 
4359     // Now the Clustered ShapeSamples are stored in "prototypeSet"
4360     // Already computed "trainVec" contains all of the training data
4361 
4362     //Learning Part
4363     if(m_prototypeReductionFactor != 0)
4364     {
4365         errorCode = processPrototypeSetForLVQ();
4366         if(errorCode != SUCCESS)
4367         {
4368             LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
4369                 " NNShapeRecognizer::trainLVQ()" << endl;
4370 
4371             LTKReturnError(errorCode);
4372         }
4373     }
4374 
4375     ofstream mdtFileHandle;
4376 
4377     //Open the model data file
4378     if (m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
4379     {
4380         mdtFileHandle.open(m_nnMDTFilePath.c_str(), ios::app);
4381     }
4382     else
4383     {
4384         mdtFileHandle.open(m_nnMDTFilePath.c_str(), ios::app | ios::binary);
4385     }
4386 
4387     //If file not opened throw an exception
4388     if(!mdtFileHandle)
4389     {
4390         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EMODEL_DATA_FILE_OPEN << " " <<
4391             " Unable to open model data file : " <<m_nnMDTFilePath<<
4392             " NNShapeRecognizer::loadModelData()" << endl;
4393         LTKReturnError(EMODEL_DATA_FILE_OPEN);
4394     }
4395     //Writing results to the Model Data file
4396     errorCode = appendPrototypesToMDTFile(m_prototypeSet,mdtFileHandle);
4397     if(errorCode != SUCCESS)
4398     {
4399         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
4400             " NNShapeRecognizer::trainLVQ()" << endl;
4401 
4402         LTKReturnError(errorCode);
4403     }
4404 
4405     //Close the Model Data file
4406     mdtFileHandle.close();
4407 
4408     //Updating the Header Information
4409     updateHeaderWithAlgoInfo();
4410 
4411     //Adding header information	and checksum generation
4412     LTKCheckSumGenerate cheSumGen;
4413     errorCode = cheSumGen.addHeaderInfo(strModelDataHeaderInfoFile, m_nnMDTFilePath, m_headerInfo);
4414     if(errorCode != SUCCESS)
4415     {
4416         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
4417             " NNShapeRecognizer::trainLVQ()" << endl;
4418 
4419         LTKReturnError(errorCode);
4420     }
4421 
4422     //Time at the end of LVQ training
4423     m_OSUtilPtr->recordEndTime();
4424 
4425 	m_prototypeSet.clear();
4426 
4427     string timeTaken = "";
4428     m_OSUtilPtr->diffTime(timeTaken);
4429 
4430     cout << "Time Taken  = " << timeTaken << endl;
4431 
4432     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
4433         "NNShapeRecognizer::trainLVQ()" << endl;
4434     return SUCCESS;
4435 }
4436 /******************************************************************************
4437  * AUTHOR		: Saravanan
4438  * DATE			: 22-02-2007
4439  * NAME			: processPrototypeSetForLVQ
4440  * DESCRIPTION	:
4441  * ARGUMENTS		:
4442  * RETURNS		: none
4443  * NOTES			:
4444  * CHANGE HISTROY
4445  * Author Naveen Sundar G.	Date 11-Oct-2007	Description
4446  ******************************************************************************/
processPrototypeSetForLVQ()4447 int NNShapeRecognizer::processPrototypeSetForLVQ()
4448 {
4449 
4450     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
4451         "NNShapeRecognizer::processPrototypeSetForLVQ()" << endl;
4452     //Reference : http://www.cis.hut.fi/research/lvq_pak/lvq_doc.txt
4453     LTKShapeSample bestShapeSample;
4454 
4455 	int codeVecIndex = 5;
4456 	int trainSize = m_trainSet.size() ;
4457 	int train_index = 0;
4458 
4459 	//Number of iterations for LVQ
4460 	long length = m_prototypeSet.size() * m_LVQIterationScale;
4461 	long iter ;
4462 	long index;
4463 	// learning parameter
4464 	double c_alpha=m_LVQInitialAlpha;
4465 
4466         int errorCode = SUCCESS;
4467 
4468 	// initialize random seed
4469 	unsigned int randSeedVal ;
4470 
4471 	#ifdef WINCE
4472 		char szTime[10] ;
4473 		SYSTEMTIME st ;
4474 		GetLocalTime(&st) ;
4475 		sprintf(szTime, "%d%d%d", st.wHour, st.wMinute, st.wSecond) ;
4476 		randSeedVal = atoi(szTime);
4477 	#else
4478 		randSeedVal = time(NULL);
4479 	#endif
4480 		srand(randSeedVal) ;
4481 
4482 	for (iter=0; iter < length; ++iter )
4483 	{
4484 
4485 
4486 		cout<<"\n Amount of LVQ Training Completed = "<<(double)iter*100/length<<" %\n\n Current Value of Alpha \t  = "<<c_alpha<<"\n";
4487 		//To take the train vector at a random index
4488                 index = rand()%trainSize;
4489                 errorCode = trainRecognize(m_trainSet.at(index), bestShapeSample, codeVecIndex);
4490 
4491                 if(errorCode != SUCCESS)
4492                 {
4493                     LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
4494                         " NNShapeRecognizer::morphVector()" << endl;
4495 
4496                     LTKReturnError(errorCode);
4497                 }
4498 
4499 
4500                 if(bestShapeSample.getClassID() == m_trainSet.at(index).getClassID())
4501                 {
4502                     //Move the codeVec closer (Match)
4503                     c_alpha = linearAlpha(iter,length,m_LVQInitialAlpha,c_alpha,+1);
4504                     errorCode = morphVector(m_trainSet.at(index), -c_alpha, bestShapeSample);
4505                     if(errorCode != SUCCESS)
4506                     {
4507                         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
4508                             " NNShapeRecognizer::morphVector()" << endl;
4509 
4510                         LTKReturnError(errorCode);
4511                     }
4512                 }
4513                 else
4514                 {
4515                     //Move the codeVec away (No Match)
4516                     c_alpha = linearAlpha(iter,length,m_LVQInitialAlpha,c_alpha,-1);
4517                     errorCode = morphVector(m_trainSet.at(index), c_alpha, bestShapeSample);
4518                     if(errorCode != SUCCESS)
4519                     {
4520                         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
4521                             " NNShapeRecognizer::morphVector()" << endl;
4522 
4523                         LTKReturnError(errorCode);
4524                     }
4525                 }
4526 
4527                 //Now update the prototypeSet with the morphed vector
4528 
4529                 const vector<LTKShapeFeaturePtr>& tempFeatVec = (bestShapeSample).getFeatureVector();
4530                 m_prototypeSet.at(codeVecIndex).setFeatureVector(tempFeatVec);
4531 	}
4532 
4533 	m_trainSet.clear();
4534 
4535 	cout<<"\n Amount of LVQ Training Completed = "<<(double) 100<<" %\n\n Current Value of Alpha \t  = "<<c_alpha<<"\n\n\n";
4536 
4537 
4538     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
4539         "NNShapeRecognizer::processPrototypeSetForLVQ()" << endl;
4540 	return SUCCESS;
4541 }
4542 
4543 /******************************************************************************
4544  * AUTHOR		: N. Sridhar Krishna
4545  * DATE			: 24-03-2006
4546  * NAME			: linearAlpha
4547  * DESCRIPTION	: this function is called from trainLVQ - linearly decreasing learning parameter in learing vector quantization
4548  * ARGUMENTS		:
4549  * RETURNS		: learning parameter (alpha)
4550  * NOTES			:
4551  * CHANGE HISTROY
4552  * Author Naveen Sundar G.	Date 11-Oct-2007	Description
4553  ******************************************************************************/
linearAlpha(long iter,long length,double & initialAlpha,double lastAlpha,int correctDecision)4554 float NNShapeRecognizer:: linearAlpha(long iter, long length, double& initialAlpha, double lastAlpha,int correctDecision)
4555 {
4556 
4557         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
4558         "NNShapeRecognizer::linearAlpha()" << endl;
4559 	// return ( (initialAlpha * ( ( (double) (length - iter)) / (double) length )));
4560 	// return (alpha *( (double ) 1/iter));
4561 
4562 	//  Reference : http://www.cis.hut.fi/research/lvq_pak/lvq_doc.txt
4563 
4564 	float currentAlpha;
4565 	currentAlpha=lastAlpha/(1+correctDecision*lastAlpha);
4566 
4567 	if (currentAlpha >initialAlpha)
4568 		currentAlpha=initialAlpha;
4569 
4570         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
4571         "NNShapeRecognizer::linearAlpha()" << endl;
4572 
4573         return currentAlpha;
4574 
4575 }
4576 
4577 /**********************************************************************************
4578 * AUTHOR		: N. Sridhar Krishna
4579 * DATE			: 24-03-2006
4580 * NAME			: morphVector
4581 * DESCRIPTION	: This function does the reshaping of prototype vector (called from trainLVQ)
4582 * ARGUMENTS		: The input parameters are the code vector, data vector (learning example in the context of LVQ), and alpha (learning parameter)
4583 *				  @param bestcodeVec is the character which we are trying to morph
4584 *						 the function modifies the character bestcodeVec
4585 * RETURNS		: SUCCESS on successful training
4586 * NOTES			:
4587 * CHANGE HISTROY
4588 * Author Naveen Sundar G. Date				Description
4589 *************************************************************************************/
morphVector(const LTKShapeSample & dataShapeSample,double talpha,LTKShapeSample & bestShapeSample)4590 int NNShapeRecognizer::morphVector(const LTKShapeSample& dataShapeSample,
4591 		double talpha, LTKShapeSample& bestShapeSample)
4592 {
4593 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<
4594 		"Enter NNShapeRecognizer::morphVector"<<endl;
4595 
4596 	vector<LTKShapeFeaturePtr> bestFeatureVector = bestShapeSample.getFeatureVector();
4597 	const vector<LTKShapeFeaturePtr>& dataFeatureVector = dataShapeSample.getFeatureVector();
4598 
4599 	int index=0;
4600 	int bestFVSize = bestFeatureVector.size();
4601 	int dataFVSize = dataFeatureVector.size();
4602 
4603         int errorCode = SUCCESS;
4604 
4605 	if(bestFVSize !=dataFVSize)
4606 	{
4607 		LTKReturnError(EMORPH_FVEC_SIZE_MISMATCH);
4608 	}
4609 
4610 	float temp1 = 0;
4611 
4612 
4613 
4614 	for(index=0; index < bestFVSize ; ++index)
4615         {
4616             LTKShapeFeaturePtr temp1;
4617             LTKShapeFeaturePtr temp2;
4618             LTKShapeFeaturePtr temp3;
4619 
4620 
4621             errorCode = bestFeatureVector[index]->subtractFeature(dataFeatureVector[index],temp1);
4622             if(errorCode != SUCCESS)
4623             {
4624                 LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
4625                     " NNShapeRecognizer::morphVector()" << endl;
4626 
4627                 LTKReturnError(errorCode);
4628             }
4629 
4630             errorCode = temp1->scaleFeature(talpha,temp2);
4631             if(errorCode != SUCCESS)
4632             {
4633                 LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
4634                     " NNShapeRecognizer::morphVector()" << endl;
4635 
4636                 LTKReturnError(errorCode);
4637             }
4638 
4639             errorCode = bestFeatureVector[index]->addFeature(temp2,temp3);
4640             if(errorCode != SUCCESS)
4641             {
4642                 LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
4643                     " NNShapeRecognizer::morphVector()" << endl;
4644 
4645                 LTKReturnError(errorCode);
4646             }
4647 
4648             bestFeatureVector[index] = temp3;
4649 
4650         }
4651 
4652         bestShapeSample.setFeatureVector(bestFeatureVector);
4653 
4654         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG)<<"Exit NNShapeRecognizer::morphVector"<<endl;
4655 
4656 	return SUCCESS;
4657 
4658 }
4659 
4660 /**********************************************************************************
4661  * AUTHOR               : N. Sridhar Krishna
4662  * DATE                 : 23-03-2006
4663  * NAME                 : trainRecognize (overloaded with 4 args)
4664  * DESCRIPTION          : This function does the recognition function required for training phase (called from trainLVQ)
4665  * ARGUMENTS            : The input parameter are the inFeatureVector, 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
4666  * @param inFeatureVector is the character which we are trying to recognise.
4667  * @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
4668  * RETURNS              : SUCCESS on successful reading of the allocation statistics
4669  * NOTES                        :
4670  * CHANGE HISTROY
4671  * Author                       Date                            Description
4672  *************************************************************************************/
trainRecognize(LTKShapeSample & inShapeSample,LTKShapeSample & bestShapeSample,int & codeVecIndex)4673 int NNShapeRecognizer::trainRecognize(LTKShapeSample& inShapeSample,
4674 		LTKShapeSample& bestShapeSample,int& codeVecIndex)
4675 
4676 {
4677 
4678         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
4679         "NNShapeRecognizer::trainRecognize()" << endl;
4680 	//Variable to store the Euclidean distance.
4681 	float localDistance = 0.0;
4682 
4683 	//Iterator for prototypeSet
4684 	vector <LTKShapeSample>::const_iterator prototypeSetIter = m_prototypeSet.begin();
4685 	vector <LTKShapeSample>::const_iterator prototypeSetIterEnd = m_prototypeSet.end();
4686 
4687 	//The top choice index
4688 	int bestIndex = 0;
4689 
4690 	//The top choice distance (FLT_MAX indicates the maximum value for float)
4691 	float bestMinDist = FLT_MAX;
4692 
4693         int errorCode = SUCCESS;
4694 
4695 	for(int j = 0; prototypeSetIter != prototypeSetIterEnd; ++prototypeSetIter, j++)
4696 	{
4697 		localDistance=0;
4698 		if(LTKSTRCMP(m_LVQDistanceMeasure.c_str(), EUCLIDEAN_DISTANCE) == 0)
4699 		{
4700 			errorCode = computeEuclideanDistance(*prototypeSetIter,
4701 					   				inShapeSample,
4702 									localDistance);
4703 
4704                         if(errorCode != SUCCESS)
4705                         {
4706                             LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
4707                                 " NNShapeRecognizer::trainRecognize()" << endl;
4708 
4709                             LTKReturnError(errorCode);
4710                         }
4711 		}
4712 		if(LTKSTRCMP(m_LVQDistanceMeasure.c_str(), DTW_DISTANCE) == 0)
4713 		{
4714 			errorCode = computeDTWDistance(*prototypeSetIter,
4715 					   				inShapeSample,
4716 									localDistance);
4717 
4718                         if(errorCode != SUCCESS)
4719                         {
4720                             LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: " << errorCode << " " <<
4721                                 " NNShapeRecognizer::trainRecognize()" << endl;
4722 
4723                             LTKReturnError(errorCode);
4724                         }
4725 		}
4726 
4727 		//BestSofar Value for BSF computation using Euclidean distance
4728 		if(bestMinDist > localDistance )
4729 		{
4730 			//bestMinDist is the Minimum Distance
4731 			bestMinDist = localDistance;
4732 			//bestIndex is the best match for the given character
4733 			bestIndex = j;
4734 		}
4735 	}
4736 
4737 	//Get the shape id of the best match from the prototypeSet
4738 	bestShapeSample.setClassID((m_prototypeSet.at(bestIndex)).getClassID());
4739 
4740 	//Get the Feature vector of the best match from the prototypeSet
4741 	const vector<LTKShapeFeaturePtr>& tempFeatureVector =
4742 							(m_prototypeSet.at(bestIndex)).getFeatureVector();
4743 	bestShapeSample.setFeatureVector(tempFeatureVector);
4744 
4745 	codeVecIndex = bestIndex ;
4746 
4747         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
4748         "NNShapeRecognizer::trainRecognize()" << endl;
4749 	return SUCCESS;
4750 }
4751 
4752 
4753 /**********************************************************************************
4754  * AUTHOR		: Saravanan. R
4755  * DATE			: 25-01-2007
4756  * NAME			: deletePreprocessor
4757  * DESCRIPTION	: This method is used to deletes the PreProcessor instance
4758  * ARGUMENTS		: ptrPreprocInstance : Holds the pointer to the LTKPreprocessorInterface
4759  * RETURNS		: none
4760  * NOTES			:
4761  * CHANGE HISTROY
4762  * Author			Date				Description
4763  *************************************************************************************/
4764 
4765 //int NNShapeRecognizer::deletePreprocessor(LTKPreprocessorInterface *ptrPreprocInstance)
deletePreprocessor()4766 int NNShapeRecognizer::deletePreprocessor()
4767 {
4768 
4769     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
4770         "NNShapeRecognizer::deletePreprocessor()" << endl;
4771 
4772     //deleting the preprocessor instance
4773     if(m_ptrPreproc != NULL)
4774     {
4775         m_deleteLTKLipiPreProcessor(m_ptrPreproc);
4776         m_ptrPreproc = NULL;
4777     }
4778 
4779     //Unload the dll
4780     int returnStatus = unloadPreprocessorDLL();
4781     if(returnStatus != SUCCESS)
4782     {
4783         LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Error: " <<
4784             getErrorMessage(returnStatus) <<
4785             " NNShapeRecognizer::deletePreprocessor()" << endl;
4786         LTKReturnError(returnStatus);
4787     }
4788 
4789     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
4790         "NNShapeRecognizer::deletePreprocessor()" << endl;
4791 
4792     return SUCCESS;
4793 }
4794 
4795 /**************************************************************************
4796  * AUTHOR		: Nidhi Sharma
4797  * DATE			: 29-01-2007
4798  * NAME			: unloadPreprocessorDLL
4799  * DESCRIPTION	: This method is used to Unloads the preprocessor DLL.
4800  * ARGUMENTS		: none
4801  * RETURNS		: none
4802  * NOTES			:
4803  * CHANGE HISTROY
4804  * Author			Date				Description
4805  ****************************************************************************/
unloadPreprocessorDLL()4806 int NNShapeRecognizer::unloadPreprocessorDLL()
4807 {
4808     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
4809         "NNShapeRecognizer::unloadPreprocessorDLL()" << endl;
4810 
4811 
4812     //Check the preprocessor DLL was loaded already
4813     if(m_libHandler != NULL)
4814     {
4815         //Unload the DLL
4816 		m_OSUtilPtr->unloadSharedLib(m_libHandler);
4817         m_libHandler = NULL;
4818     }
4819 
4820     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
4821         "NNShapeRecognizer::unloadPreprocessorDLL()" << endl;
4822 
4823     return SUCCESS;
4824 }
4825 
4826 /**************************************************************************
4827  * AUTHOR		: Srinivasa Vithal, Ch
4828  * DATE			: 20-06-2008
4829  * NAME			: validatePreprocParameters
4830  * DESCRIPTION	: This method is used to validate the preproc parameters with
4831  *						mdt header values
4832  * ARGUMENTS		: none
4833  * RETURNS		: none
4834  * NOTES			:
4835  * CHANGE HISTROY
4836  * Author			Date				Description
4837  ****************************************************************************/
validatePreprocParameters(stringStringMap & headerSequence)4838 int NNShapeRecognizer::validatePreprocParameters(stringStringMap& headerSequence)
4839 {
4840     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
4841         "NNShapeRecognizer::validatePreprocParameters()" << endl;
4842 	string tempStrVar = "";
4843     string headerValue = "";
4844     int headerValueInt   = 0;
4845     float headerValueFloat = 0.0f;
4846     int tempIntegerValue = 0;
4847     float tempFloatValue = 0.0f;
4848 
4849 	//preproc sequence
4850     string mdtPreprocSeqn = headerSequence[PREPROC_SEQ];
4851     if(LTKSTRCMP(m_preProcSeqn.c_str(), mdtPreprocSeqn.c_str()) != 0 &&
4852 	   LTKSTRCMP("NA", mdtPreprocSeqn.c_str()) != 0)
4853     {
4854         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
4855             "Value of preprocSeqn in config file ("<<
4856             m_preProcSeqn <<") does not match with the value in MDT file ("<<
4857             mdtPreprocSeqn <<")"<<
4858             " NNShapeRecognizer::loadModelData()" << endl;
4859         LTKReturnError(ECONFIG_MDT_MISMATCH);
4860     }
4861 
4862     //ResampTraceDimension
4863     headerValue = "";
4864 	if(LTKSTRCMP("NA", headerSequence[TRACE_DIM].c_str()) != 0)
4865     {
4866 		headerValueInt = atoi(headerSequence[TRACE_DIM].c_str());
4867 		tempIntegerValue = m_ptrPreproc->getTraceDimension();
4868 
4869 		if(headerValueInt != tempIntegerValue )
4870 		{
4871 			LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
4872 				"Value of TraceDimension in config file ("<<
4873 				tempIntegerValue<<") does not match with the value in MDT file ("<<
4874 				headerValueInt <<")"<<
4875 				" NNShapeRecognizer::loadModelData()" << endl;
4876 			LTKReturnError(ECONFIG_MDT_MISMATCH);
4877 		}
4878 	}
4879 
4880     // preserve aspect ratio
4881 	bool preProcPreserveAspectRatio = m_ptrPreproc->getPreserveAspectRatio();
4882 	tempStrVar = "false";
4883 	if (preProcPreserveAspectRatio == true)
4884 	{
4885 		tempStrVar = "true";
4886 	}
4887 
4888     if(LTKSTRCMP((headerSequence[PRESER_ASP_RATIO]).c_str(), tempStrVar.c_str()) != 0 &&
4889 		LTKSTRCMP((headerSequence[PRESER_ASP_RATIO]).c_str(), "NA") != 0)
4890     {
4891         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
4892             "Value of preProcPreserveAspectRatio in config file ("<<
4893             tempStrVar<<") does not match with the value in MDT file ("<<
4894             headerSequence[PRESER_ASP_RATIO] <<")"<<
4895             " NNShapeRecognizer::loadModelData()" << endl;
4896         LTKReturnError(ECONFIG_MDT_MISMATCH);
4897     }
4898 
4899 	//NormPreserveRelativeYPosition
4900 	bool preProcNormPreserveRelativeYPosition = m_ptrPreproc->getPreserveRealtiveYPosition();
4901 	tempStrVar = "false";
4902 	if (preProcNormPreserveRelativeYPosition == true)
4903 		{
4904 			tempStrVar = "true";
4905 		}
4906 
4907     if(LTKSTRCMP((headerSequence[PRESER_REL_Y_POS]).c_str(), tempStrVar.c_str()) != 0 &&
4908 		LTKSTRCMP((headerSequence[PRESER_REL_Y_POS]).c_str(), "NA") != 0)
4909     {
4910         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
4911             "Value of preProcNormPreserveRelativeYPosition in config file ("<<
4912             tempStrVar<<") does not match with the value in MDT file ("<<
4913             headerSequence[PRESER_REL_Y_POS] <<")"<<
4914             " NNShapeRecognizer::loadModelData()" << endl;
4915         LTKReturnError(ECONFIG_MDT_MISMATCH);
4916     }
4917 
4918 	// NormPreserveAspectRatioThreshold
4919 	tempFloatValue = m_ptrPreproc->getAspectRatioThreshold();
4920 	if(LTKSTRCMP((headerSequence[ASP_RATIO_THRES]).c_str(), "NA") != 0)
4921     {
4922         headerValueFloat = LTKStringUtil::convertStringToFloat(headerSequence[ASP_RATIO_THRES]);
4923 
4924 		if(headerValueFloat != tempFloatValue)
4925 		{
4926 			LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
4927 				"Value of preProcPreserveAspectRatioThreshold in config file ("<<
4928 				tempFloatValue<<") does not match with the value in MDT file ("<<
4929 				headerValueFloat <<")"<<
4930 				" NNShapeRecognizer::loadModelData()" << endl;
4931 			LTKReturnError(ECONFIG_MDT_MISMATCH);
4932 		}
4933 	}
4934 
4935 	// NormLineWidthThreshold
4936 	if(LTKSTRCMP((headerSequence[DOT_SIZE_THRES]).c_str(), "NA") != 0)
4937     {
4938         headerValueFloat = LTKStringUtil::convertStringToFloat(headerSequence[DOT_SIZE_THRES]);
4939 		tempFloatValue = m_ptrPreproc->getSizeThreshold();
4940 
4941 		if(headerValueFloat !=  tempFloatValue)
4942 		{
4943 			LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
4944 				"Value of preProcNormLineWidthThreshold in config file ("<<
4945 				tempFloatValue<<") does not match with the value in MDT file ("<<
4946 				headerValueFloat <<")"<<
4947 				" NNShapeRecognizer::loadModelData()" << endl;
4948 			LTKReturnError(ECONFIG_MDT_MISMATCH);
4949 		}
4950 	}
4951 
4952 	// NormDotSizeThreshold
4953 	if(LTKSTRCMP((headerSequence[DOT_THRES]).c_str(), "NA") != 0)
4954     {
4955         headerValueFloat = LTKStringUtil::convertStringToFloat(headerSequence[DOT_THRES]);
4956 		tempFloatValue = m_ptrPreproc->getDotThreshold();
4957 
4958 		if(headerValueFloat != tempFloatValue)
4959 		{
4960 			LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
4961 				"Value of preProcNormDotSizeThreshold in config file ("<<
4962 				tempFloatValue<<") does not match with the value in MDT file ("<<
4963 				headerValueFloat <<")"<<
4964 				" NNShapeRecognizer::loadModelData()" << endl;
4965 			LTKReturnError(ECONFIG_MDT_MISMATCH);
4966 		}
4967 	}
4968 	//ResampPointAllocation
4969 	tempStrVar = "";
4970 	tempStrVar = m_ptrPreproc->getResamplingMethod();
4971 	if(LTKSTRCMP((headerSequence[RESAMP_POINT_ALLOC]).c_str(), tempStrVar.c_str()) != 0 &&
4972 		LTKSTRCMP((headerSequence[RESAMP_POINT_ALLOC]).c_str(), "NA") != 0)
4973     {
4974         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
4975             "Value of preProcResampPointAllocation in config file ("<<
4976             tempStrVar<<") does not match with the value in MDT file ("<<
4977             headerSequence[RESAMP_POINT_ALLOC] <<")"<<
4978             " NNShapeRecognizer::loadModelData()" << endl;
4979         LTKReturnError(ECONFIG_MDT_MISMATCH);
4980     }
4981 
4982 
4983 	//SmoothWindowSize
4984 	if(LTKSTRCMP((headerSequence[SMOOTH_WIND_SIZE]).c_str(), "NA") != 0)
4985 	{
4986 		headerValueInt = atoi(headerSequence[SMOOTH_WIND_SIZE].c_str());
4987 		tempIntegerValue = m_ptrPreproc->getFilterLength();
4988 
4989 		if(headerValueInt != tempIntegerValue)
4990 		{
4991 			LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<  ECONFIG_MDT_MISMATCH << " " <<
4992 				"Value of preProcSmoothWindowSize in config file ("<<
4993 				tempIntegerValue<<") does not match with the value in MDT file ("<<
4994 				headerValueInt <<")"<<
4995 				" NNShapeRecognizer::loadModelData()" << endl;
4996 			LTKReturnError(ECONFIG_MDT_MISMATCH);
4997 		}
4998 	}
4999     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
5000         "NNShapeRecognizer::validatePreprocParameters()" << endl;
5001 	return SUCCESS;
5002 
5003 }
5004 /******************************************************************************
5005  * AUTHOR		: Saravanan
5006  * DATE			: 22-02-2007
5007  * NAME			: trainFromFeatureFile
5008  * DESCRIPTION	: This method will do the training by giving the Feature
5009  *				  file as input
5010  * ARGUMENTS	:
5011  * RETURNS		: none
5012  * NOTES		:
5013  * CHANGE HISTROY
5014  * Author			Date				Description
5015  ******************************************************************************/
5016 
trainFromFeatureFile(const string & featureFilePath)5017 int NNShapeRecognizer::trainFromFeatureFile(const string& featureFilePath)
5018 {
5019     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
5020         "NNShapeRecognizer::trainFromFeatureFile()" << endl;
5021 
5022     //Count for the no. of samples read for a shape
5023     int sampleCount = 0;
5024 
5025     //Count of the no. of shapes read so far
5026     int shapeCount = 0;
5027 
5028     //ID for each shapes
5029     int shapeId = -1;
5030 
5031     //classId of the character
5032     int prevClassId = -1;
5033 
5034     //Flag to skip reading a newline in the list file, when a new class starts
5035     bool lastshapeIdFlag = false;
5036 
5037     //Flag is set when EOF is reached
5038     bool eofFlag = false;
5039 
5040     //Line from the list file
5041     string line = "";
5042 
5043     //Indicates the first class
5044     bool initClassFlag = false;
5045 
5046     //Output Stream for MDT file
5047     ofstream mdtFileHandle;
5048 
5049     //Input Stream for feature file
5050     ifstream featureFileHandle;
5051 
5052     LTKShapeSample shapeSampleFeatures;
5053 
5054     vector<LTKShapeSample> shapeSamplesVec;
5055 
5056     vector<LTKShapeSample> clusteredShapeSampleVec;
5057 
5058 
5059     //Opening the feature file for reading mode
5060     featureFileHandle.open(featureFilePath.c_str(), ios::in);
5061 
5062     //Throw an error if unable to open the training list file
5063     if(!featureFileHandle)
5064     {
5065         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EFEATURE_FILE_OPEN << " " <<
5066             getErrorMessage(EFEATURE_FILE_OPEN) <<
5067             " NNShapeRecognizer::trainFromFeatureFile()" << endl;
5068         LTKReturnError(EFEATURE_FILE_OPEN);
5069 
5070     }
5071     //Open the Model data file for writing mode
5072     if ( m_MDTFileOpenMode == NN_MDT_OPEN_MODE_ASCII )
5073     {
5074         mdtFileHandle.open(m_nnMDTFilePath.c_str(), ios::out);
5075     }
5076     else
5077     {
5078         mdtFileHandle.open(m_nnMDTFilePath.c_str(), ios::out|ios::binary);
5079     }
5080 
5081     //Return  error if unable to open the Model data file
5082     if(!mdtFileHandle)
5083     {
5084         featureFileHandle.close();
5085         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< EMODEL_DATA_FILE_OPEN << " " <<
5086             getErrorMessage(EMODEL_DATA_FILE_OPEN) <<
5087             " NNShapeRecognizer::trainFromFeatureFile()" << endl;
5088         LTKReturnError(EMODEL_DATA_FILE_OPEN);
5089     }
5090 
5091 	//Reading feature file header
5092     getline(featureFileHandle, line, NEW_LINE_DELIMITER);
5093     stringStringMap headerSequence;
5094     int errorCode = SUCCESS;
5095     errorCode = m_shapeRecUtil.convertHeaderToStringStringMap(line, headerSequence);
5096     if(errorCode != SUCCESS)
5097     {
5098         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
5099             " NNShapeRecognizer::trainFromFeatureFile()" << endl;
5100         LTKReturnError(errorCode);
5101     }
5102 
5103 
5104 
5105     //Write the number of Shapes
5106     mdtFileHandle << m_numShapes << endl;
5107 
5108     //write Trace Dimension of input vector into the file
5109 	 // mdtFileHandle << m_traceDimension << endl;
5110 
5111 
5112     while(!featureFileHandle.eof())
5113     {
5114         if( lastshapeIdFlag == false )
5115         {
5116             //Get a line from the feature file
5117             getline(featureFileHandle, line, NEW_LINE_DELIMITER);
5118 
5119             if( featureFileHandle.eof() )
5120             {
5121                 eofFlag = true;
5122             }
5123 
5124             if((getShapeSampleFromString(line, shapeSampleFeatures) != SUCCESS) && (eofFlag == false) )
5125                 continue;
5126 
5127             shapeId = shapeSampleFeatures.getClassID();
5128 
5129 			if(eofFlag == false)
5130 			{
5131 				if(shapeId < 0)
5132 				{
5133 					LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<<
5134 						"The NN Shape recognizer requires training file class Ids to be positive integers and listed in the increasing order" <<
5135 						" NNShapeRecognizer::trainFromFeatureFile()" << endl;
5136 					errorCode = EINVALID_SHAPEID;
5137 					break;
5138 				}
5139 				else if(shapeId < prevClassId)
5140 				{
5141 					LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<<
5142 						"Shape IDs in the train list file should be in the increasing order. Please use scripts/validateListFile.pl to generate list files." <<
5143 						" NNShapeRecognizer::trainFromFeatureFile()" << endl;
5144 					errorCode = EINVALID_ORDER_LISTFILE;
5145 					break;
5146 				}
5147 			}
5148 
5149             if( initClassFlag == false )
5150             {
5151                 initClassFlag = true;
5152                 prevClassId=shapeId;
5153             }
5154 
5155         }
5156         else //Do not read next line during this iteration
5157         {
5158             //flag unset to read next line during the next iteration
5159             lastshapeIdFlag = false;
5160         }
5161         // Sample of the same class seen, keep pushing to the shapeSamplesVec
5162         if( shapeId == prevClassId )
5163         {
5164             shapeSamplesVec.push_back(shapeSampleFeatures);
5165             ++sampleCount;
5166             //All the samples are pushed to trainSet used only for trainLVQ
5167             //trainSet was NULL for Clustering and not NULL for LVQ
5168             if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_LVQ)
5169 					== 0 && m_prototypeReductionFactor != 0)
5170 				m_trainSet.push_back(shapeSampleFeatures);
5171 
5172             shapeSampleFeatures.clearShapeSampleFeatures();
5173         }
5174         // Sample of a new class seen, or end of feature file reached, train the recognizer on the samples of the previous class
5175         if( shapeId != prevClassId || eofFlag == true )
5176         {
5177             //Increase shape count only if there are atleast one sample per class
5178             if( sampleCount > 0 )
5179                 shapeCount++;
5180 
5181             //check that shapecount must not be greater than specified number
5182             //of shapes, if projecttype was not dynamic
5183             if( !m_projectTypeDynamic && shapeCount > m_numShapes )
5184             {
5185                 errorCode = EINVALID_NUM_OF_SHAPES;
5186                 break;
5187             }
5188 
5189             if( shapeCount > 0 && sampleCount > 0 )
5190             {
5191                 errorCode = performClustering(shapeSamplesVec, clusteredShapeSampleVec);
5192 
5193                 if( errorCode != SUCCESS )
5194                 {
5195                     LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
5196                         " NNShapeRecognizer::trainFromFeatureFile()" << endl;
5197                     LTKReturnError(errorCode);
5198                 }
5199 
5200 
5201                 if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_LVQ) == 0)
5202                 {
5203                     //Push all the samples after clustering into prototypeSet
5204                     for( int i = 0; i < clusteredShapeSampleVec.size(); ++i )
5205                     {
5206                         m_prototypeSet.push_back(clusteredShapeSampleVec[i]);
5207                     }
5208                 }
5209                 else if(LTKSTRCMP(m_prototypeSelection.c_str(), PROTOTYPE_SELECTION_CLUSTERING) == 0)
5210                 {
5211                     //Writing results to the MDT file
5212                     errorCode = appendPrototypesToMDTFile(clusteredShapeSampleVec, mdtFileHandle);
5213                     if( errorCode != SUCCESS )
5214                     {
5215                         LOG(LTKLogger::LTK_LOGLEVEL_ERR)<<"Error: "<< errorCode << " " <<
5216                             " NNShapeRecognizer::trainFromFeatureFile()" << endl;
5217                         LTKReturnError(errorCode);
5218                     }
5219                 }
5220 
5221                 //Clearing the shapeSampleVector and clusteredShapeSampleVector
5222 
5223                 clusteredShapeSampleVec.clear();
5224                 shapeSamplesVec.clear();
5225                 //Resetting sampleCount for the next class
5226                 sampleCount = 0;
5227 
5228                 //Set the flag so that the already read line of next class in the list file is not lost
5229                 lastshapeIdFlag = true;
5230 
5231                 prevClassId = shapeId;
5232             }
5233         }
5234     }
5235 
5236     featureFileHandle.close();
5237     mdtFileHandle.close();
5238 
5239     if(!m_projectTypeDynamic && shapeCount != m_numShapes)
5240     {
5241         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< EINVALID_NUM_OF_SHAPES << " " <<
5242             getErrorMessage(EINVALID_NUM_OF_SHAPES) <<
5243             " NNShapeRecognizer::trainFromFeatureFile()" << endl;
5244         LTKReturnError(EINVALID_NUM_OF_SHAPES);
5245     }
5246 
5247     if(errorCode != SUCCESS)
5248     {
5249         LOG(LTKLogger::LTK_LOGLEVEL_ERR) << "Error: "<< errorCode << " " <<
5250             " NNShapeRecognizer::trainFromFeatureFile()" << endl;
5251         LTKReturnError(errorCode);
5252     }
5253 
5254     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
5255         "NNShapeRecognizer::trainFromFeatureFile()" << endl;
5256 
5257     return SUCCESS;
5258 }
5259 
5260 /**************************************************************************
5261  * AUTHOR		: Balaji MNA
5262  * DATE			: 01-DEC-2008
5263  * NAME			: validatePreprocParameters
5264  * DESCRIPTION	: This method is used to update the preproc parameters for
5265  *				  featurefile
5266  * ARGUMENTS	: none
5267  * RETURNS		: none
5268  * NOTES		:
5269  * CHANGE HISTROY
5270  * Author			Date				Description
5271  ****************************************************************************/
PreprocParametersForFeatureFile(stringStringMap & headerSequence)5272 int NNShapeRecognizer::PreprocParametersForFeatureFile(stringStringMap& headerSequence)
5273 {
5274     LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Entering " <<
5275         "NNShapeRecognizer::PreprocParametersForFeatureFile()" << endl;
5276 
5277 	//preproc sequence
5278     headerSequence[PREPROC_SEQ] = "NA";
5279     //ResampTraceDimension
5280     headerSequence[TRACE_DIM] = "NA";
5281     // preserve aspect ratio
5282     headerSequence[PRESER_ASP_RATIO] = "NA";
5283 	//NormPreserveRelativeYPosition
5284     headerSequence[PRESER_REL_Y_POS] = "NA";
5285 	// NormPreserveAspectRatioThreshold
5286     headerSequence[ASP_RATIO_THRES] = "NA";
5287 	// NormLineWidthThreshold
5288 	headerSequence[DOT_SIZE_THRES] = "NA";
5289 	// NormDotSizeThreshold
5290 	headerSequence[DOT_THRES] = "NA";
5291 	//ResampPointAllocation
5292 	headerSequence[RESAMP_POINT_ALLOC] = "NA";
5293 	//SmoothWindowSize
5294 	headerSequence[SMOOTH_WIND_SIZE] = "NA";
5295 
5296 	LOG(LTKLogger::LTK_LOGLEVEL_DEBUG) << "Exiting " <<
5297         "NNShapeRecognizer::PreprocParametersForFeatureFile()" << endl;
5298 	return SUCCESS;
5299 
5300 }
5301 
5302 /**********************************************************************************
5303 * AUTHOR		: Tarun Madan
5304 * DATE			: 30-Aug-2007
5305 * NAME			: adapt
5306 * DESCRIPTION	: adapt recent recognized sample
5307 * ARGUMENTS		: shapeID : True shapeID of sample
5308 * RETURNS		: Success : If sample was adapted successfully
5309 *				  Failure : Returns Error Code
5310 * NOTES			:
5311 * CHANGE HISTROY
5312 * Author			Date				Description
5313 *************************************************************************************/
adapt(int shapeId)5314 int NNShapeRecognizer::adapt(int shapeId)
5315 {
5316 	try{
5317 		LOG(LTKLogger::LTK_LOGLEVEL_INFO)
5318 				<< "Enter NNShapeRecognizer::adapt()"<<endl;
5319 
5320 		//Validate shapeID
5321 		map<int,int>::iterator m_shapeIDNumPrototypesMapIter;
5322 		if(m_shapeIDNumPrototypesMap.find(shapeId) == m_shapeIDNumPrototypesMap.end())
5323 		{
5324 			LTKReturnError(EINVALID_SHAPEID);
5325 		}
5326 
5327 		//Adaptation Code
5328 		LTKAdapt* adaptObj = LTKAdapt::getInstance(this);
5329 
5330 		int nErrorCode;
5331 		nErrorCode = adaptObj->adapt(shapeId);
5332 		if(nErrorCode !=0)
5333 		{
5334 			LOG(LTKLogger::LTK_LOGLEVEL_ERR)
5335 				<< "Error during NNShapeRecognizer::adapt()"<<endl;
5336 			LTKReturnError(nErrorCode);
5337 		}
5338 
5339 		//Clear Variables cached
5340 		m_neighborInfoVec.clear();
5341 		m_vecRecoResult.clear();
5342 
5343 	}
5344 	catch(...)
5345 	{
5346 		LOG(LTKLogger::LTK_LOGLEVEL_ERR)
5347 				<< "Error during NNShapeRecognizer::adapt()"<<endl;
5348 		return FAILURE;
5349 	}
5350 
5351 	LOG(LTKLogger::LTK_LOGLEVEL_INFO)
5352 			<< "Exit NNShapeRecognizer::adapt()"<<endl;
5353 
5354 	return SUCCESS;
5355 }
5356 
5357 /**********************************************************************************
5358 * AUTHOR		: Tarun Madan
5359 * DATE			: 30-Aug-2007
5360 * NAME			: adapt
5361 * DESCRIPTION	: adapt sample passed as argument
5362 * ARGUMENTS		: sampleTraceGroup :  TraceGroup of sample to be adapted
5363 *				  shapeID : True shapeID of sample
5364 * RETURNS		: Success : If sample was adapted successfully
5365 *				  Failure : Returns Error Code
5366 * NOTES			:
5367 * CHANGE HISTROY
5368 * Author			Date				Description
5369 *************************************************************************************/
adapt(const LTKTraceGroup & sampleTraceGroup,int shapeId)5370 int NNShapeRecognizer::adapt(const LTKTraceGroup& sampleTraceGroup, int shapeId )
5371 {
5372 	LOG(LTKLogger::LTK_LOGLEVEL_INFO)
5373 			<< "Enter NNShapeRecognizer::Adapt()"<<endl;
5374 
5375 	vector<int> vecSubSet;
5376 	vector<LTKShapeRecoResult> vecRecoResult;
5377 	LTKScreenContext objScreenContext;
5378 	int nErrorCode;
5379 	nErrorCode = recognize(
5380 					sampleTraceGroup,
5381 					objScreenContext,
5382 					vecSubSet,
5383 					CONF_THRESHOLD_FILTER_OFF,
5384 					NN_DEF_RECO_NUM_CHOICES,
5385 					vecRecoResult
5386 					);
5387 
5388 	if(nErrorCode !=0)
5389 	{
5390 		LOG(LTKLogger::LTK_LOGLEVEL_ERR)
5391 			<< "Error during call to recognize in NNShapeRecognizer::Adapt()"<<endl;
5392 		LTKReturnError(nErrorCode);
5393 	}
5394 
5395 	nErrorCode = adapt(shapeId);
5396 	if(nErrorCode !=0)
5397 	{
5398 		LOG(LTKLogger::LTK_LOGLEVEL_ERR)
5399 			<< "Error during NNShapeRecognizer::Adapt()"<<endl;
5400 		LTKReturnError(nErrorCode);
5401 	}
5402 
5403 	LOG(LTKLogger::LTK_LOGLEVEL_INFO)
5404 			<< "Exit NNShapeRecognizer::Adapt()"<<endl;
5405 
5406 	return SUCCESS;
5407 }
5408 
5409 /**********************************************************************************
5410 * AUTHOR		: Tarun Madan
5411 * DATE			: 8-Oct-2007
5412 * NAME			: deleteAdaptInstance
5413 * DESCRIPTION	: delete AdaptInstance
5414 * ARGUMENTS		:
5415 * RETURNS		: None
5416 * NOTES			:
5417 * CHANGE HISTROY
5418 * Author			Date				Description
5419 *************************************************************************************/
deleteAdaptInstance()5420 int NNShapeRecognizer::deleteAdaptInstance()
5421 {
5422 	//Implemented as deleteAdaptInstance is called by ~NNShapeRecognizer
5423 	//and adaptObj object is not available in NN.cpp
5424 
5425 	LTKAdapt *adaptInstance = LTKAdapt::getInstance(this);
5426 	if(adaptInstance)
5427 	{
5428 		adaptInstance->deleteInstance();
5429 	}
5430 
5431 	return SUCCESS;
5432 }
5433