91 #include <yarp/os/Network.h>
92 #include <yarp/os/RFModule.h>
93 #include <yarp/os/Time.h>
94 #include <yarp/os/BufferedPort.h>
95 #include <yarp/os/RpcClient.h>
96 #include <yarp/os/PortReport.h>
98 #include <yarp/sig/Vector.h>
99 #include <yarp/sig/Image.h>
101 #include <yarp/cv/Cv.h>
103 #include <yarp/math/Math.h>
104 #include <yarp/math/Rand.h>
106 #include <opencv2/opencv.hpp>
119 #include "SiftGPU_Extractor.h"
120 #include "DictionaryLearning.h"
123 using namespace yarp;
124 using namespace yarp::os;
125 using namespace yarp::sig;
126 using namespace yarp::cv;
127 using namespace yarp::math;
129 #define CMD_HELP yarp::os::createVocab32('h','e','l','p')
130 #define DUMP_SIFT yarp::os::createVocab32('d','u','m','p')
131 #define DUMP_STOP yarp::os::createVocab32('s','t','o','p')
132 #define LEARN_DICT yarp::os::createVocab32('l','e','a','r')
134 #define CODE_MODE_SC 0
135 #define CODE_MODE_BOW 1
136 #define CODE_MODE_BCE 2
139 class SparseCoderPort:
public BufferedPort<Image>
147 vector<SiftGPU::SiftKeypoint> keypoints;
148 vector<float> descriptors;
153 SiftGPU_Extractor siftGPU_extractor;
158 DictionaryLearning *sparse_coder;
177 virtual void onRead(Image &img)
180 if(Time::now()-last_read<rate)
183 lock_guard<mutex> lg(mtx);
184 if(ipl==NULL || ipl->width!=img.width() || ipl->height!=img.height())
188 cvReleaseImage(&ipl);
190 ipl=cvCreateImage(cvSize(img.width(),img.height()),IPL_DEPTH_8U,1);
191 siftGPU_extractor.setDenseGrid(ipl,grid_step,grid_scale);
194 cv::cvtColor(toCvMat(img),cv::cvarrToMat(ipl),CV_RGB2GRAY);
198 siftGPU_extractor.extractDenseSift(ipl,&keypoints,&descriptors);
200 siftGPU_extractor.extractSift(ipl,&keypoints,&descriptors);
204 for(
int i=0; i<keypoints.size(); i++)
206 for(
int j=0; j<128; j++)
207 fprintf(fout_sift,
"%f ",descriptors[i*128+j]);
208 fprintf(fout_sift,
"\n");
214 vector<Vector> features(keypoints.size());
216 for(
unsigned int i=0; i<keypoints.size(); i++)
218 features[i].resize(128);
219 for(
unsigned int j=0; j<128; j++)
220 features[i][j]=descriptors[i*128+j];
227 sparse_coder->maxPooling(features,coding,keypoints,pyramidLevels,ipl->width, ipl->height);
232 sparse_coder->maxPooling(features,coding,keypoints,pyramidLevels,ipl->width, ipl->height);
237 sparse_coder->avgPooling(features,coding,keypoints,pyramidLevels,ipl->width, ipl->height);
243 if(port_out_code.getOutputCount())
245 port_out_code.write(coding);
247 if(port_out_img.getOutputCount())
249 for(
unsigned int i=0; i<keypoints.size(); i++)
251 int x = cvRound(keypoints[i].x);
252 int y = cvRound(keypoints[i].y);
253 cv::Mat imgMat=toCvMat(img);
254 cv::circle(imgMat,cvPoint(x,y),3,cvScalar(0,0,255),-1);
256 port_out_img.write(img);
263 SparseCoderPort(ResourceFinder &_rf)
264 :BufferedPort<Image>(),rf(_rf)
268 verbose=rf.check(
"verbose");
270 grid_step=rf.check(
"grid_step",Value(8)).asInt32();
271 grid_scale=rf.check(
"grid_scale",Value(1)).asInt32();
273 contextPath=rf.getHomeContextPath().c_str();
274 string dictionary_name=rf.check(
"dictionary_file",Value(
"dictionary_bow.ini")).asString().c_str();
276 string dictionary_path=rf.findFile(dictionary_name);
277 if(dictionary_path==
"")
278 dictionary_path=contextPath+
"/"+dictionary_name;
279 string dictionary_group=rf.check(
"dictionary_group",Value(
"DICTIONARY")).asString().c_str();
281 no_code=rf.check(
"no_code");
282 dump_sift=rf.check(
"dump_sift");
286 string sift_path=rf.check(
"dump_sift",Value(
"sift.txt")).asString().c_str();
287 sift_path=contextPath+
"/"+sift_path;
288 string sift_write_mode=rf.check(
"append")?
"a":
"w";
290 fout_sift=fopen(sift_path.c_str(),sift_write_mode.c_str());
293 rate=rf.check(
"rate",Value(0.0)).asFloat64();
294 dense=rf.check(
"useDense",Value(1)).asInt32();
295 int knn=rf.check(
"KNN",Value(5)).asInt32();
298 pyramidLevels=rf.check(
"PyramidLevels",Value(3)).asInt32();
301 fprintf(stdout,
"Step: %d Scale: %d Pyramid: %d Using Dense SIFT Grid\n",grid_step, grid_scale, pyramidLevels);
303 fprintf(stdout,
"Step: %d Scale: %d Pyramid: %d Using Sparse SIFTs \n",grid_step, grid_scale, pyramidLevels);
305 string code_mode_string=rf.check(
"code_mode",Value(
"SC")).asString().c_str();
308 sparse_coder=
new DictionaryLearning(dictionary_path,dictionary_group,code_mode_string,knn);
313 for(
int i=0; i<code_mode_string.size(); i++)
314 code_mode_string[i] = std::toupper((
unsigned char)code_mode_string[i]);
316 fprintf(stdout,
"%s\n",code_mode_string.c_str());
318 if(code_mode_string==
"SC")
319 code_mode=CODE_MODE_SC;
320 if(code_mode_string==
"BCE")
321 code_mode=CODE_MODE_BCE;
322 if(code_mode_string==
"BOW")
323 code_mode=CODE_MODE_BOW;
325 string name=rf.find(
"name").asString().c_str();
327 port_out_img.open((
"/"+name+
"/img:o").c_str());
328 port_out_code.open((
"/"+name+
"/code:o").c_str());
329 BufferedPort<Image>::useCallback();
332 virtual void interrupt()
334 lock_guard<mutex> lg(mtx);
335 port_out_code.interrupt();
336 port_out_img.interrupt();
337 BufferedPort<Image>::interrupt();
340 virtual void resume()
342 lock_guard<mutex> lg(mtx);
343 port_out_code.resume();
344 port_out_img.resume();
345 BufferedPort<Image>::resume();
350 lock_guard<mutex> lg(mtx);
352 cvReleaseImage(&ipl);
358 if(sparse_coder!=NULL)
361 port_out_code.close();
362 port_out_img.close();
363 BufferedPort<Image>::close();
367 bool execReq(
const Bottle &command, Bottle &reply)
369 switch(command.get(0).asVocab32())
376 reply.addString(
"There's no help in this life. You oughta do everything on your own");
380 reply.add(Value::makeVocab32(
"many"));
381 reply.addString(
"Ok joking.. here the help!");
382 reply.addString(
"[dump] [a] for starting the SIFT dumping in the context directory.. use 'a' for appending");
383 reply.addString(
"[stop] for stopping the SIFT dumping in the context directory.. ");
384 reply.addString(
"[learn] [dictionarySize] [usePCA] [dimPCA] for learning the dictionary from a SIFT file previously dumped..");
391 lock_guard<mutex> lg(mtx);
393 string sift_path=
"sift.txt";
394 sift_path=contextPath+
"/"+sift_path;
396 string sift_write_mode;
397 if(command.size()==1)
400 sift_write_mode=command.get(1).asString().c_str();
402 fout_sift=fopen(sift_path.c_str(),sift_write_mode.c_str());
403 reply.addString(
"Starting to dump SIFTs...");
409 lock_guard<mutex> lg(mtx);
412 reply.addString(
"Stopped SIFT Dump.");
417 lock_guard<mutex> lg(mtx);
420 string sift_path=rf.findFile(
"sift.txt").c_str();
421 string dictionary_path=
"newDictionary.ini";
422 dictionary_path=contextPath+
"/"+dictionary_path;
423 reply.addString(
"Dictionary Learned.");
425 if(command.size()==1)
428 dictSize=command.get(1).asInt32();
430 bool usePCA=command.size()>2;
435 dimPCA=command.get(3).asInt32();
441 sparse_coder->learnDictionary(sift_path, dictSize,usePCA,dimPCA);
442 sparse_coder->saveDictionary(dictionary_path);
454 class SparseCoderModule:
public RFModule
457 SparseCoderPort *scPort;
466 virtual bool configure(ResourceFinder &rf)
468 string name=rf.find(
"name").asString().c_str();
470 scPort=
new SparseCoderPort(rf);
471 scPort->open((
"/"+name+
"/img:i").c_str());
472 rpcPort.open((
"/"+name+
"/rpc").c_str());
493 virtual bool respond(
const Bottle &command, Bottle &reply)
495 if(scPort->execReq(command,reply))
498 return RFModule::respond(command,reply);
501 virtual double getPeriod() {
return 1.0; }
502 virtual bool updateModule()
514 int main(
int argc,
char *argv[])
518 if (!yarp.checkNetwork())
522 rf.setDefaultContext(
"himrep");
523 rf.setDefaultConfigFile(
"sparseCoder.ini");
524 rf.configure(argc,argv);
525 rf.setDefault(
"name",
"sparseCoder");
526 SparseCoderModule mod;
528 return mod.runModule(rf);