segmentation
All Data Structures Namespaces Files Functions Variables Modules Pages
lbpExtract.cpp
1 /*
2  * Copyright (C) 2015 Department of iCub Facility - Istituto Italiano di Tecnologia
3  * Author: Vadim Tikhanoff
4  * email: vadim.tikhanoff@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 <opencv2/core.hpp>
19 #include <yarp/cv/Cv.h>
20 #include "lbpExtract.h"
21 
22 using namespace yarp::sig;
23 using namespace yarp::cv;
24 
25 /**********************************************************/
26 bool SEGMENTModule::configure(yarp::os::ResourceFinder &rf){
27  moduleName = rf.check("name", yarp::os::Value("lbpExtract"), "module name (string)").asString();
28 
29  setName(moduleName.c_str());
30 
31  handlerPortName = "/";
32  handlerPortName += getName();
33  handlerPortName += "/rpc:i";
34 
35  if (!rpcPort.open(handlerPortName)) {
36  fprintf(stdout, "%s : Unable to open port %s\n", getName().c_str(), handlerPortName.c_str());
37  return false;
38  }
39 
40  attach(rpcPort);
41  closing = false;
42 
43  /* create the thread and pass pointers to the module parameters */
44  segmentManager = new SEGMENTManager( moduleName );
45 
46  int rad = rf.check("radius",yarp::os::Value(5)).asInt32();
47  int iter = rf.check("numIteration",yarp::os::Value(5)).asInt32();
48  int neigh = rf.check("neighbours",yarp::os::Value(8)).asInt32();
49  int topB = rf.check("topBound",yarp::os::Value(40)).asInt32();
50  int minL = rf.check("minArcLength",yarp::os::Value(75)).asInt32();
51  int maxL = rf.check("maxArcLength",yarp::os::Value(1000)).asInt32();
52  int minA = rf.check("minArea",yarp::os::Value(300)).asInt32();
53  int maxA = rf.check("maxArea",yarp::os::Value(6000)).asInt32();
54  int minW = rf.check("minWidth",yarp::os::Value(3)).asInt32();
55 
56  segmentManager->setDefaultValues(rad, neigh, topB, minL, maxL, iter, minA, maxA, minW);
57 
58  /* now start the thread to do the work */
59  segmentManager->open();
60 
61  return true ;
62 }
63 
64 /**********************************************************/
65 bool SEGMENTModule::interruptModule(){
66  rpcPort.interrupt();
67  return true;
68 }
69 
70 /**********************************************************/
71 bool SEGMENTModule::close(){
72  //rpcPort.close();
73  yDebug("starting the shutdown procedure\n");
74  segmentManager->interrupt();
75  segmentManager->close();
76  yDebug("deleting thread\n");
77  delete segmentManager;
78  yDebug("done deleting thread\n");
79  return true;
80 }
81 
82 /************************************************************************/
83 bool SEGMENTModule::attach(yarp::os::RpcServer &source){
84  return this->yarp().attachAsServer(source);
85 }
86 
87 /**********************************************************/
88 bool SEGMENTModule::quit(){
89  closing = true;
90  return true;
91 }
92 
93 /**********************************************************/
94 bool SEGMENTModule::reset(){
95  //to be conpleted
96  return true;
97 }
98 
99 /**********************************************************/
100 bool SEGMENTModule::updateModule(){
101  return !closing;
102 }
103 
104 /**********************************************************/
105 double SEGMENTModule::getPeriod(){
106  return 0.1;
107 }
108 
109 /**********************************************************/
110 bool SEGMENTModule::setRadius(const int32_t radius){
111  segmentManager->setRadius(radius);
112  return true;
113 }
114 
115 /**********************************************************/
116 bool SEGMENTModule::setNeighbours(const int32_t neighbours){
117  segmentManager->setNeighbours(neighbours);
118  return true;
119 }
120 
121 /**********************************************************/
122 bool SEGMENTModule::setTopBound(const int32_t topBound){
123  segmentManager->setTopBound(topBound);
124  return true;
125 }
126 
127 /**********************************************************/
128 bool SEGMENTModule::setMinArcLength(const int32_t minArcLenght){
129  segmentManager->setMinArcLength(minArcLenght);
130  return true;
131 }
132 
133 /**********************************************************/
134 bool SEGMENTModule::setMaxArcLength(const int32_t maxArcLenght){
135  segmentManager->setMaxArcLength(maxArcLenght);
136  return true;
137 }
138 
139 /**********************************************************/
140 bool SEGMENTModule::setMinArea(const int32_t minArea){
141  segmentManager->setMinArea(minArea);
142  return true;
143 }
144 
145 /**********************************************************/
146 bool SEGMENTModule::setMaxArea(const int32_t maxArea){
147  segmentManager->setMaxArea(maxArea);
148  return true;
149 }
150 
151 /**********************************************************/
152 bool SEGMENTModule::setMinWidth(const int32_t minWidth){
153  segmentManager->setMinWidth(minWidth);
154  return true;
155 }
156 
157 /**********************************************************/
158 bool SEGMENTModule::setNumIteration(const int32_t numIteration){
159  segmentManager->setNumIteration(numIteration);
160  return true;
161 }
162 
163 /**********************************************************/
164 bool SEGMENTModule::setbbOffset(const int32_t offset){
165  segmentManager->setbbOffset(offset);
166  return true;
167 }
168 
169 /**********************************************************/
170 bool SEGMENTModule::resetAllValues(){
171 
172  segmentManager->resetAllValues();
173  return true;
174 }
175 
176 /**********************************************************/
177 bool SEGMENTModule::verbosity(const int32_t verbose){
178  bool rep;
179  if (verbose <0 && verbose > 1)
180  rep = false;
181  else
182  {
183  segmentManager->verbosity(verbose);
184  rep = true;
185  }
186  return rep;
187 }
188 
189 /**********************************************************/
190 int SEGMENTModule::getRadius(){
191  return segmentManager->getRadius();
192 }
193 
194 /**********************************************************/
195 int SEGMENTModule::getNeighbours(){
196  return segmentManager->getNeighbours();
197 }
198 
199 /**********************************************************/
200 int SEGMENTModule::getTopBound(){
201  return segmentManager->getTopBound();
202 }
203 
204 /**********************************************************/
205 int SEGMENTModule::getMinArcLength(){
206  return segmentManager->getMinArcLength();
207 }
208 
209 /**********************************************************/
210 int SEGMENTModule::getMaxArcLength(){
211  return segmentManager->getMaxArcLength();
212 }
213 
214 /**********************************************************/
215 int SEGMENTModule::getMinArea(){
216  return segmentManager->getMinArea();
217 }
218 
219 /**********************************************************/
220 int SEGMENTModule::getMaxArea(){
221  return segmentManager->getMaxArea();
222 }
223 
224 /**********************************************************/
225 int SEGMENTModule::getMinWidth(){
226  return segmentManager->getMinWidth();
227 }
228 
229 /**********************************************************/
230 int SEGMENTModule::getNumIteration(){
231  return segmentManager->getNumIteration();
232 }
233 
234 /**********************************************************/
235 int SEGMENTModule::getbbOffset(){
236  return segmentManager->getbbOffset();
237 }
238 
239 /**********************************************************/
240 yarp::os::Bottle SEGMENTModule::get_component_around(const int32_t x, const int32_t y){
241  return segmentManager->get_component_around(x, y);
242 }
243 
244 /**********************************************************/
245 SEGMENTManager::~SEGMENTManager(){
246 
247 }
248 
249 /**********************************************************/
250 SEGMENTManager::SEGMENTManager( const std::string &moduleName ){
251  fprintf(stdout,"initialising Variables\n");
252  this->moduleName = moduleName;
253 }
254 
255 /**********************************************************/
256 bool SEGMENTManager::setDefaultValues(const int32_t radius, const int32_t neighbours, const int32_t topBound, const int32_t minArcLength, const int32_t maxArcLength, const int32_t numIteration, const int32_t minArea, const int32_t maxArea, const int32_t minWidth){
257 
258  defaultRadius = radius;
259  defaultNeighbours = neighbours;
260  defaultTopBound = topBound;
261  defaultMinArcLength = minArcLength;
262  defaultMaxArcLength = maxArcLength;
263  defaultNumIteration = numIteration;
264  defaultMinArea = minArea;
265  defaultMaxArea = maxArea;
266  defaultMinWidth = minWidth;
267 
268  return true;
269 }
270 
271 /**********************************************************/
272 bool SEGMENTManager::open(){
273  this->useCallback();
274 
275  //create all ports
276  inPortName = "/" + moduleName + "/image:i";
277  BufferedPort<ImageOf<PixelRgb> >::open( inPortName );
278 
279  outPortPropagate.open( "/" + moduleName + "/propagated:o" );
280  outPortBlobs.open( "/" + moduleName + "/extractedlbp:o" );
281  outPortSegmented.open( "/" + moduleName + "/segmentedlbp:o" );
282  outTargetPort.open( "/" + moduleName + "/blobs:o" );
283  outPortLbp.open( "/" + moduleName + "/lbp:o" );
284  outPortLbpContours.open( "/" + moduleName + "/contourslbp:o" );
285 
286  radius = defaultRadius;
287  neighbours = defaultNeighbours;
288  minArcLength = defaultMinArcLength;
289  maxArcLength = defaultMaxArcLength;
290  topBound = defaultTopBound;
291  numIteration = defaultNumIteration;
292 
293  minArea = defaultMinArea;
294  maxArea = defaultMaxArea;
295 
296  minWidth = defaultMinWidth;
297 
298  bbOffset = 0;
299 
300  verbose = false;
301 
302  yInfo("Module started with the following default values:\nradius: %d, neighbours %d, minArcLength %d, maxArcLength %d, minArea %d, maxArea %d, minWidth %d, topBound %d, numIteration %d", radius, neighbours, minArcLength, maxArcLength, minArea, maxArea, minWidth, topBound, numIteration);
303 
304  return true;
305 }
306 
307 /**********************************************************/
308 void SEGMENTManager::close(){
309 
310  yDebug("now closing ports...\n");
311 
312  outPortPropagate.close();
313  outPortBlobs.close();
314  outPortSegmented.close();
315  outPortLbp.close();
316  outPortLbpContours.close();
317  outTargetPort.close();
318 
319  BufferedPort<ImageOf<PixelRgb> >::close();
320 
321  yDebug("finished closing the read port...\n");
322 }
323 
324 /**********************************************************/
325 void SEGMENTManager::interrupt(){
326  yDebug("cleaning up...\n");
327  yDebug("attempting to interrupt ports\n");
328  BufferedPort<ImageOf<PixelRgb> >::interrupt();
329 
330  yDebug("finished interrupt ports\n");
331 }
332 
333 /**********************************************************/
334 bool SEGMENTManager::setRadius(const int32_t radius){
335  this->radius = radius;
336  return true;
337 }
338 
339 /**********************************************************/
340 bool SEGMENTManager::setNeighbours(const int32_t neighbours){
341  this->neighbours = neighbours;
342  return true;
343 }
344 
345 /**********************************************************/
346 bool SEGMENTManager::setTopBound(const int32_t topBound){
347  this->topBound = topBound;
348  return true;
349 }
350 
351 /**********************************************************/
352 bool SEGMENTManager::setMinArcLength(const int32_t minArcLength){
353  this->minArcLength = minArcLength;
354  return true;
355 }
356 
357 /**********************************************************/
358 bool SEGMENTManager::setMaxArcLength(const int32_t maxArcLength){
359  this->maxArcLength = maxArcLength;
360  return true;
361 }
362 
363 /**********************************************************/
364 bool SEGMENTManager::setMinArea(const int32_t minArea){
365  this->minArea = minArea;
366  return true;
367 }
368 
369 /**********************************************************/
370 bool SEGMENTManager::setMaxArea(const int32_t maxArea){
371  this->maxArea = maxArea;
372  return true;
373 }
374 
375 /**********************************************************/
376 bool SEGMENTManager::setMinWidth(const int32_t minWidth){
377  this->minWidth = minWidth;
378  return true;
379 }
380 
381 /**********************************************************/
382 bool SEGMENTManager::setNumIteration(const int32_t numIteration){
383  this->numIteration = numIteration;
384  return true;
385 }
386 
387 /**********************************************************/
388 bool SEGMENTManager::setbbOffset(const int32_t offset){
389  this->bbOffset = offset;
390  return true;
391 }
392 
393 /**********************************************************/
394 bool SEGMENTManager::resetAllValues(){
395  radius = defaultRadius;
396  neighbours = defaultNeighbours;
397  topBound = defaultTopBound;
398  minArcLength = defaultMinArcLength;
399  maxArcLength = defaultMaxArcLength;
400  minArea = defaultMinArea;
401  maxArea = defaultMaxArea;
402  minWidth = defaultMinWidth;
403  bbOffset = 0;
404  return true;
405 }
406 
407 /**********************************************************/
408 bool SEGMENTManager::verbosity(const int32_t verbose)
409 {
410  this->verbose = verbose;
411  return true;
412 }
413 
414 /**********************************************************/
415 int SEGMENTManager::getRadius(){
416  return this->radius;
417 }
418 
419 /**********************************************************/
420 int SEGMENTManager::getNeighbours(){
421  return this->neighbours;
422 }
423 
424 /**********************************************************/
425 int SEGMENTManager::getTopBound(){
426  return this->topBound;
427 }
428 
429 /**********************************************************/
430 int SEGMENTManager::getMinArcLength(){
431  return this->minArcLength;
432 }
433 
434 /**********************************************************/
435 int SEGMENTManager::getMaxArcLength(){
436  return this->maxArcLength;
437 }
438 
439 /**********************************************************/
440 int SEGMENTManager::getMinArea(){
441  return this->minArea;
442 }
443 
444 /**********************************************************/
445 int SEGMENTManager::getMaxArea(){
446  return this->maxArea;
447 }
448 
449 /**********************************************************/
450 int SEGMENTManager::getMinWidth(){
451  return this->minWidth;
452 }
453 
454 /**********************************************************/
455 int SEGMENTManager::getNumIteration(){
456  return this->numIteration;
457 }
458 
459 /**********************************************************/
460 int SEGMENTManager::getbbOffset(){
461  return this->bbOffset;
462 }
463 
464 
465 /**********************************************************/
466 yarp::os::Bottle SEGMENTManager::get_component_around(const int32_t x, const int32_t y){
467 
468  yarp::os::Bottle& tosend = getComponents(segmented, x, y);
469 
470  return tosend;
471 }
472 
473 /**********************************************************/
474 yarp::os::Bottle& SEGMENTManager::getComponents(cv::Mat &img, int x, int y)
475 {
476  allPoints.clear();
477 
478  std::vector<std::vector<cv::Point> > objcnt;
479  std::vector<cv::Vec4i> objhrch;
480  cv::Mat prov;
481  semComp.lock();
482 
483  if (img.rows == 0 || img.cols == 0){
484  return allPoints;
485  }
486 
487  cvtColor(img, prov, CV_BGR2GRAY);
488 
489  findContours( prov, objcnt, objhrch, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE );
490 
491  semComp.unlock();
492 
493  cv::Mat nonZeroCoordinates;
494  cv::Mat inside = cv::Mat::zeros( imgMat.size(), CV_8UC1 );
495 
496  for( size_t i = 0; i< objcnt.size(); i++ )
497  {
498  if (pointPolygonTest( objcnt[i], cv::Point2f(x, y), 1 ) > 0)
499  cv::drawContours( inside, objcnt, i, cvScalar(255,255,355), cv::FILLED, 8, objhrch, 0, cv::Point() );
500  }
501 
502  cv::findNonZero(inside, nonZeroCoordinates);
503 
504  for (size_t i = 0; i < nonZeroCoordinates.total(); i++ ) {
505  yarp::os::Bottle &subjList = allPoints.addList();
506  subjList.addInt32(nonZeroCoordinates.at<cv::Point>(i).x);
507  subjList.addInt32(nonZeroCoordinates.at<cv::Point>(i).y);
508  }
509 
510  return allPoints;
511 }
512 /**********************************************************/
513 void SEGMENTManager::onRead(ImageOf<yarp::sig::PixelRgb> &img){
514  yarp::os::Stamp ts;
515 
516  ImageOf<PixelRgb> &outOrig = outPortPropagate.prepare();
517  ImageOf<PixelRgb> &outImg = outPortBlobs.prepare();
518  ImageOf<PixelRgb> &outSeg = outPortSegmented.prepare();
519  ImageOf<PixelMono> &outLbp = outPortLbp.prepare();
520  ImageOf<PixelMono> &outLbpContour = outPortLbpContours.prepare();
521 
522  outOrig.resize(img.width(), img.height());
523  outImg.resize(img.width(), img.height());
524  outSeg.resize(img.width(), img.height());
525  outLbp.resize(img.width(), img.height());
526  outLbpContour.resize(img.width(), img.height());
527 
528  outOrig.zero();
529  outImg.zero();
530  outSeg.zero();
531  outLbp.zero();
532  outLbpContour.zero();
533 
534  imgMat = toCvMat(img);
535 
536  yarp::os::Bottle &b = outTargetPort.prepare();
537  b.clear();
538 
539  cv::Mat temp;
540  cv::Mat lbp = cv::Mat::zeros( imgMat.size(), CV_8UC1 );
541  cv::Mat extracted = cv::Mat::zeros( imgMat.size(), CV_8UC3 );
542 
543  semComp.lock();
544  segmented = cv::Mat::zeros( imgMat.size(), CV_8UC3 );
545 
546  cvtColor(imgMat, temp, CV_BGR2GRAY);
547  //GaussianBlur(temp, temp, cv::Size(3,3), 5, 3, BORDER_CONSTANT); // tiny bit of smoothing is always a good idea
548 
549  // Variance-based LB - lbp::OLBP
550  lbp::VARLBP(temp, lbp, radius, neighbours);
551 
552  // now to show the patterns a normalization is necessary
553  // a simple min-max norm will do the job...
554 
555  cv::Mat norm(lbp);
556 
557  normalize(lbp, norm, 0, 255, cv::NORM_MINMAX, CV_8UC1);
558 
559  uint8_t* pixelPtr = (uint8_t*)norm.data;
560  int cn = norm.channels();
561  for(int i = 0; i < norm.rows; i++){
562  for(int j = 0; j < norm.cols; j += cn){
563  cv::Scalar_<uint8_t> bgrPixel;
564  bgrPixel.val[0] = pixelPtr[i*norm.cols*cn + j*cn + 0];
565 
566  if (bgrPixel.val[0] < 255 && bgrPixel.val[0] > 5)
567  pixelPtr[i*norm.cols*cn + j*cn + 0] = 255;
568  else
569  pixelPtr[i*norm.cols*cn + j*cn + 0] = 0;
570  }
571  }
572 
573  cv::Mat cleanedImg;
574  cleanedImg = norm.clone();
575 
576  std::vector<std::vector<cv::Point> > cnt;
577  std::vector<cv::Vec4i> hrch;
578 
579  cv::Mat structuringElement = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
580  cv::morphologyEx( cleanedImg, cleanedImg, cv::MORPH_CLOSE, structuringElement );
581 
582  // Find contours and trim blobs according to radius size
583  if(radius > 1)
584  {
585  findContours( cleanedImg, cnt, hrch, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_L1 );
586  cv::fillPoly( cleanedImg, cnt, 255);
587  structuringElement = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(2*radius-1, 2*radius-1));
588  cv::morphologyEx( cleanedImg, cleanedImg, cv::MORPH_ERODE, structuringElement );
589  }
590 
591  // Find new clean contours and further remove parts that are too thin
592  if(minWidth > 0)
593  {
594  findContours( cleanedImg, cnt, hrch, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_L1 );
595  cv::fillPoly( cleanedImg, cnt, 255);
596  structuringElement = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(minWidth, minWidth));
597  cv::morphologyEx( cleanedImg, cleanedImg, cv::MORPH_OPEN, structuringElement );
598  }
599 
600  // Find final clean contours
601  findContours( cleanedImg, cnt, hrch, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_L1 );
602 
603  // Align contours with initial image
604  int alignOffsetX = (imgMat.cols - cleanedImg.cols) / 2;
605  int alignOffsetY = (imgMat.rows - cleanedImg.rows) / 2;
606  for( size_t i = 0; i < cnt.size(); i++ )
607  {
608  for( size_t j = 0; j < cnt[i].size(); j++ )
609  {
610  cnt[i][j].x += alignOffsetX;
611  cnt[i][j].y += alignOffsetY;
612  }
613  }
614 
615  // Get the moments
616  std::vector<cv::Moments> mu(cnt.size() );
617  for( size_t i = 0; i < cnt.size(); i++ )
618  mu[i] = moments( cnt[i], false );
619 
620  // Get the mass centers:
621  std::vector<cv::Point2f> mc( cnt.size() );
622 
623  for( size_t i = 0; i < cnt.size(); i++ )
624  mc[i] = cv::Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 );
625 
626  std::vector<std::vector<cv::Point> > contours_poly( cnt.size() );
627  std::vector<cv::Rect> boundRect( cnt.size() );
628 
629  for( size_t i = 0; i< cnt.size(); i++ ){
630 
631  double length = arcLength( cnt[i], true );
632  double area = contourArea(cnt[i]);
633 
634  if ( (mc[i].y > topBound) && (length > minArcLength) && (length < maxArcLength) && (area > minArea) && (area < maxArea)){
635  //yDebug(" Contour[%d] -X[%lf] -Y[%lf] -Length: %.2f minArc %d maxArc %d topBound %d\n", i, mc[i].x, mc[i].y, length, minArcLength, maxArcLength, topBound );
636 
637  if (verbose)
638  {
639  yDebug(" Contour[%zu] -X[%lf] -Y[%lf] -Length: %.2f -Area %lf", i, mc[i].x, mc[i].y, length, area);
640  cv::drawContours( extracted, cnt, i, cvScalar(255,0,0), 2, 8, hrch, 0, cv::Point() );
641  }
642 
643  approxPolyDP( cv::Mat(cnt[i]), contours_poly[i], 3, true );
644  boundRect[i] = boundingRect( cv::Mat(contours_poly[i]) );
645 
646  /*yarp::os::Bottle &t=b.addList();
647  t.addFloat64(boundRect[i].tl().x);
648  t.addFloat64(boundRect[i].tl().y);
649  t.addFloat64(boundRect[i].br().x);
650  t.addFloat64(boundRect[i].br().y);*/
651 
652  double topLeftX = boundRect[i].tl().x;
653  double topLeftY = boundRect[i].tl().y;
654  double bottomRightX = boundRect[i].br().x;
655  double bottomRightY = boundRect[i].br().y;
656 
657  int shift = 3;
658 
659  if (topLeftX > shift)
660  topLeftX -= shift;
661 
662  if (topLeftY > shift)
663  topLeftY -= shift;
664 
665  if (bottomRightX > 0 && bottomRightX < (img.width() - shift))
666  bottomRightX += shift;
667 
668  if (bottomRightY > 0 && bottomRightY < (img.height() - shift))
669  bottomRightY += shift;
670 
671  /*-------------------------grabcut on bounding box---------------------------------*/
672 
673  int blobWidth = std::abs(bottomRightX - topLeftX);
674  int blobHeight = std::abs(bottomRightY - topLeftY);
675 
676  //yDebug("ROI: %d %d %d %d arcLength %.2f \n", boundRect[i].tl().x, boundRect[i].tl().y, blobWidth, blobHeight, length);
677 
678  cv::Rect roi(topLeftX, topLeftY, blobWidth, blobHeight);
679 
680  if (blobWidth > 20 && blobHeight > 20){ //keep it safe for the grabCut algorithm
681 
682  //cvtColor( imgMat, imgMat, CV_BGR2RGB);
683  cv::Mat image_roi(imgMat, roi);
684 
685  int border = 3;
686  cv::Rect rect;
687  rect = cv::Rect( border, border, image_roi.cols - (border*2), image_roi.rows-(border*2));
688 
689  cv::Mat result; // segmentation result (4 possible values)
690  cv::Mat bgModel,fgModel; // the models (internally used)
691 
692  // GrabCut segmentation
693  cv::grabCut(image_roi, result, rect, bgModel, fgModel, numIteration, cv::GC_INIT_WITH_RECT);
694 
695  // Get the pixels marked as likely foreground
696  cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);
697 
698  // Generate output image
699  cv::Mat foreground(image_roi.size(),CV_8UC3,cv::Scalar(0,0,0));
700  image_roi.copyTo(foreground,result); // bg pixels not copied
701 
703  foreground.copyTo(segmented(cv::Rect(topLeftX, topLeftY, foreground.cols, foreground.rows)));
704  }
705  }
706  }
707 
708  std::vector<std::vector<cv::Point> > objcnt;
709  std::vector<cv::Vec4i> objhrch;
710  cv::Mat prov;
711  cvtColor(segmented, prov, CV_BGR2GRAY);
712  findContours( prov, objcnt, objhrch, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE );
713 
714  // Get the moments
715  std::vector<cv::Moments> muSeg(objcnt.size() );
716  for( size_t i = 0; i < objcnt.size(); i++ )
717  muSeg[i] = moments( objcnt[i], false );
718 
719  // Get the mass centers:
720  std::vector<cv::Point2f> mcSeg( objcnt.size() );
721 
722  for( size_t i = 0; i < objcnt.size(); i++ )
723  mcSeg[i] = cv::Point2f( muSeg[i].m10/muSeg[i].m00 , muSeg[i].m01/muSeg[i].m00 );
724 
725  std::vector<std::vector<cv::Point> > contours_polySeg( objcnt.size() );
726  std::vector<cv::Rect> boundRectSeg( objcnt.size() );
727 
728  for( size_t i = 0; i< objcnt.size(); i++ ){
729 
730  double area = contourArea(objcnt[i]);
731 
732  if (area > minArea)
733  {
734  cv::drawContours( extracted, objcnt, i, cvScalar(255,255,255), cv::FILLED, 8, objhrch, 0, cv::Point() );
735 
736  approxPolyDP( cv::Mat(objcnt[i]), contours_polySeg[i], 3, true );
737  boundRectSeg[i] = boundingRect( cv::Mat(contours_polySeg[i]) );
738 
739  yarp::os::Bottle &t=b.addList();
740 
741  if (bbOffset < 0)
742  bbOffset = 0;
743 
744  double topLeftX = boundRectSeg[i].tl().x - bbOffset;
745  double topLeftY = boundRectSeg[i].tl().y - bbOffset;
746  double bottomRightX = boundRectSeg[i].br().x + bbOffset;
747  double bottomRightY = boundRectSeg[i].br().y + bbOffset;
748 
749  yDebug("%lf %lf %lf %lf \n", topLeftX, topLeftY, bottomRightX, bottomRightY);
750 
751  int shift = 3;
752 
753  if (topLeftX < shift)
754  topLeftX = shift;
755 
756  if (topLeftY < shift)
757  topLeftY = shift;
758 
759  if (bottomRightX > img.width()-3)
760  bottomRightX = img.width()-3;
761 
762  if (bottomRightY > img.height()-3)
763  bottomRightY = img.height()-3;
764 
765  t.addFloat64(topLeftX);
766  t.addFloat64(topLeftY);
767  t.addFloat64(bottomRightX);
768  t.addFloat64(bottomRightY);
769 
770  /*cv::Point tl = cv::Point( (topLeftX), (topLeftY) );
771  cv::Point br = cv::Point( (bottomRightX), (bottomRightY) );
772 
773  line(segmented, cv::Point( tl.x, tl.y ), cv::Point( br.x, tl.y ),cv::Scalar(255,255,255), 1, 8);
774  line(segmented, cv::Point( br.x, tl.y ), cv::Point( br.x, br.y ),cv::Scalar(255,255,255), 1, 8);
775  line(segmented, cv::Point( br.x, br.y ), cv::Point( tl.x, br.y ),cv::Scalar(255,255,255), 1, 8);
776  line(segmented, cv::Point( tl.x , br.y ), cv::Point( tl.x, tl.y ),cv::Scalar(255,255,255), 1, 8);
777  */
778  }
779  }
780 
781  if (verbose)
782  yDebug(" ");
783 
784  semComp.unlock();
785 
786  if (b.size())
787  outTargetPort.write();
788 
789  outOrig.resize(imgMat.size().width, imgMat.size().height);
790  outOrig = fromCvMat<PixelRgb>(imgMat);
791  outPortPropagate.setEnvelope(ts);
792  outPortPropagate.write();
793 
794  outImg.resize(extracted.size().width, extracted.size().height);
795  outImg = fromCvMat<PixelRgb>(extracted);
796  outPortBlobs.setEnvelope(ts);
797  outPortBlobs.write();
798 
799  outSeg.resize(segmented.size().width, segmented.size().height);
800  outSeg = fromCvMat<PixelRgb>(segmented);
801  outPortSegmented.setEnvelope(ts);
802  outPortSegmented.write();
803 
804  cv::Mat olbp, tmp;
805  cvtColor(imgMat, tmp, CV_BGR2GRAY);
806  lbp::OLBP(tmp, olbp); // use the original operator
807  normalize(olbp, olbp, 0, 255, cv::NORM_MINMAX, CV_8UC1);
808 
809  outLbpContour.resize(norm.size().width, norm.size().height);
810  outLbpContour = fromCvMat<PixelMono>(norm);
811  outPortLbpContours.setEnvelope(ts);
812  outPortLbpContours.write();
813 
814  outLbp.resize(olbp.size().width, olbp.size().height);
815  outLbp = fromCvMat<PixelMono>(olbp);
816  outPortLbp.setEnvelope(ts);
817  outPortLbp.write();
818 }
819 //empty line to make gcc happy
Original code by philipp <bytefish[at]gmx[dot]de>
Definition: histogram.h:27