29 #include <yarp/os/Network.h>
30 #include <yarp/os/RFModule.h>
31 #include <yarp/os/Time.h>
32 #include <yarp/os/BufferedPort.h>
33 #include <yarp/os/RpcClient.h>
34 #include <yarp/os/PortReport.h>
35 #include <yarp/os/Stamp.h>
37 #include <yarp/sig/Vector.h>
38 #include <yarp/sig/Image.h>
40 #include <yarp/cv/Cv.h>
42 #include <yarp/math/Math.h>
44 #include "CaffeFeatExtractor.hpp"
48 using namespace yarp::os;
49 using namespace yarp::sig;
50 using namespace yarp::cv;
51 using namespace yarp::math;
53 #define CMD_HELP yarp::os::createVocab32('h','e','l','p')
54 #define DUMP_CODE yarp::os::createVocab32('d','u','m','p')
55 #define DUMP_STOP yarp::os::createVocab32('s','t','o','p')
57 class CaffeCoderPort:
public BufferedPort<Image>
83 list<double> time_measurements_prep;
84 list<double> time_measurements_net;
89 CaffeFeatExtractor<float> *caffe_extractor;
91 void onRead(Image &img)
94 if (Time::now() - last_read < rate)
97 lock_guard<mutex> lg(mtx);
100 if (img.width()>0 && img.height()>0)
103 ImageOf<PixelRgb> tmp_img;
105 matImg = toCvMat(tmp_img);
109 std::vector<float> codingVecFloat;
111 if (!caffe_extractor->extract_singleFeat_1D(matImg, codingVecFloat, times))
113 std::cout <<
"CaffeFeatExtractor::extract_singleFeat_1D(): failed..." << std::endl;
116 std::vector<double> codingVec(codingVecFloat.begin(), codingVecFloat.end());
118 if (caffe_extractor->timing)
120 time_measurements_prep.push_back(times[0]);
121 time_measurements_net.push_back(times[1]);
123 while (time_measurements_prep.size()>time_avg_window)
125 time_measurements_prep.pop_front();
126 time_measurements_net.pop_front();
129 double prep_sum = std::accumulate(time_measurements_prep.begin(), time_measurements_prep.end(), 0.0);
130 double prep_mean = prep_sum / time_measurements_prep.size();
131 double prep_sq_sum = std::inner_product(time_measurements_prep.begin(), time_measurements_prep.end(), time_measurements_prep.begin(), 0.0);
132 double prep_stdev = std::sqrt(prep_sq_sum / time_measurements_prep.size() - prep_mean * prep_mean);
134 double net_sum = std::accumulate(time_measurements_net.begin(), time_measurements_net.end(), 0.0);
135 double net_mean = net_sum / time_measurements_net.size();
136 double net_sq_sum = std::inner_product(time_measurements_net.begin(), time_measurements_net.end(), time_measurements_net.begin(), 0.0);
137 double net_stdev = std::sqrt(net_sq_sum / time_measurements_net.size() - net_mean * net_mean);
139 std::cout <<
"PREP: " << prep_mean <<
" - " << prep_stdev << endl;
140 std::cout <<
"NET: " << net_mean <<
" - " << net_stdev << endl;
142 std::cout <<
"time_avg_window = " << time_measurements_prep.size() << endl;
148 fwrite (&codingVec[0],
sizeof(
double), codingVec.size(), fout_code);
152 this->getEnvelope(stamp);
154 if(port_out_code.getOutputCount())
156 port_out_code.setEnvelope(stamp);
157 Vector codingYarpVec(codingVec.size(), &codingVec[0]);
158 port_out_code.write(codingYarpVec);
161 if(port_out_img.getOutputCount())
163 port_out_img.write(img);
170 CaffeCoderPort(ResourceFinder &_rf) :BufferedPort<Image>(),rf(_rf)
173 contextPath = rf.getHomeContextPath().c_str();
178 string caffemodel_file = rf.check(
"caffemodel_file", Value(
"bvlc_googlenet.caffemodel")).asString().c_str();
179 cout <<
"Setting .caffemodel file to " << caffemodel_file << endl;
182 string prototxt_file = rf.check(
"prototxt_file", Value(contextPath +
"/bvlc_googlenet_val_cutpool5.prototxt")).asString().c_str();
183 cout <<
"Setting .prototxt file to " << prototxt_file << endl;
186 string blob_name = rf.check(
"blob_name", Value(
"pool5/7x7_s1")).asString().c_str();
187 cout <<
"Setting blob_name to " << blob_name << endl;
189 bool timing = rf.check(
"timing");
192 time_avg_window = rf.check(
"timing",Value(
"1000")).asInt32();
196 time_avg_window = -1;
204 compute_mode = rf.check(
"compute_mode", Value(
"GPU")).asString();
205 device_id = rf.check(
"device_id", Value(0)).asInt32();
207 compute_mode =
"CPU";
211 int resizeWidth = rf.check(
"resizeWidth", Value(256)).asFloat64();
212 int resizeHeight = rf.check(
"resizeHeight", Value(256)).asFloat64();
214 caffe_extractor = NULL;
215 caffe_extractor =
new CaffeFeatExtractor<float>(caffemodel_file,
216 prototxt_file, resizeWidth, resizeHeight,
223 string name = rf.find(
"name").asString().c_str();
225 port_out_img.open((
"/"+name+
"/img:o").c_str());
226 port_out_code.open((
"/"+name+
"/code:o").c_str());
228 BufferedPort<Image>::useCallback();
230 rate = rf.check(
"rate",Value(0.0)).asFloat64();
233 dump_code = rf.check(
"dump_code");
236 string code_path = rf.check(
"dump_code",Value(
"codes.bin")).asString().c_str();
237 code_path = contextPath +
"/" + code_path;
238 string code_write_mode = rf.check(
"append")?
"wb+":
"wb";
240 fout_code = fopen(code_path.c_str(),code_write_mode.c_str());
246 lock_guard<mutex> lg(mtx);
248 port_out_code.interrupt();
249 port_out_img.interrupt();
251 BufferedPort<Image>::interrupt();
256 lock_guard<mutex> lg(mtx);
258 port_out_code.resume();
259 port_out_img.resume();
261 BufferedPort<Image>::resume();
266 lock_guard<mutex> lg(mtx);
273 port_out_code.close();
274 port_out_img.close();
276 BufferedPort<Image>::close();
279 bool execReq(
const Bottle &command, Bottle &reply)
281 switch(command.get(0).asVocab32())
286 reply.add(Value::makeVocab32(
"many"));
287 reply.addString(
"[dump] [path-to-file] [a] to start dumping the codes in the context directory. Use 'a' for appending.");
288 reply.addString(
"[stop] to stop dumping.");
294 lock_guard<mutex> lg(mtx);
298 string code_write_mode;
300 if (command.size()==1)
302 code_path = contextPath +
"/codes.bin";
303 code_write_mode=
"wb";
305 else if (command.size()==2)
307 if (strcmp(command.get(1).asString().c_str(),
"a")==0)
309 code_write_mode=
"wb+";
310 code_path = contextPath +
"/codes.bin";
313 code_write_mode=
"wb";
314 code_path = command.get(1).asString().c_str();
316 }
else if (command.size()==3)
318 code_write_mode=
"wb+";
319 code_path = command.get(2).asString().c_str();
322 fout_code = fopen(code_path.c_str(),code_write_mode.c_str());
323 reply.addString(
"Start dumping codes...");
330 lock_guard<mutex> lg(mtx);
334 reply.addString(
"Stopped code dump.");
346 class CaffeCoderModule:
public RFModule
349 CaffeCoderPort *caffePort;
359 bool configure(ResourceFinder &rf)
361 string name = rf.find(
"name").asString().c_str();
363 caffePort =
new CaffeCoderPort(rf);
365 caffePort->open((
"/"+name+
"/img:i").c_str());
367 rpcPort.open((
"/"+name+
"/rpc").c_str());
373 bool interruptModule()
376 caffePort->interrupt();
396 bool respond(
const Bottle &command, Bottle &reply)
398 if (caffePort->execReq(command,reply))
401 return RFModule::respond(command,reply);
404 double getPeriod() {
return 1.0; }
415 int main(
int argc,
char *argv[])
418 if (!yarp.checkNetwork())
422 rf.setDefaultContext(
"himrep");
423 rf.setDefaultConfigFile(
"caffeCoder.ini");
424 rf.configure(argc,argv);
425 rf.setDefault(
"name",
"caffeCoder");
427 CaffeCoderModule mod;
428 return mod.runModule(rf);