1 #include "linearClassifierThread.h"
5 linearClassifierThread::linearClassifierThread(yarp::os::ResourceFinder &rf, Port* commPort)
7 this->commandPort=commPort;
8 currentState=STATE_DONOTHING;
10 this->currPath = rf.getHomeContextPath().c_str();
12 string moduleName = rf.check(
"name",Value(
"linearClassifier"),
"module name (string)").asString().c_str();
13 this->inputFeatures =
"/";
14 this->inputFeatures += moduleName;
15 this->inputFeatures += rf.check(
"InputPortFeatures",Value(
"/features:i"),
"Input image port (string)").asString().c_str();
17 this->outputPortName =
"/";
18 this->outputPortName += moduleName;
19 this->outputPortName += rf.check(
"OutputPortClassification",Value(
"/classification:o"),
"Input image port (string)").asString().c_str();
21 this->outputScorePortName =
"/";
22 this->outputScorePortName += moduleName;
23 this->outputScorePortName += rf.check(
"OutputPortScores",Value(
"/scores:o"),
"Input image port (string)").asString().c_str();
25 this->bufferSize = rf.check(
"BufferSize",Value(15),
"Buffer Size").asInt32();
26 this->CSVM = rf.check(
"CSVM",Value(1.0),
"CSVM").asFloat64();
27 this->useWeightedSVM= rf.check(
"WeightedSVM",Value(0),
"WeightedSVM").asInt32();
29 printf(
"WeightedSVM: %d \n",useWeightedSVM);
31 string dbfolder = rf.check(
"databaseFolder",Value(
"database"),
"module name (string)").asString().c_str();
32 dbfolder=
"/"+dbfolder;
33 this->currPath=this->currPath+dbfolder;
36 bool linearClassifierThread::getClassList(Bottle &b)
38 lock_guard<mutex> lg(mtx);
39 for(
int i=0; i<knownObjects.size(); i++)
40 b.addString(knownObjects[i].first.c_str());
44 bool linearClassifierThread::changeName(
const string &old_name,
const string &new_name)
46 lock_guard<mutex> lg(mtx);
49 for (
size_t i=0; i<knownObjects.size(); i++)
51 if (knownObjects[i].first==old_name)
53 else if (knownObjects[i].first==new_name)
60 knownObjects[j].first=new_name;
62 string old_path=currPath+
"/"+old_name;
63 string new_path=currPath+
"/"+new_name;
64 yarp::os::rename(old_path.c_str(),new_path.c_str());
69 void linearClassifierThread::checkKnownObjects()
72 linearClassifiers.clear();
74 if(yarp::os::stat(currPath.c_str()))
76 createFullPath(currPath.c_str());
81 getdir(currPath,files);
83 for (
int i=0; i<files.size(); i++)
85 if(!files[i].compare(
".") || !files[i].compare(
"..") || !files[i].compare(
"svmmodel"))
87 string objPath=currPath+
"/"+files[i];
89 string svmPath=objPath+
"/svmmodel";
90 if(!yarp::os::stat(svmPath.c_str()))
92 SVMLinear model(files[i]);
97 vector<string> featuresFile;
98 vector<string> tmpFiles;
99 getdir(objPath,featuresFile);
101 for (
int j=0; j< featuresFile.size(); j++)
103 if(!featuresFile[j].compare(
".") || !featuresFile[j].compare(
".."))
106 string tmp=objPath+
"/"+featuresFile[j];
107 tmpFiles.push_back(tmp);
110 pair<string, vector<string> > obj(files[i],tmpFiles);
111 knownObjects.push_back(obj);
115 bool linearClassifierThread::threadInit()
117 if (!featuresPort.open(inputFeatures.c_str())) {
118 cout <<
": unable to open port " << inputFeatures << endl;
122 if (!outputPort.open(outputPortName.c_str())) {
123 cout <<
": unable to open port " << outputPortName << endl;
127 if (!scorePort.open(outputScorePortName.c_str())) {
128 cout <<
": unable to open port " << outputScorePortName << endl;
132 trainClassifiersHelper();
136 void linearClassifierThread::run()
139 while (!isStopping())
141 Bottle *p=featuresPort.read();
146 lock_guard<mutex> lg(mtx);
148 vector<double> feature;
149 feature.resize(p->size());
151 for (
int i=0; i<p->size(); i++)
152 feature[i]=p->get(i).asFloat64();
154 if(currentState==STATE_DONOTHING)
157 if(currentState==STATE_SAVING)
159 for (
int i=0; i<feature.size(); i++)
160 objFeatures << feature[i] <<
" ";
164 if(currentState==STATE_RECOGNIZING)
166 if(linearClassifiers.size()==0)
171 double minValue=1000;
173 for(
int i =0; i<linearClassifiers.size(); i++)
175 double value=linearClassifiers[i].predictModel(feature);
183 bufferScores[current%bufferSize][i]=(value);
184 countBuffer[current%bufferSize][i]=0;
187 countBuffer[current%bufferSize][idWin]=1;
189 vector<double> avgScores(linearClassifiers.size(),0.0);
190 vector<double> bufferVotes(linearClassifiers.size(),0.0);
192 for(
int i =0; i<bufferSize; i++)
194 for(
int k =0; k<linearClassifiers.size(); k++)
196 avgScores[k]=avgScores[k]+bufferScores[i][k];
197 bufferVotes[k]=bufferVotes[k]+countBuffer[i][k];
201 double maxValue=-100;
206 for(
int i =0; i<linearClassifiers.size(); i++)
208 avgScores[i]=avgScores[i]/bufferSize;
209 if(avgScores[i]>maxValue)
211 maxValue=avgScores[i];
215 if(bufferVotes[i]>maxVote)
217 maxVote=bufferVotes[i];
222 string winnerClass=knownObjects[indexClass].first;
223 string winnerVote=knownObjects[indexMaxVote].first;
225 if(bufferVotes[indexMaxVote]/bufferSize<0.75)
228 if(outputPort.getOutputCount()>0)
230 Bottle &b=outputPort.prepare();
232 b.addString(winnerClass.c_str());
236 if(scorePort.getOutputCount()>0)
239 for(
int i =0; i<linearClassifiers.size(); i++)
241 Bottle &b=allScores.addList();
242 b.addString(knownObjects[i].first.c_str());
243 b.addFloat64(bufferScores[current%bufferSize][i]);
246 scorePort.write(allScores);
254 void linearClassifierThread::threadRelease()
256 if(linearClassifiers.size()>0)
257 for (
int i=0; i<linearClassifiers.size(); i++)
258 linearClassifiers[i].freeModel();
260 this->commandPort->close();
261 this->featuresPort.close();
262 this->outputPort.close();
263 this->scorePort.close();
266 void linearClassifierThread::onStop()
268 this->commandPort->interrupt();
269 this->featuresPort.interrupt();
270 this->outputPort.interrupt();
271 this->scorePort.interrupt();
274 void linearClassifierThread::prepareObjPath(
const string &objName)
276 lock_guard<mutex> lg(mtx);
279 pathObj=currPath+
"/"+objName;
280 if(yarp::os::stat(pathObj.c_str()))
282 createFullPath(pathObj.c_str());
283 pathObj=pathObj+
"/1.txt";
290 for (
int i=1; proceed; i++)
292 sprintf(tmpPath,
"%s/%d.txt",pathObj.c_str(),i);
293 proceed=!yarp::os::stat(tmpPath);
294 sprintf(tmpPath,
"%s/%d.txt",pathObj.c_str(),i);
300 objFeatures.open(pathObj.c_str(),fstream::out | fstream::out);
301 currentState=STATE_SAVING;
304 void linearClassifierThread::createFullPath(
const char * path)
306 if (yarp::os::stat(path))
308 string strPath=string(path);
309 size_t found=strPath.find_last_of(
"/");
311 while (strPath[found]==
'/')
314 createFullPath(strPath.substr(0,found+1).c_str());
315 yarp::os::mkdir(strPath.c_str());
319 void linearClassifierThread::stopAllHelper()
321 currentState=STATE_DONOTHING;
322 if(objFeatures.is_open())
326 void linearClassifierThread::stopAll()
328 lock_guard<mutex> lg(mtx);
332 int linearClassifierThread::getdir(
const string &dir, vector<string> &files)
336 if((dp = opendir(dir.c_str())) == NULL) {
337 cout <<
"Error opening " << dir << endl;
341 while ((dirp = readdir(dp)) != NULL) {
342 files.push_back(
string(dirp->d_name));
348 bool linearClassifierThread::loadFeatures()
351 if(this->knownObjects.size()==0)
355 Features.resize(knownObjects.size());
356 datasetSizes.clear();
357 SVMLinear svmmodel(knownObjects[0].first);
359 for (
int i=0; i<knownObjects.size(); i++)
361 vector<string> obj=knownObjects[i].second;
363 for (
int k=0; k< obj.size(); k++)
365 vector<vector<double> > tmpF=svmmodel.readFeatures(obj[k]);
367 for (
int t =0; t<tmpF.size(); t++)
368 Features[i].push_back(tmpF[t]);
373 this->datasetSizes.push_back(cnt);
379 bool linearClassifierThread::trainClassifiersHelper()
383 if(linearClassifiers.size()>0)
384 for (
int i=0; i<linearClassifiers.size(); i++)
385 linearClassifiers[i].freeModel();
387 cout <<
"load features" << endl;
389 if(this->datasetSizes.size()==0)
392 cout <<
"features loaded" << endl;
394 linearClassifiers.clear();
398 for (
int i=0; i<knownObjects.size(); i++)
402 string name=knownObjects[i].first;
403 SVMLinear svmmodel(name);
404 vector<vector<double> > orderedF;
405 vector<double> orderedLabels;
406 for (
int k=0; k<knownObjects.size(); k++)
408 for(
int j=0; j<Features[k].size(); j++)
409 if(knownObjects[i].first==knownObjects[k].first)
411 orderedF.push_back(Features[k][j]);
412 orderedLabels.push_back(1.0);
417 for (
int k=0; k<knownObjects.size(); k++)
419 for(
int j=0; j<Features[k].size(); j++)
420 if(knownObjects[i].first!=knownObjects[k].first)
422 orderedF.push_back(Features[k][j]);
423 orderedLabels.push_back(-1.0);
428 printf(
"nClass: %d nPositive: %d nNegative: %d\n",nClass,nPositive,nNegative);
431 param=svmmodel.initialiseParam(L2R_L2LOSS_SVC,CSVM,0.0,nClass,nPositive,nNegative);
433 param=svmmodel.initialiseParam(L2R_L2LOSS_SVC_DUAL,CSVM);
435 svmmodel.trainModel(orderedF,orderedLabels,param);
437 linearClassifiers.push_back(svmmodel);
442 string tmpModelPath=currPath+
"/"+knownObjects[i].first+
"/svmmodel";
446 cout <<
"trained" << endl;
451 bool linearClassifierThread::trainClassifiers()
453 lock_guard<mutex> lg(mtx);
454 return trainClassifiersHelper();
457 bool linearClassifierThread::startRecognition()
459 lock_guard<mutex> lg(mtx);
462 if(this->linearClassifiers.size()==0)
465 currentState=STATE_RECOGNIZING;
467 this->countBuffer.resize(bufferSize);
468 this->bufferScores.resize(bufferSize);
469 for (
int i=0; i<bufferSize; i++)
471 bufferScores[i].resize(linearClassifiers.size());
472 countBuffer[i].resize(linearClassifiers.size());
478 bool linearClassifierThread::forgetClassHelper(
const string &className,
const bool retrain)
480 string classPath=currPath+
"/"+className;
481 if(yarp::os::stat(classPath.c_str()))
484 vector<string> files;
485 getdir(classPath,files);
487 for (
int i=0; i< files.size(); i++)
489 if(!files[i].compare(
".") || !files[i].compare(
".."))
492 string feature=classPath+
"/"+files[i];
493 remove(feature.c_str());
496 bool res=(yarp::os::rmdir(classPath.c_str())==0);
498 trainClassifiersHelper();
503 bool linearClassifierThread::forgetClass(
const string &className,
const bool retrain)
505 lock_guard<mutex> lg(mtx);
506 return forgetClassHelper(className,retrain);
509 bool linearClassifierThread::forgetAll()
511 lock_guard<mutex> lg(mtx);
514 for (
int i=0; i<knownObjects.size(); i++)
515 forgetClassHelper(knownObjects[i].first,
false);
517 trainClassifiersHelper();