segmentation
All Data Structures Namespaces Files Functions Variables Modules Pages
dispBlobberModule.cpp
1 /*
2  * Copyright (C) 2015 iCub Facility - Istituto Italiano di Tecnologia
3  * Authors: Tanis Mar, Giulia Pasquale
4  * email: tanis.mar@iit.it, giulia.pasquale@iit.it
5  * Permission is granted to copy, distribute, and/or modify this program
6  * under the terms of the GNU General Public License, version 2 or any
7  * later version published by the Free Software Foundation.
8  *
9  * A copy of the license can be found at
10  * http://www.robotcub.org/icub/license/gpl.txt
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15  * Public License for more details
16  */
17 
18 #include <yarp/cv/Cv.h>
19 #include "dispBlobberModule.hpp"
20 
21 using namespace cv;
22 using namespace std;
23 using namespace yarp::os;
24 using namespace yarp::sig;
25 using namespace yarp::cv;
26 
27 
28 bool DispBlobberModule::configure(yarp::os::ResourceFinder &rf)
29 {
30  moduleName = rf.check("name", Value("dispBlobber"), "module name (string)").asString();
31 
32  setName(moduleName.c_str());
33 
34  handlerPortName = "/";
35  handlerPortName += getName();
36  handlerPortName += "/rpc:i";
37 
38  if (!handlerPort.open(handlerPortName)) {
39  fprintf(stdout, "%s : Unable to open RPC port %s\n", getName().c_str(), handlerPortName.c_str());
40  return false;
41  }
42  attach(handlerPort);
43 
44  blobPort = new DispBlobberPort( moduleName, rf );
45 
46  blobPort->open();
47 
48  closing = false;
49 
50  return true ;
51 }
52 
53 bool DispBlobberModule::interruptModule()
54 {
55  closing = true;
56 
57  handlerPort.interrupt();
58 
59  blobPort->interrupt();
60 
61  return true;
62 }
63 
64 bool DispBlobberModule::close()
65 {
66  handlerPort.close();
67 
68  fprintf(stdout, "starting the shutdown procedure\n");
69 
70  blobPort->close();
71 
72  fprintf(stdout, "deleting thread\n");
73  delete blobPort;
74  fprintf(stdout, "done deleting thread\n");
75 
76  return true;
77 }
78 
79 bool DispBlobberModule::updateModule()
80 {
81  return !closing;
82 }
83 
84 bool DispBlobberModule::respond(const Bottle &command, Bottle &reply)
85 {
86 
87  reply.clear();
88 
89  /* Get command string */
90  string receivedCmd = command.get(0).asString();
91 
92  int responseCode; // contain Vocab-encoded response
93 
94  if (receivedCmd == "margin")
95  {
96  bool ok = blobPort->setMargin(command.get(1).asInt32());
97  if (ok)
98  responseCode = Vocab32::encode("ack");
99  else
100  {
101  fprintf(stdout,"Margin for ROI cannot be set. \n");
102  responseCode = Vocab32::encode("nack");
103  }
104  reply.addVocab32(responseCode);
105  return true;
106  }
107  if (receivedCmd == "thresh")
108  {
109  bool ok = blobPort->setThresh(command.get(1).asInt32());
110  if (ok)
111  responseCode = Vocab32::encode("ack");
112  else {
113  fprintf(stdout,"Threshold cannot be set. \n");
114  responseCode = Vocab32::encode("nack");
115  }
116  reply.addVocab32(responseCode);
117  return true;
118  }
119  else if (receivedCmd == "help")
120  {
121  reply.addVocab32("many");
122 
123  responseCode = Vocab32::encode("ack");
124 
125  reply.addString("Available commands are:");
126  reply.addString("margin (int) - sets the margin (in pixels) that the ROI keeps around the closest blob.");
127  reply.addString("thresh (int) - sets lower luminosity limit (0-255) that is considered. Objects with luminosity lower than the boundary wont be considered.");
128  reply.addString("help - produces this help.");
129  reply.addString("quit - closes the module.");
130 
131  reply.addVocab32(responseCode);
132  return true;
133  }
134  else if (receivedCmd == "quit")
135  {
136  responseCode = Vocab32::encode("ack");
137 
138  reply.addVocab32(responseCode);
139 
140  closing = true;
141  return true;
142  }
143 
144  reply.addString("Invalid command, type [help] for a list of accepted commands.");
145 
146  return true;
147 }
148 
149 double DispBlobberModule::getPeriod()
150 {
151  return 0.1;
152 }
153 
154 DispBlobberPort::DispBlobberPort( const string &_moduleName, ResourceFinder &rf)
155 {
156 
157  this->moduleName = _moduleName;
158 
159  moduleRF = &rf;
160 
161  fprintf(stdout,"Parsing parameters...\n");
162 
163  int imH = moduleRF->check("imH", Value(240)).asInt32();
164  int imW = moduleRF->check("imW", Value(320)).asInt32();
165 
166  int bufferSize = moduleRF->check("bufferSize", Value(1)).asInt32();
167 
168  int margin = moduleRF->check("margin", Value(20)).asInt32();
169  cropSize = 0;
170 
171  if (rf.check("cropSize"))
172  {
173  Value &vCropSize=rf.find("cropSize");
174 
175  if (!vCropSize.isString())
176  {
177  cropSize = vCropSize.asInt32();
178  margin = 0; // not used in this case
179  }
180  }
181 
182  // threshold of intensity of the image under which info is ignored
183  int backgroundThresh = moduleRF->check("backgroundThresh", Value(30)).asInt32();
184 
185  int minBlobSize = moduleRF->check("minBlobSize", Value(300)).asInt32();
186  int maxBlobSize = moduleRF->check("maxBlobSize", Value(2000)).asInt32();
187 
188  int gaussSize = moduleRF->check("gaussSize", Value(5)).asInt32();
189 
190  int imageThreshRatioLow = moduleRF->check("imageThreshRatioLow", Value(10)).asInt32();
191  int imageThreshRatioHigh = moduleRF->check("imageThreshRatioHigh", Value(20)).asInt32();
192 
193  blobExtractor = NULL;
194 
195  blobExtractor = new dispBlobber(imH, imW, bufferSize,
196  margin,
197  backgroundThresh,
198  minBlobSize, maxBlobSize, gaussSize,
199  imageThreshRatioLow, imageThreshRatioHigh);
200 }
201 
202 bool DispBlobberPort::open()
203 {
204 
205  this->useCallback();
206 
207  fprintf(stdout,"Opening ports...\n");
208 
209  /* Inputs */
210 
211  imgInPortName = "/" + moduleName + "/img:i";
212  BufferedPort<ImageOf<PixelBgr> >::open( imgInPortName );
213 
214  /* Outputs */
215 
216  blobsOutPortName = "/" + moduleName + "/blobs/left:o";
217  blobsOutPort.open(blobsOutPortName);
218 
219  blobsOutPortRightName = "/" + moduleName + "/blobs/right:o";
220  blobsOutPortRight.open(blobsOutPortRightName);
221 
222  points3dOutPortName = "/" + moduleName + "/points3d:o";;
223  points3dOutPort.open(points3dOutPortName);
224 
225  roiOutPortName = "/" + moduleName + "/roi/left:o";
226  roiOutPort.open(roiOutPortName);
227 
228  roiOutPortRightName = "/" + moduleName + "/roi/right:o";
229  roiOutPortRight.open(roiOutPortRightName);
230 
231  optOutPortName = "/" + moduleName + "/opt:o";
232  optOutPort.open(optOutPortName);
233 
234  cropOutPortName = "/" + moduleName + "/crop:o";
235  cropOutPort.open(cropOutPortName);
236 
237  sfmRpcPort.open("/" + moduleName + "/sfm/rpc");
238 
239  return true;
240 }
241 
242 void DispBlobberPort::close()
243 {
244  fprintf(stdout,"Closing ports...\n");
245 
246  blobsOutPort.close();
247  blobsOutPortRight.close();
248  points3dOutPort.close();
249 
250  roiOutPort.close();
251  roiOutPortRight.close();
252 
253  optOutPort.close();
254  cropOutPort.close();
255 
256  sfmRpcPort.close();
257 
258  BufferedPort<ImageOf<PixelBgr> >::close();
259 
260  fprintf(stdout,"Finished closing ports...\n");
261 }
262 
263 void DispBlobberPort::interrupt()
264 {
265 
266  fprintf(stdout,"Attempting to interrupt ports...\n");
267 
268  blobsOutPort.interrupt();
269  blobsOutPortRight.interrupt();
270  points3dOutPort.interrupt();
271 
272  roiOutPort.interrupt();
273  roiOutPortRight.interrupt();
274 
275  optOutPort.interrupt();
276  cropOutPort.interrupt();
277 
278  sfmRpcPort.interrupt();
279 
280  BufferedPort<ImageOf<PixelBgr> >::interrupt();
281 
282  fprintf(stdout,"Finished interrupting ports...\n");
283 }
284 
285 bool DispBlobberPort::setThresh(int low)
286 {
287  return blobExtractor->setThresh(low);
288 
289 }
290 
291 bool DispBlobberPort::setMargin(int mrg)
292 {
293  return blobExtractor->setMargin(mrg);
294 }
295 
296 void DispBlobberPort::onRead(ImageOf<PixelBgr> &input)
297 {
298  lock_guard<mutex> lg(mtx);
299 
300  /* Get the envelope from the input image */
301 
302  Stamp stamp;
303  BufferedPort<ImageOf<PixelBgr> >::getEnvelope(stamp);
304 
305  /* Prepare output data structures */
306 
307  std::vector<int> centroid;
308  std::vector<int> roi;
309  cv::Mat blobMat;
310 
311  /* Prepare the buffer, call the extractor, clear the buffer */
312 
313  cv::Mat inputMat=toCvMat(input);
314  imagesMatBuffer.push_back(inputMat);
315 
316  double blobSize = blobExtractor->extractBlob(imagesMatBuffer, roi, centroid, blobMat);
317 
318  if (blobSize>0)
319  {
320 
321  if (optOutPort.getOutputCount()>0)
322  {
323  yarp::sig::ImageOf<yarp::sig::PixelMono> &blobImage = optOutPort.prepare();
324  blobImage.resize(blobMat.cols, blobMat.rows);
325 
326  cv::Mat blobImageMat=toCvMat(blobImage);
327  blobMat.copyTo(blobImageMat);
328 
329  optOutPort.setEnvelope(stamp);
330  optOutPort.write();
331  }
332 
333  int x = centroid[0];
334  int y = centroid[1];
335 
336  int dx = ( (cropSize>0) ? cropSize : (roi[2]-roi[0]) );
337  int dy = ( (cropSize>0) ? cropSize : (roi[3]-roi[1]) );
338 
339  int dx2 = dx>>1;
340  int dy2 = dy>>1;
341 
342  int tlx = std::max(x-dx2,0);
343  int tly = std::max(y-dy2,0);
344  int brx = std::min(x+dx2,blobMat.cols-1);
345  int bry = std::min(y+dy2,blobMat.rows-1);
346 
347  if (cropOutPort.getOutputCount()>0)
348  {
349  cv::Rect roiRegion = cv::Rect(cv::Point( tlx, tly ), cv::Point( brx, bry ));
350 
351  yarp::sig::ImageOf<yarp::sig::PixelBgr> &cropImage = cropOutPort.prepare();
352  cropImage.resize(roiRegion.width, roiRegion.height);
353 
354  cv::Mat cropImageMat=toCvMat(cropImage);
355  imagesMatBuffer.back()(roiRegion).copyTo(cropImageMat);
356 
357  cropOutPort.setEnvelope(stamp);
358  cropOutPort.write();
359  }
360 
361  if (roiOutPort.getOutputCount()>0)
362  {
363  Bottle roisBottle;
364 
365  Bottle &roiBottle = roisBottle.addList();
366  roiBottle.addInt32(tlx);
367  roiBottle.addInt32(tly);
368  roiBottle.addInt32(brx);
369  roiBottle.addInt32(bry);
370 
371  roiOutPort.prepare() = roisBottle;
372 
373  roiOutPort.setEnvelope(stamp);
374  roiOutPort.write();
375  }
376 
377  if (blobsOutPort.getOutputCount()>0)
378  {
379  Bottle blobsBottle;
380 
381  Bottle &blobBottle = blobsBottle.addList();
382  blobBottle.addInt32(centroid[0]);
383  blobBottle.addInt32(centroid[1]);
384  blobBottle.addInt32((int)(blobSize+0.5f));
385 
386  blobsOutPort.prepare() = blobsBottle;
387 
388  blobsOutPort.setEnvelope(stamp);
389  blobsOutPort.write();
390  }
391 
392  if (roiOutPortRight.getOutputCount()>0)
393  {
394  Bottle cmd_sfm, reply_sfm;
395 
396  cmd_sfm.addInt32(tlx);
397  cmd_sfm.addInt32(tly);
398  sfmRpcPort.write(cmd_sfm,reply_sfm);
399 
400  Bottle roisBottle;
401  Bottle &roiBottle = roisBottle.addList();
402 
403  if (reply_sfm.size()>0)
404  {
405  double tlX = reply_sfm.get(0).asFloat64();
406  double tlY = reply_sfm.get(1).asFloat64();
407  double tlZ = reply_sfm.get(2).asFloat64();
408 
409  if (!(tlX==0 && tlY==0 && tlZ==0))
410  {
411  int tlur = reply_sfm.get(3).asInt32();
412  int tlvr = reply_sfm.get(4).asInt32();
413 
414  roiBottle.addInt32(tlur);
415  roiBottle.addInt32(tlvr);
416  }
417  }
418 
419  cmd_sfm.clear();
420  reply_sfm.clear();
421 
422  cmd_sfm.addInt32(brx);
423  cmd_sfm.addInt32(bry);
424  sfmRpcPort.write(cmd_sfm,reply_sfm);
425 
426  if (reply_sfm.size()>0)
427  {
428  double brX = reply_sfm.get(0).asFloat64();
429  double brY = reply_sfm.get(1).asFloat64();
430  double brZ = reply_sfm.get(2).asFloat64();
431 
432  if (!(brX==0 && brY==0 && brZ==0))
433  {
434  int brur = reply_sfm.get(3).asInt32();
435  int brvr = reply_sfm.get(4).asInt32();
436 
437  roiBottle.addInt32(brur);
438  roiBottle.addInt32(brvr);
439  }
440  }
441 
442  if (roiBottle.size()>0)
443  {
444  roiOutPortRight.prepare() = roisBottle;
445  roiOutPortRight.setEnvelope(stamp);
446  roiOutPortRight.write();
447  }
448 
449  }
450 
451  if (blobsOutPortRight.getOutputCount()>0 || points3dOutPort.getOutputCount()>0)
452  {
453  Bottle cmd_sfm, reply_sfm;
454 
455  cmd_sfm.addInt32(centroid[0]);
456  cmd_sfm.addInt32(centroid[1]);
457  sfmRpcPort.write(cmd_sfm,reply_sfm);
458 
459  if (reply_sfm.size()>0)
460  {
461  double X = reply_sfm.get(0).asFloat64();
462  double Y = reply_sfm.get(1).asFloat64();
463  double Z = reply_sfm.get(2).asFloat64();
464 
465  if (points3dOutPort.getOutputCount()>0)
466  {
467  Bottle points3dBottle;
468  Bottle &point3dBottle = points3dBottle.addList();
469 
470  point3dBottle.addFloat64(X);
471  point3dBottle.addFloat64(Y);
472  point3dBottle.addFloat64(Z);
473 
474  points3dOutPort.prepare() = points3dBottle;
475  points3dOutPort.setEnvelope(stamp);
476  points3dOutPort.write();
477  }
478 
479  if (blobsOutPort.getOutputCount()>0)
480  {
481  if (!(X==0.0 && Y==0.0 && Z==0.0))
482  {
483  int ur = reply_sfm.get(3).asInt32();
484  int vr = reply_sfm.get(4).asInt32();
485 
486  Bottle blobsBottle;
487  Bottle &blobBottle = blobsBottle.addList();
488 
489  blobBottle.addInt32(ur);
490  blobBottle.addInt32(vr);
491 
492  blobsOutPortRight.prepare() = blobsBottle;
493  blobsOutPortRight.setEnvelope(stamp);
494  blobsOutPortRight.write();
495  }
496  }
497  }
498  }
499 
500  }
501 
502  imagesMatBuffer.erase(imagesMatBuffer.begin());
503 }
504