segmentation
All Data Structures Namespaces Files Functions Variables Modules Pages
EdisonSegmModule.cpp
1 // -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
2 
3 /*
4  * Copyright (C) 2009 Alexandre Bernardino, Vislab, IST/ISR.
5  * CopyPolicy: Released under the terms of the GNU GPL v2.0.
6  *
7  */
8 extern bool CmCDisplayProgress;
9 #include <string>
10 #include <vector>
11 #include <iostream>
12 
13 #include "EdisonSegmModule.h"
14 
15 #include <edge/BgImage.h>
16 #include <edge/BgEdge.h>
17 #include <edge/BgEdgeList.h>
18 #include <edge/BgEdgeDetect.h>
19 #include <edge/BgDefaults.h>
20 
21 // yarp
22 #include <yarp/os/Network.h>
23 #include <yarp/cv/Cv.h>
24 
25 using namespace std;
26 using namespace yarp::os;
27 using namespace yarp::sig;
28 using namespace yarp::cv;
29 
30 void EdisonSegmModule::setSpeedUpValue(int newSpeedUpValue)
31 {
32  switch(newSpeedUpValue) {
33  case(0): speedup = NO_SPEEDUP; break;
34  case(1): speedup = MED_SPEEDUP; break;
35  case(2): speedup = HIGH_SPEEDUP; break;
36  default: speedup = NO_SPEEDUP;
37  }
38 }
39 
40 EdisonSegmModule::EdisonSegmModule() : _stamp(0,0)
41 {
42  orig_height_ = -1;
43  orig_width_ = -1;
44  height_ = -1;
45  width_ = -1;
46  dim_ = -1; //defaults to color image
47  numEdges_ = -1;
48  numBoundaries_ = -1;
49  inputImage_ = (unsigned char *) NULL;
50  filtImage_ = (unsigned char *) NULL;
51  segmImage_ = (unsigned char *) NULL;
52  gradMap_ = (float *) NULL;
53  confMap_ = (float *) NULL;
54  weightMap_ = (float *) NULL;
55  edges_ = (int *) NULL;
56  boundaries_ = (int *) NULL;
57 
58  //defaults for the parameters - as the ones in the EDISON GUI application
59  sigmaS = 7;
60  sigmaR = 6.5;
61  minRegion = 20;
62  gradWindRad = 2;
63  threshold = 0.3F;
64  mixture = 0.2F;
65  speedup = MED_SPEEDUP;
66 }
67 
68 EdisonSegmModule::~EdisonSegmModule()
69 {
70  if(edges_) delete [] edges_;
71  if(boundaries_) delete [] boundaries_;
72 }
73 
74 
75 bool EdisonSegmModule::configure (yarp::os::ResourceFinder &rf)
76 {
77  if (rf.check("help","if present, display usage message")) {
78  printf("Call with --from configfile.ini\n");
79  return false;
80  }
81 
82  if (rf.check("name"))
83  setName(rf.find("name").asString().c_str());
84  else setName("edisonSeg");
85 
86  //defaults for the parameters - as the ones in the EDISON GUI application
87  height_ = 240;
88  width_ = 320;
89  dim_ = 3;
90  sigmaS = 7;
91  sigmaR = 6.5;
92  minRegion = 20;
93  gradWindRad = 2;
94  threshold = 0.3F;
95  mixture = 0.2F;
96  speedup = MED_SPEEDUP;
97  //override defaults if specified - TODO: range checking
98  if(rf.check("height")) height_ = rf.find("height").asInt32();
99  if(rf.check("width")) width_ = rf.find("width").asInt32();
100  //if(rf.check("dim")) dim_ = rf.find("dim").asInt32(); // not required - should always be 3
101  if(rf.check("sigmaS")) sigmaS = rf.find("sigmaS").asInt32();
102  if(rf.check("sigmaR")) sigmaR = (float)rf.find("sigmaR").asFloat64();
103  if(rf.check("minRegion")) minRegion = rf.find("minRegion").asInt32();
104  if(rf.check("gradWinRad")) gradWindRad = (int)rf.find("gradWinRad").asFloat64();
105  if(rf.check("threshold")) threshold = (float)rf.find("threshold").asFloat64();
106  if(rf.check("mixture")) mixture = (float)rf.find("mixture").asFloat64();
107  if(rf.check("speedup"))
108  {
109  int spdp = rf.find("speedup").asInt32();
110  setSpeedUpValue(spdp);
111  }
112 
113  std::string slash="/";
114  _imgPort.open(slash + getName("/rawImg:i"));
115  _configPort.open(slash + getName("/conf"));
116  _filtPort.open(slash + getName("/filtImg:o"));
117  _labelPort.open(slash +getName("/labeledImg:o"));
118  _viewPort.open(slash +getName("/viewImg:o"));
119  _rawPort.open(slash +getName("/rawImg:o"));
120  _labelViewPort.open(slash +getName("/debugImg:o"));
121  //attach(_configPort, true);
122  attach(_configPort);
123 
124  //read an image to get the dimensions
125  ImageOf<PixelRgb> *yrpImgIn;
126  yrpImgIn = _imgPort.read();
127  if (yrpImgIn == NULL) // this is the case if module is requested to quit while waiting for image
128  return true;
129  orig_height_ = yrpImgIn->height();
130  orig_width_ = yrpImgIn->width();
131 
132  //override internal image dimension if necessary
133  if( width_ > orig_width_ )
134  width_ = orig_width_;
135  if( height_ > orig_height_ )
136  height_ = orig_height_;
137 
138  //allocate memory for image buffers and get the pointers
139 
140  inputImage.resize(width_, height_); inputImage_ = inputImage.getRawImage();
141  inputHsv.resize(width_, height_); inputHsv_ = inputHsv.getRawImage();
142  inputHue.resize(width_, height_); inputHue_ = inputHue.getRawImage();
143  filtImage.resize(width_, height_); filtImage_ = filtImage.getRawImage();
144  segmImage.resize(width_, height_); segmImage_ = segmImage.getRawImage();
145  gradMap.resize(width_, height_); gradMap_ = (float*)gradMap.getRawImage();
146  confMap.resize(width_, height_); confMap_ = (float*)confMap.getRawImage();
147  weightMap.resize(width_, height_); weightMap_ = (float*)weightMap.getRawImage();
148  labelImage.resize(width_, height_);
149  labelView.resize(width_, height_);
150 
151  return true;
152 }
153 
154 bool EdisonSegmModule::close()
155 {
156  _imgPort.close();
157  _labelPort.close();
158  _labelViewPort.close();
159  _filtPort.close();
160  _viewPort.close();
161  _configPort.close();
162  _rawPort.close();
163 
164  // also deallocate image _frame
165  return true;
166 }
167 
168 bool EdisonSegmModule::interruptModule(){
169 
170  _imgPort.interrupt();
171  _configPort.interrupt();
172  _labelPort.interrupt();
173  _filtPort.interrupt();
174  _labelViewPort.interrupt();
175  _viewPort.interrupt();
176  _rawPort.interrupt();
177  return true;
178 }
179 
180 bool EdisonSegmModule::updateModule()
181 {
182  ImageOf<PixelRgb> *yrpImgIn;
183  static int cycles = 0;
184 
185  yrpImgIn = _imgPort.read();
186  if (yrpImgIn == NULL) // this is the case if module is requested to quit while waiting for image
187  return true;
188 
189  bool use_private_stamp;
190  Stamp s;
191  if(!_imgPort.getEnvelope(s))
192  {
193  cout << "No stamp found in input image. Will use private stamp" << endl;
194  use_private_stamp = true;
195  }
196  else
197  {
198  cout << "Received image #" << s.getCount() << " generated at time " << s.getTime() << endl;
199  use_private_stamp = false;
200  }
201 
202  if(cycles == 0)
203  _timestart = yarp::os::Time::now();
204  cycles++;
205 
206  cv::Mat imgMat = toCvMat(*yrpImgIn);
207 
208  //Rescale image if required
209  if( (width_ != orig_width_) || (height_ != orig_height_ ) )
210  cv::resize(imgMat,toCvMat(inputImage),cv::Size(),1.0,1.0);
211  else
212  imgMat.copyTo(toCvMat(inputImage));
213 
214  double edgetime = yarp::os::Time::now();
215  //compute gradient and confidence maps
216  BgEdgeDetect edgeDetector(gradWindRad);
217  BgImage bgImage;
218  bgImage.SetImage(inputImage_, width_, height_, true);
219  edgeDetector.ComputeEdgeInfo(&bgImage, confMap_, gradMap_);
220  //compute the weigth map
221  for(int i = 0; i < width_*height_; i++) {
222  if(gradMap_[i] > 0.02) {
223  weightMap_[i] = mixture*gradMap_[i] + (1 - mixture)*confMap_[i];
224  } else {
225  weightMap_[i] = 0;
226  }
227  }
229  cout << "Edge computation Time (ms): " << (yarp::os::Time::now() - edgetime)*1000.0 << endl;
230 
231  msImageProcessor iProc;
232  if( dim_ == 3 )
233  iProc.DefineImage(inputImage_, COLOR, height_, width_);
234  else
235  {
236  vector<cv::Mat> channels;
237  cv::cvtColor(toCvMat(inputImage), toCvMat(inputHsv), CV_RGB2HSV);
238  cv::split(toCvMat(inputHsv),channels);
239  toCvMat(inputHue)=channels[0];
240  iProc.DefineImage(inputHue_, GRAYSCALE, height_, width_);
241  }
242  if(iProc.ErrorStatus) {
243  cout << "MeanShift Error" << endl;
244  return false;
245  }
246  iProc.SetWeightMap(weightMap_, threshold);
247  if(iProc.ErrorStatus) {
248  cout << "MeanShift Error" << endl;
249  return false;
250  }
251 
252  double filtertime = yarp::os::Time::now();
253  iProc.Filter(sigmaS, sigmaR, speedup);
254  if(iProc.ErrorStatus) {
255  cout << "MeanShift Error" << endl;
256  return false;
257  }
258  cout << "Mean Shift Filter Computation Time (ms): " << (yarp::os::Time::now() - filtertime)*1000.0 << endl;
259 
260  //obtain the filtered image
261  iProc.GetResults(filtImage_);
262  if(iProc.ErrorStatus) {
263  cout << "MeanShift Error" << endl;
264  return false;
265  }
266 
267  //fuse regions
268  double fusetime = yarp::os::Time::now();
269  iProc.FuseRegions(sigmaR, minRegion);
270  if(iProc.ErrorStatus) {
271  cout << "MeanShift Error" << endl;
272  return false;
273  }
274  cout << "Region Fusion Computation Time (ms): " << (yarp::os::Time::now() - fusetime)*1000.0 << endl;
275 
276  //obtain the segmented image
277  iProc.GetResults(segmImage_);
278  if(iProc.ErrorStatus) {
279  cout << "MeanShift Error" << endl;
280  return false;
281  }
282 
283  int regionCount; // how many regions have been found
284  int *labels = NULL; //pointer for the labels (should this be released in the end?)
285  float *modes; //pointer for the Luv values (should this be released in the end?)
286  int *modePointCounts; //the area of each region (should this be released in the end?)
287 
288  regionCount = iProc.GetRegions(&labels, &modes, &modePointCounts);
289  int *labelp = (int*)labelImage.getRawImage();
290  for(int i = 0; i < width_*height_; i++)
291  labelp[i] = labels[i];
292 
293  cv::convertScaleAbs(toCvMat(labelImage),toCvMat(labelView));
294 
295  //prepare timestamps
296  if(use_private_stamp)
297  {
298  _stamp.update();
299  _labelPort.setEnvelope(_stamp);
300  _labelViewPort.setEnvelope(_stamp);
301  _viewPort.setEnvelope(_stamp);
302  _filtPort.setEnvelope(_stamp);
303  _rawPort.setEnvelope(_stamp);
304  }
305  else
306  {
307  _labelPort.setEnvelope(s);
308  _labelViewPort.setEnvelope(s);
309  _viewPort.setEnvelope(s);
310  _filtPort.setEnvelope(s);
311  _rawPort.setEnvelope(s);
312  }
313 
314  ImageOf<PixelInt> &yrpImgLabel = _labelPort.prepare();
315  //Rescale image if required
316  if( (width_ != orig_width_) || (height_ != orig_height_ ) )
317  {
318  yrpImgLabel.resize(orig_width_, orig_height_);
319  cv::resize(toCvMat(labelImage),toCvMat(yrpImgLabel),cv::Size(),1.0,1.0);
320  }
321  else
322  yrpImgLabel = labelImage;
323  _labelPort.write();
324 
325  ImageOf<PixelMono> &yrpImgDebug = _labelViewPort.prepare();
326  //Rescale image if required
327  if( (width_ != orig_width_) || (height_ != orig_height_ ) )
328  {
329  yrpImgDebug.resize(orig_width_, orig_height_);
330  cv::resize(toCvMat(labelView),toCvMat(yrpImgDebug),cv::Size(),1.0,1.0);
331  }
332  else
333  yrpImgDebug = labelView;
334  _labelViewPort.write();
335 
336 
337  ImageOf<PixelRgb> &yrpFiltOut = _filtPort.prepare();
338  //Rescale image if required
339  if( (width_ != orig_width_) || (height_ != orig_height_ ) )
340  {
341  yrpFiltOut.resize(orig_width_, orig_height_);
342  cv::resize(toCvMat(filtImage),toCvMat(yrpFiltOut),cv::Size(),1.0,1.0);
343  }
344  else
345  yrpFiltOut = filtImage;
346  _filtPort.write();
347 
348  ImageOf<PixelRgb> &yrpImgView = _viewPort.prepare();
349  //Rescale image if required
350  if( (width_ != orig_width_) || (height_ != orig_height_ ) )
351  {
352  yrpImgView.resize(orig_width_, orig_height_);
353  cv::resize(toCvMat(segmImage),toCvMat(yrpImgView),cv::Size(),1.0,1.0);
354  }
355  else
356  yrpImgView = segmImage;
357  _viewPort.write();
358 
359  ImageOf<PixelRgb> &yrpImgOut = _rawPort.prepare();
360  yrpImgOut = *yrpImgIn;
361  _rawPort.write();
362 
363  //report the frame rate
364  if(cycles % 100 == 0)
365  {
366  double cps = ((double)cycles)/(yarp::os::Time::now() - _timestart);
367  printf("fps: %02.2f\n", cps);
368  }
369  return true;
370 }
371 
372