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