00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <QMouseEvent>
00031
00032 #include "object_segmentation_gui/object_segmentation_rviz_ui.h"
00033
00034 #include "rviz_interaction_tools/image_tools.h"
00035 #include "rviz_interaction_tools/image_overlay.h"
00036 #include "rviz_interaction_tools/camera_tools.h"
00037 #include "rviz_interaction_tools/unique_string_manager.h"
00038
00039 #include <rviz/window_manager_interface.h>
00040 #include <rviz/render_panel.h>
00041 #include <rviz/visualization_manager.h>
00042 #include <rviz/validate_floats.h>
00043 #include <rviz/frame_manager.h>
00044
00045 #include <OGRE/OgreRenderWindow.h>
00046 #include <OGRE/OgreRoot.h>
00047
00048 #include "tabletop_object_detector/marker_generator.h"
00049
00050 #include "pcl/point_cloud.h"
00051 #include "pcl/point_types.h"
00052 #include "pcl/filters/statistical_outlier_removal.h"
00053 #include "pcl/filters/voxel_grid.h"
00054
00055 #include <sensor_msgs/PointCloud.h>
00056 #include <sensor_msgs/PointCloud2.h>
00057 #include <sensor_msgs/point_cloud_conversion.h>
00058 #include <sensor_msgs/image_encodings.h>
00059
00060 #include "ui_main_frame.h"
00061
00062 namespace enc = sensor_msgs::image_encodings;
00063
00064
00065
00066
00067 #define MAX_FG 6
00068
00069 namespace object_segmentation_gui
00070 {
00071
00072 typedef pcl::PointXYZ PCL_Point;
00073
00074 static const char
00075 * HELP_TEXT =
00076 "Left Mouse Button: Click on objects or drag a rectangle to segment them. \n\
00077 Segment Button: Start Segmentation. \n\
00078 Reset Button: Reset Segmentation and Seeds. \n\
00079 Cancel Button: Cancel Segmentation. \n\
00080 OK Button: Accept Segmentation. ";
00081
00082 ObjectSegmentationRvizUI::ObjectSegmentationRvizUI( rviz::VisualizationManager *visualization_manager, QWidget* parent )
00083 : QWidget( parent )
00084 , object_segmentation_server_(0)
00085 , nh_("")
00086 , priv_nh_("~")
00087 , n_iter_(2)
00088 , use_gpu_(false)
00089 , object_segmenter_(0)
00090 , num_fg_hypos_(0)
00091 , running_(false)
00092 , paused_(true)
00093 , num_markers_published_(1)
00094 , current_marker_id_(1)
00095 , ui_( new Ui::MainFrame )
00096 {
00097
00098 ui_->setupUi( this );
00099
00100 render_panel_ = ui_->render_panel_;
00101 render_panel_->installEventFilter( this );
00102
00103 connect( ui_->accept_button_, SIGNAL( clicked() ), this, SLOT( acceptButtonClicked() ));
00104 connect( ui_->cancel_button_, SIGNAL( clicked() ), this, SLOT( cancelButtonClicked() ));
00105 connect( ui_->reset_button_, SIGNAL( clicked() ), this, SLOT( resetButtonClicked() ));
00106 connect( ui_->restart_button_, SIGNAL( clicked() ), this, SLOT( restartButtonClicked() ));
00107 connect( ui_->segment_button_, SIGNAL( clicked() ), this, SLOT( segmentButtonClicked() ));
00108
00109 connect( ui_->with_surface_, SIGNAL( toggled( bool )), this, SLOT( withSurfaceChecked() ));
00110 connect( ui_->with_disparity_, SIGNAL( toggled( bool )), this, SLOT( withDisparityChecked() ));
00111 connect( ui_->with_color_, SIGNAL( toggled( bool )), this, SLOT( withColorChecked() ));
00112 connect( ui_->with_holes_, SIGNAL( toggled( bool )), this, SLOT( withHolesChecked() ));
00113 connect( ui_->uniform_, SIGNAL( toggled( bool )), this, SLOT( uniformChecked() ));
00114
00115 connect( ui_->grad_weight_slider_, SIGNAL( valueChanged( int )), this, SLOT( gradWeightChanged( int )));
00116 connect( ui_->grad_weight_slider_, SIGNAL( valueChanged( int )), ui_->grad_weight_value_label_, SLOT( setNum( int )));
00117
00119
00120
00121
00122 rviz_interaction_tools::UniqueStringManager usm;
00123
00124
00125 scene_manager_ = Ogre::Root::getSingleton().createSceneManager(
00126 Ogre::ST_GENERIC, usm.unique("ObjectSegmentationRvizUI"));
00127
00128 scene_root_ = scene_manager_->getRootSceneNode()->createChildSceneNode();
00129
00130 image_overlay_ = new rviz_interaction_tools::ImageOverlay(scene_root_,
00131 Ogre::RENDER_QUEUE_OVERLAY - 2);
00132
00133
00134 setupRenderPanel(visualization_manager);
00135
00136 setWindowTitle( "Interactive Object Segmentation" );
00137 ui_->bottom_label_->setText( HELP_TEXT );
00138
00139 click_info_.down_ = false;
00140 click_info_.down_x_ = click_info_.down_y_ = 0;
00141
00142 marker_pub_ = nh_.advertise<visualization_msgs::Marker> (nh_.resolveName(
00143 "tabletop_segmentation_markers"), 10);
00144
00145 box_object_ = scene_manager_->createManualObject("SelectRegionIndicator");
00146 box_object_->setUseIdentityProjection(true);
00147 box_object_->setUseIdentityView(true);
00148 box_object_->setDynamic(true);
00149 box_object_->begin("BaseWhiteNoLighting",
00150 Ogre::RenderOperation::OT_LINE_STRIP);
00151 box_object_->position(0.0, 0.0, 0.0);
00152 box_object_->position(0.0, 0.0, 0.0);
00153 box_object_->position(0.0, 0.0, 0.0);
00154 box_object_->position(0.0, 0.0, 0.0);
00155 box_object_->index(0);
00156 box_object_->index(1);
00157 box_object_->index(2);
00158 box_object_->index(3);
00159 box_object_->index(0);
00160 box_object_->end();
00161 Ogre::AxisAlignedBox aabInf;
00162 aabInf.setInfinite();
00163 box_object_->setBoundingBox(aabInf);
00164
00165 box_object_->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY);
00166 scene_root_->attachObject(box_object_);
00167
00168 priv_nh_.param<int> ("inlier_threshold", inlier_threshold_, 300);
00169 priv_nh_.param<double> ("up_direction", up_direction_, -1.0);
00170
00171 priv_nh_.param<double> ("mean_k", mean_k_, 50.0);
00172 priv_nh_.param<double> ("std", std_, 1.0);
00173
00174 priv_nh_.param<double> ("clustering_voxel_size", clustering_voxel_size_,
00175 0.003);
00176
00177 nh_.param<double> ("grad_weight", grad_weight_, 80.0);
00178
00179 nh_.param<double> ("window_size", window_size_, 0.10);
00180
00181 nh_.param<double> ("ball_size", ball_size_, 0.10);
00182
00183 object_segmenter_ = new ObjectSegmenter(grad_weight_, n_iter_, use_gpu_,
00184 window_size_, ball_size_);
00185
00186 }
00187
00188 ObjectSegmentationRvizUI::~ObjectSegmentationRvizUI()
00189 {
00190 if (object_segmentation_server_)
00191 stopActionServer();
00192
00193 render_panel_->getRenderWindow()->setActive(false);
00194 delete render_panel_;
00195 delete image_overlay_;
00196 delete object_segmenter_;
00197 }
00198
00199 void ObjectSegmentationRvizUI::setupRenderPanel(
00200 rviz::VisualizationManager *visualization_manager )
00201 {
00202 render_panel_->initialize(scene_manager_, visualization_manager);
00203
00204 render_panel_->setAutoRender(false);
00205 render_panel_->getViewport()->setOverlaysEnabled(false);
00206 render_panel_->getViewport()->setClearEveryFrame(true);
00207 render_panel_->getRenderWindow()->setAutoUpdated(false);
00208 render_panel_->getRenderWindow()->setActive(true);
00209 }
00210
00211 void ObjectSegmentationRvizUI::startActionServer( ros::NodeHandle &node_handle )
00212 {
00213 if (object_segmentation_server_)
00214 {
00215 ROS_ERROR( "ObjectSegmentationGuiAction server already started!" );
00216 return;
00217 }
00218
00219 ROS_INFO("Starting ObjectSegmentationGuiAction server.");
00220
00221
00222 object_segmentation_server_ = new actionlib::SimpleActionServer<
00223 ObjectSegmentationGuiAction>(node_handle, "segmentation_popup", false);
00224
00225 object_segmentation_server_->registerGoalCallback(boost::bind(
00226 &ObjectSegmentationRvizUI::acceptNewGoal, this));
00227 object_segmentation_server_->registerPreemptCallback(boost::bind(
00228 &ObjectSegmentationRvizUI::preempt, this));
00229
00230 object_segmentation_server_->start();
00231 }
00232
00233 void ObjectSegmentationRvizUI::stopActionServer()
00234 {
00235 if (!object_segmentation_server_)
00236 {
00237 ROS_ERROR("ObjectSegmentationGuiAction server cannot be stopped because it is not running.");
00238 return;
00239 }
00240
00241
00242 if (object_segmentation_server_->isActive())
00243 {
00244 ROS_WARN("Aborting ObjectSegmentationGuiAction goal.");
00245 stopSegmentation();
00246 object_segmentation_server_->setAborted();
00247 cleanupAndHide();
00248 }
00249
00250 ROS_INFO("Stopping ObjectSegmentationGuiAction server.");
00251 delete object_segmentation_server_;
00252 object_segmentation_server_ = 0;
00253 }
00254
00255 void ObjectSegmentationRvizUI::acceptNewGoal()
00256 {
00257
00258
00259 ui_->accept_button_->setEnabled(running_);
00260
00261
00262
00263 ui_->restart_button_->setEnabled(!previous_queue_.empty());
00264
00265
00266 ui_->segment_button_->setEnabled(!running_);
00267
00268 const ObjectSegmentationGuiGoal::ConstPtr &goal =
00269 object_segmentation_server_->acceptNewGoal();
00270
00271 rviz_interaction_tools::updateCamera(render_panel_->getCamera(),
00272 goal->camera_info);
00273
00274 ROS_ASSERT( goal->point_cloud.height ==
00275 goal->disparity_image.image.height &&
00276 goal->point_cloud.width ==
00277 goal->disparity_image.image.width);
00278
00279 current_point_cloud_ = goal->point_cloud;
00280 current_camera_info_ = goal->camera_info;
00281 current_disparity_image_ = goal->disparity_image;
00282 fillRgbImage(current_image_, current_point_cloud_);
00283
00284
00285 float baseline = current_disparity_image_.T;
00286 table_transformer_.setParams(current_camera_info_, baseline, up_direction_);
00287
00288
00289
00290
00291 image_overlay_->setImage(current_image_);
00292 image_overlay_->update();
00293
00294 show();
00295
00296 click_info_.down_x_ = click_info_.down_y_ = 0;
00297
00298
00299 object_segmenter_->setNewData(current_image_, current_disparity_image_);
00300
00301
00302 bool with_colors, with_color_holes, uniform, with_disparities, with_surface;
00303 object_segmenter_->getCurrentSegmFlags(with_colors, with_color_holes,
00304 uniform, with_disparities, with_surface);
00305
00306 ui_->with_surface_->setChecked(with_surface);
00307 ui_->with_surface_->setEnabled(true);
00308 ui_->with_disparity_->setChecked(with_disparities);
00309 ui_->with_disparity_->setEnabled(true);
00310 ui_->with_color_->setChecked(with_colors);
00311 ui_->with_color_->setEnabled(true);
00312 ui_->with_holes_->setChecked(with_color_holes);
00313 ui_->with_holes_->setEnabled(true);
00314 ui_->uniform_->setChecked(uniform);
00315 ui_->uniform_->setEnabled(true);
00316
00317 ui_->grad_weight_slider_->setValue( int( grad_weight_ ));
00318
00319 initStorage(current_image_);
00320
00321 }
00322
00323 void ObjectSegmentationRvizUI::initStorage( const sensor_msgs::Image &image )
00324 {
00325
00326 inits_.header.frame_id = "narrow_stereo_optical_frame";
00327 inits_.header.stamp = ros::Time::now();
00328 inits_.height = image.height;
00329 inits_.width = image.width;
00330 inits_.encoding = enc::MONO8;
00331 inits_.is_bigendian = false;
00332 inits_.step = image.width;
00333 size_t size = inits_.step * inits_.height;
00334 inits_.data.resize(size);
00335
00336 texture_buffer_.header = image.header;
00337 texture_buffer_.height = image.height;
00338 texture_buffer_.width = image.width;
00339 texture_buffer_.encoding = enc::RGB8;
00340 texture_buffer_.is_bigendian = false;
00341 texture_buffer_.step = 3 * texture_buffer_.width;
00342 size = texture_buffer_.step * texture_buffer_.height;
00343 texture_buffer_.data.resize(size);
00344 }
00345
00346 void ObjectSegmentationRvizUI::preempt()
00347 {
00348 stopSegmentation();
00349 object_segmentation_server_->setPreempted();
00350 cleanupAndHide();
00351 }
00352
00353 void ObjectSegmentationRvizUI::cleanupAndHide()
00354 {
00355 image_overlay_->clear();
00356 ui_->segment_button_->setText("Segment");
00357 paused_ = true;
00358 resetVars();
00359 previous_queue_.clear();
00360 hide();
00361 }
00362
00363 void ObjectSegmentationRvizUI::stopSegmentation()
00364 {
00365 ObjectSegmenter::Action action;
00366 action.type_ = ObjectSegmenter::STOP;
00367 object_segmenter_->queueAction(action);
00368 }
00369
00370 void ObjectSegmentationRvizUI::resetVars()
00371 {
00372 for (size_t i = 0; i < clusters_.size(); ++i)
00373 clusters_[i].points.clear();
00374
00375 clusters_.clear();
00376 segm_size_.clear();
00377 table_points_.points.clear();
00378 num_fg_hypos_ = 0;
00379 color_code_.clear();
00380
00381 size_t size = inits_.step * inits_.height;
00382 inits_.data.clear();
00383 inits_.data.resize(size, 0);
00384
00385 labels_.data.clear();
00386 labels_.data.resize(size, 0);
00387
00388 image_overlay_->setImage(current_image_);
00389 image_overlay_->update();
00390
00391 region_queue_.clear();
00392
00393
00394 running_ = false;
00395 paused_ = true;
00396
00397
00398 ui_->accept_button_->setEnabled(running_);
00399
00400
00401
00402 ui_->restart_button_->setEnabled(!previous_queue_.empty());
00403
00404
00405 ui_->segment_button_->setEnabled(!running_);
00406 }
00407
00408 void ObjectSegmentationRvizUI::update( float wall_dt, float ros_dt )
00409 {
00410 render_panel_->getRenderWindow()->update();
00411
00412
00413 if (click_info_.down_)
00414 updateSelectBox(click_info_.down_x_, click_info_.down_y_, click_info_.x_,
00415 click_info_.y_);
00416 else
00417 updateSelectBox(0.0, 0.0, 0.0, 0.0);
00418
00419 if (num_fg_hypos_ > 0)
00420 {
00421 if (running_)
00422 {
00423 object_segmenter_->getCurrentResult(labels_);
00424
00425
00426
00427
00428
00429 }
00430 overlaySegmentationMask();
00431 }
00432
00433
00434
00435 ui_->restart_button_->setEnabled(!previous_queue_.empty());
00436 }
00437
00438 int ObjectSegmentationRvizUI::sumLabels( const sensor_msgs::Image &labels )
00439 {
00440 int sum = 0;
00441 for (unsigned int i = 0; i < labels.width; ++i)
00442 for (unsigned int j = 0; j < labels.height; ++j)
00443 {
00444 int adr = j * labels.width + i;
00445 sum += labels.data[adr];
00446 }
00447
00448 return sum;
00449 }
00450
00451 bool ObjectSegmentationRvizUI::eventFilter( QObject* watched_object, QEvent* event )
00452 {
00453
00454 if( watched_object != render_panel_ )
00455 {
00456 return QWidget::eventFilter( watched_object, event );
00457 }
00458
00459
00460 if( event->type() == QEvent::Wheel )
00461 {
00462 return true;
00463 }
00464
00465
00466 if( event->type() != QEvent::MouseMove &&
00467 event->type() != QEvent::MouseButtonPress &&
00468 event->type() != QEvent::MouseButtonRelease &&
00469 event->type() != QEvent::MouseButtonDblClick )
00470 {
00471 return QWidget::eventFilter( watched_object, event );
00472 }
00473
00474
00475 QMouseEvent* mevent = static_cast<QMouseEvent*>( event );
00476
00477 int x = mevent->x();
00478 int y = mevent->y();
00479
00480 x = floor(x * current_image_.width / render_panel_->width());
00481 y = floor(y * current_image_.height / render_panel_->height());
00482
00483 if( mevent->type() == QEvent::MouseButtonPress &&
00484 mevent->button() == Qt::LeftButton )
00485 {
00486 click_info_.down_ = true;
00487
00488 ROS_DEBUG("Good click at (%d,%d)", x, y);
00489 click_info_.down_x_ = x;
00490 click_info_.down_y_ = y;
00491
00492 click_info_.x_ = x;
00493 click_info_.y_ = y;
00494 }
00495 else if( mevent->type() == QEvent::MouseButtonRelease &&
00496 mevent->button() == Qt::LeftButton )
00497 {
00498 if (click_info_.down_x_ > click_info_.x_)
00499 swap(click_info_.down_x_, click_info_.x_);
00500
00501 if (click_info_.down_y_ > click_info_.y_)
00502 swap(click_info_.down_y_, click_info_.y_);
00503
00504 float dist_clicks = dist(click_info_.down_x_, click_info_.down_y_,
00505 click_info_.x_, click_info_.y_);
00506
00507 ObjectSegmenter::Action action;
00508
00509 Point tl;
00510 tl.x = click_info_.down_x_;
00511 tl.y = click_info_.down_y_;
00512
00513 Point br;
00514
00515 if (click_info_.dragged_ && dist_clicks > 2)
00516 {
00517
00518 br.x = click_info_.x_;
00519 br.y = click_info_.y_;
00520
00521 click_info_.dragged_ = false;
00522 action.type_ = ObjectSegmenter::REGION;
00523
00524 } else
00525 {
00526
00527 br.x = -1;
00528 br.y = -1;
00529
00530 click_info_.dragged_ = false;
00531 action.type_ = ObjectSegmenter::CLICK;
00532 }
00533
00534 ObjectSegmenter::Box2D region;
00535 region.p_tl_ = tl;
00536 region.p_br_ = br;
00537
00538 if (!running_ && region_queue_.size() < MAX_FG)
00539 {
00540 region_queue_.push_back(region);
00541 previous_queue_.push_back(region);
00542 addToMasks(region);
00543 num_fg_hypos_++;
00544 addColorCode();
00545 } else if (num_fg_hypos_ < MAX_FG)
00546 {
00547 previous_queue_.push_back(region);
00548 action.box_ = region;
00549 object_segmenter_->queueAction(action);
00550 num_fg_hypos_++;
00551 addColorCode();
00552 }
00553 else ROS_WARN("Maximum Number of Segments reached.");
00554
00555 click_info_.down_ = false;
00556
00557 }
00558 else if( mevent->type() == QEvent::MouseMove &&
00559 mevent->buttons() == Qt::LeftButton )
00560 {
00561 if (click_info_.down_)
00562 {
00563 click_info_.dragged_ = true;
00564
00565 click_info_.x_ = x;
00566 click_info_.y_ = y;
00567 }
00568 }
00569
00570
00571 return true;
00572 }
00573
00574 void ObjectSegmentationRvizUI::addColorCode()
00575 {
00576
00577
00578 int zero = rand()&2;
00579 for(int i=0; i<3; i++)
00580 if(i==zero)
00581 color_code_.push_back(0);
00582 else
00583 color_code_.push_back(rand()&255);
00584 }
00585
00586 void ObjectSegmentationRvizUI::addToMasks(const ObjectSegmenter::Box2D &select_)
00587 {
00588
00589 int w = inits_.width;
00590
00591 int size = 0;
00592
00593
00594 if(!(select_.p_br_.x == -1 && select_.p_br_.y == -1))
00595 {
00596
00597 for(int y=select_.p_tl_.y; y<select_.p_br_.y; ++y)
00598 {
00599 for(int x=select_.p_tl_.x; x<select_.p_br_.x; ++x)
00600 {
00601 int i = y*w + x;
00602 inits_.data[i]=num_fg_hypos_ + 2;
00603 size ++;
00604 }
00605 }
00606
00607 ROS_DEBUG("Added rectangle of size %d", size);
00608
00609 } else
00610 {
00611
00612
00613 int radius = 10;
00614
00615 for(int y=select_.p_tl_.y-radius; y<select_.p_tl_.y+radius; ++y)
00616 {
00617 for(int x=select_.p_tl_.x-radius; x<select_.p_tl_.x+radius; ++x)
00618 {
00619
00620 if(dist((int)select_.p_tl_.x, (int)select_.p_tl_.y, x, y)<=radius)
00621 {
00622 int i = y*w + x;
00623 inits_.data[i]=num_fg_hypos_ + 2;
00624 size++;
00625 }
00626 }
00627 }
00628
00629 ROS_DEBUG("Added circle of size %d", size);
00630 }
00631 }
00632
00633 void ObjectSegmentationRvizUI::fillRgbImage(sensor_msgs::Image &rgb_img,
00634 const sensor_msgs::PointCloud2 &point_cloud)
00635 {
00636
00637 ROS_DEBUG("Width and Height: (%d %d)",point_cloud.height, point_cloud.width );
00638
00639 rgb_img.header = point_cloud.header;
00640 rgb_img.height = point_cloud.height;
00641 rgb_img.width = point_cloud.width;
00642 rgb_img.encoding = enc::RGB8;
00643 rgb_img.is_bigendian = false;
00644 rgb_img.step = 3 * rgb_img.width;
00645 size_t size = rgb_img.step * rgb_img.height;
00646 rgb_img.data.resize(size);
00647
00648 for(unsigned int x=0; x<rgb_img.width; ++x)
00649 {
00650 for(unsigned int y=0; y<rgb_img.height; ++y)
00651 {
00652 int i = y * rgb_img.width + x;
00653
00654 float rgb;
00655 memcpy ( &rgb, &point_cloud.data[i * point_cloud.point_step + point_cloud.fields[3].offset], sizeof (float));
00656 float r, g, b;
00657 transformRgb(rgb, r, g, b);
00658
00659 int wide_i = y * rgb_img.step + x*3;
00660 rgb_img.data[wide_i+0] = round(r*255.0f);
00661 rgb_img.data[wide_i+1] = round(g*255.0f);
00662 rgb_img.data[wide_i+2] = round(b*255.0f);
00663
00664 }
00665 }
00666 }
00667
00668 void ObjectSegmentationRvizUI::overlaySegmentationMask()
00669 {
00670
00671 sensor_msgs::Image::ConstPtr overlay_ptr;
00672
00673 if( !running_)
00674 {
00675 overlay_ptr = boost::make_shared<const sensor_msgs::Image> (inits_);
00676 } else
00677 {
00678 overlay_ptr = boost::make_shared<const sensor_msgs::Image> (labels_);
00679 }
00680
00681
00682
00683
00684
00685
00686 int count = 0;
00687
00688 int w = current_image_.width;
00689 int h = current_image_.height;
00690
00691 for (int i=0; i<h; i++)
00692 {
00693 for (int j=0; j<w; j++)
00694 {
00695 unsigned int adr = i *w + j;
00696
00697 int label = (int)(overlay_ptr->data[adr]);
00698
00699 for(int c=0; c<3; c++)
00700 {
00701 uint8_t val;
00702
00703 if(label>1)
00704 {
00705
00706
00707 ROS_ASSERT(label-2<num_fg_hypos_);
00708 ROS_ASSERT(3 * (label-2) + c<(int)color_code_.size());
00709 if( color_code_.at(3 * (label-2) + c)==0)
00710 val = current_image_.data[3 * adr + c];
00711 else
00712 val = color_code_.at(3 * (label-2) + c);
00713
00714 count ++;
00715
00716 }
00717
00718
00719
00720
00721 else
00722 {
00723 val = current_image_.data[3 * adr + c];
00724 }
00725
00726 texture_buffer_.data.at( 3 * adr + c ) = val;
00727 }
00728 }
00729 }
00730
00731 image_overlay_->setImage(texture_buffer_);
00732 image_overlay_->update();
00733 }
00734
00735 void ObjectSegmentationRvizUI::updateSelectBox(int start_x,
00736 int start_y,
00737 int stop_x,
00738 int stop_y)
00739 {
00740
00741 if(start_x>stop_x)
00742 swap(start_x, stop_x);
00743
00744 if(start_y>stop_y)
00745 swap(start_y, stop_y);
00746
00747 float x0 = start_x / ((float)current_image_.width / 2.0 ) - 1.0;
00748 float y0 = - (start_y / ((float)current_image_.height / 2.0 ) - 1.0);
00749
00750 float x1 = stop_x / ((float)current_image_.width / 2.0 ) - 1.0;
00751 float y1 = - (stop_y / ((float)current_image_.height / 2.0 ) - 1.0);
00752
00753 box_object_->beginUpdate(0);
00754 box_object_->position(x0, y0, 0.0);
00755 box_object_->position(x0, y1, 0.0);
00756 box_object_->position(x1, y1, 0.0);
00757 box_object_->position(x1, y0, 0.0);
00758 box_object_->index(0);
00759 box_object_->index(1);
00760 box_object_->index(2);
00761 box_object_->index(3);
00762 box_object_->index(0);
00763 box_object_->end();
00764 }
00765
00766 void ObjectSegmentationRvizUI::acceptButtonClicked()
00767 {
00768 if( !running_) return;
00769
00770 ObjectSegmentationGuiResult result;
00771
00772 while(!object_segmenter_->getCurrentResult( labels_))
00773 {
00774 ROS_INFO("Waiting for final labeling");
00775 }
00776 float alpha, beta, gamma;
00777 object_segmenter_->getCurrentSurface( alpha, beta, gamma);
00778
00779
00780 stopSegmentation();
00781
00782 getClusterSize();
00783
00784 if ( segm_size_[0] < (int)inlier_threshold_)
00785 {
00786 ROS_INFO("Plane detection has %d inliers, below min threshold of %d",
00787 segm_size_[0],
00788 inlier_threshold_);
00789 result.result = result.NO_TABLE;
00790 return;
00791 }
00792
00793 for(int i=1; i<(int)segm_size_.size(); ++i)
00794 if(segm_size_[i] == 0)
00795 {
00796 ROS_INFO("Segment %d has 0 points.", segm_size_[i]);
00797 num_fg_hypos_--;
00798 }
00799
00800 reconstructAndClusterPointCloud(result);
00801
00802
00803 tabletop_object_detector::Table table = table_transformer_.get3DTable(alpha, beta, gamma, table_points_,
00804 clusters_[0].header);
00805 result.table = table;
00806
00807 result.result = result.SUCCESS;
00808
00809 ROS_INFO("ObjectSegmentation was successful.");
00810
00811 object_segmentation_server_->setSucceeded(result);
00812
00813 cleanupAndHide();
00814 }
00815
00816 void ObjectSegmentationRvizUI::cancelButtonClicked()
00817 {
00818 stopSegmentation();
00819 object_segmentation_server_->setAborted();
00820 cleanupAndHide();
00821 }
00822
00823 void ObjectSegmentationRvizUI::resetButtonClicked()
00824 {
00825 reset( );
00826 previous_queue_.clear();
00827 }
00828
00829 void ObjectSegmentationRvizUI::reset( )
00830 {
00831 ObjectSegmenter::Action action;
00832 action.type_ = ObjectSegmenter::RESET;
00833 includeFlags(action);
00834 object_segmenter_->queueAction(action);
00835 image_overlay_->clear();
00836
00837 ui_->segment_button_->setText("Segment");
00838 paused_ = true;
00839
00840 resetVars();
00841 }
00842
00843 void ObjectSegmentationRvizUI::restartButtonClicked()
00844 {
00845
00846 reset();
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856 for(int i=0; i<(int)previous_queue_.size();++i)
00857 {
00858 if( num_fg_hypos_ < MAX_FG )
00859 {
00860 region_queue_.push_back(previous_queue_[i]);
00861 addToMasks(previous_queue_[i]);
00862 num_fg_hypos_++;
00863 addColorCode();
00864 } else
00865 {
00866 ROS_INFO("Maximum number of segments reached");
00867 }
00868 }
00869
00870 segment();
00871
00872 ui_->segment_button_->setText("Pause");
00873 paused_ = false;
00874 }
00875
00876 void ObjectSegmentationRvizUI::includeFlags( ObjectSegmenter::Action &ac)
00877 {
00878
00879 ac.with_colors_ = ui_->with_color_->isChecked();
00880 ac.with_color_holes_ = ui_->with_holes_->isChecked();
00881 ac.uniform_ = ui_->uniform_->isChecked();
00882 ac.with_disparities_ = ui_->with_disparity_->isChecked();
00883 ac.with_surface_ = ui_->with_surface_->isChecked();
00884
00885 }
00886
00887 void ObjectSegmentationRvizUI::segmentButtonClicked()
00888 {
00889 if(paused_)
00890 {
00891 segment();
00892 ui_->segment_button_->setText("Pause");
00893 paused_ = false;
00894 } else
00895 {
00896
00897 ObjectSegmenter::Action action;
00898 action.type_ = ObjectSegmenter::PAUSE;
00899 object_segmenter_->queueAction(action);
00900 ui_->segment_button_->setText("Segment");
00901 paused_ = true;
00902 }
00903 }
00904
00905 void ObjectSegmentationRvizUI::segment()
00906 {
00907
00908 if(region_queue_.empty())
00909 {
00910
00911 ObjectSegmenter::Action action;
00912 ObjectSegmenter::Box2D dummy;
00913 dummy.p_tl_.x = -1;
00914 dummy.p_tl_.y = -1;
00915 dummy.p_br_.x = -1;
00916 dummy.p_br_.y = -1;
00917 action.type_ = ObjectSegmenter::CLICK;
00918 action.box_ = dummy;
00919 object_segmenter_->queueAction(action);
00920
00921 } else
00922 {
00923 while(!region_queue_.empty())
00924 {
00925 ObjectSegmenter::Action action;
00926 if(region_queue_[0].p_br_.x==-1 && region_queue_[0].p_br_.y==-1)
00927 {
00928 action.type_ = ObjectSegmenter::CLICK;
00929 } else
00930 {
00931 action.type_ = ObjectSegmenter::REGION;
00932 }
00933
00934 action.box_ = region_queue_[0];
00935
00936 object_segmenter_->queueAction(action);
00937 region_queue_.pop_front();
00938 }
00939 }
00940
00941 running_=true;
00942
00943 ui_->accept_button_->setEnabled(running_);
00944
00945
00946
00947 ui_->restart_button_->setEnabled(!previous_queue_.empty());
00948
00949 }
00950
00951 void ObjectSegmentationRvizUI::withSurfaceChecked()
00952 { reset();}
00953
00954 void ObjectSegmentationRvizUI::withDisparityChecked()
00955 {
00956 if(!ui_->with_disparity_->isChecked())
00957 {
00958 ui_->with_color_->setChecked(true);
00959 ui_->with_holes_->setEnabled(true);
00960 ui_->uniform_->setEnabled(true);
00961 }
00962 reset();
00963 }
00964
00965 void ObjectSegmentationRvizUI::withColorChecked()
00966 {
00967 if(!ui_->with_color_->isChecked())
00968 {
00969 ui_->with_disparity_->setChecked(true);
00970 ui_->with_holes_->setEnabled(false);
00971 ui_->uniform_->setEnabled(false);
00972 } else
00973 {
00974 ui_->with_holes_->setEnabled(true);
00975 ui_->uniform_->setEnabled(true);
00976 }
00977
00978 reset();
00979 }
00980
00981 void ObjectSegmentationRvizUI::withHolesChecked()
00982 { reset();}
00983
00984 void ObjectSegmentationRvizUI::uniformChecked()
00985 { reset();}
00986
00987 void ObjectSegmentationRvizUI::gradWeightChanged( int new_value )
00988 {
00989 grad_weight_ = (double) new_value;
00990 ObjectSegmenter::Action action;
00991 action.type_ = ObjectSegmenter::GRADCHANGE;
00992 action.grad_weight_ = grad_weight_;
00993 object_segmenter_->queueAction(action);
00994 }
00995
00996 void ObjectSegmentationRvizUI::getClusterSize()
00997 {
00998 int w = labels_.width;
00999 int h = labels_.height;
01000
01001
01002 segm_size_.resize(num_fg_hypos_+1,0);
01003
01004 for (int i=0; i<h; i++)
01005 {
01006 for (int j=0; j<w; j++)
01007 {
01008
01009 unsigned int adr = i *w + j;
01010 unsigned int label = labels_.data[adr];
01011
01012 if(rviz_interaction_tools::hasDisparityValue(current_disparity_image_,
01013 i, j))
01014 {
01015 if(label>1)
01016 segm_size_.at(label-1)++;
01017 else if(label==1)
01018 segm_size_.at(0)++;
01019 }
01020 }
01021 }
01022 }
01023
01024 void ObjectSegmentationRvizUI::reconstructAndClusterPointCloud( ObjectSegmentationGuiResult &result)
01025 {
01026 clusters_.clear();
01027 clusters_.resize(num_fg_hypos_);
01028 for(int i=0; i<num_fg_hypos_; ++i)
01029 {
01030 clusters_[i].header.frame_id = current_point_cloud_.header.frame_id;
01031 clusters_[i].header.stamp = ros::Time::now();
01032 clusters_[i].points.reserve(segm_size_[i+1]);
01033 }
01034
01035 table_points_.header.frame_id = current_point_cloud_.header.frame_id;
01036 table_points_.header.stamp = ros::Time::now();
01037 table_points_.points.reserve(segm_size_[0]);
01038
01039 int nan_cluster =0;
01040
01041 for(unsigned int x=0; x<current_point_cloud_.width; ++x)
01042 {
01043 for(unsigned int y=0; y<current_point_cloud_.height; ++y)
01044 {
01045 int i = y * current_point_cloud_.width + x;
01046 float nan;
01047 memcpy (&nan,
01048 ¤t_point_cloud_.data[i * current_point_cloud_.point_step + current_point_cloud_.fields[0].offset],
01049 sizeof (float));
01050 if(!isnan(nan))
01051 {
01052 geometry_msgs::Point32 p;
01053 float x, y, z;
01054 memcpy (&x,
01055 ¤t_point_cloud_.data[i
01056 * current_point_cloud_.point_step
01057 + current_point_cloud_.fields[0].offset],
01058 sizeof (float));
01059 memcpy (&y,
01060 ¤t_point_cloud_.data[i
01061 * current_point_cloud_.point_step
01062 + current_point_cloud_.fields[1].offset],
01063 sizeof (float));
01064 memcpy (&z,
01065 ¤t_point_cloud_.data[i
01066 * current_point_cloud_.point_step
01067 + current_point_cloud_.fields[2].offset],
01068 sizeof (float));
01069 p.x = x;
01070 p.y = y;
01071 p.z = z;
01072
01073 unsigned int label = labels_.data[i];
01074 if(label>1)
01075 {
01076 clusters_[label-2].points.push_back( p );
01077 } else if(label==1)
01078 {
01079 table_points_.points.push_back( p );
01080 }
01081 } else
01082 {
01083 nan_cluster++;
01084 }
01085 }
01086 }
01087
01088 filterOutliersAndDownsample(clusters_);
01089
01090 result.clusters = clusters_;
01091 }
01092
01093 void ObjectSegmentationRvizUI::filterOutliersAndDownsample(std::vector<sensor_msgs::PointCloud> &clusters)
01094 {
01095 std::vector<sensor_msgs::PointCloud> filtered_clusters;
01096 filtered_clusters.reserve(clusters.size());
01097
01098 for (size_t i=0; i<clusters.size(); i++)
01099 {
01100
01101
01102 sensor_msgs::PointCloud2 converted_cloud;
01103 sensor_msgs::convertPointCloudToPointCloud2(clusters[i], converted_cloud);
01104
01105 pcl::PointCloud<PCL_Point> cloud_t;
01106 pcl::fromROSMsg (converted_cloud, cloud_t);
01107 pcl::PointCloud<PCL_Point>::ConstPtr cloud_ptr
01108 = boost::make_shared<const pcl::PointCloud<PCL_Point> > (cloud_t);
01109
01110
01111 pcl::StatisticalOutlierRemoval<PCL_Point> sor;
01112 sor.setInputCloud (cloud_ptr);
01113 sor.setMeanK (mean_k_);
01114 sor.setStddevMulThresh (std_);
01115 pcl::PointCloud<PCL_Point>::Ptr
01116 cloud_filtered(new pcl::PointCloud<PCL_Point> ());
01117 sor.filter (*cloud_filtered);
01118
01119
01120 sensor_msgs::PointCloud2 filt_converted_cloud;
01121 pcl::toROSMsg ( *cloud_filtered, filt_converted_cloud);
01122 sensor_msgs::PointCloud2::ConstPtr filt_converted_cloud_ptr
01123 = boost::make_shared<const sensor_msgs::PointCloud2> (filt_converted_cloud);
01124
01125
01126 pcl::VoxelGrid<sensor_msgs::PointCloud2> dvx;
01127 dvx.setInputCloud(filt_converted_cloud_ptr);
01128 dvx.setLeafSize (clustering_voxel_size_,
01129 clustering_voxel_size_,
01130 clustering_voxel_size_);
01131 sensor_msgs::PointCloud2::Ptr
01132 cloud_downsampled(new sensor_msgs::PointCloud2());
01133 dvx.filter (*cloud_downsampled);
01134
01135 sensor_msgs::PointCloud cloud_tmp;
01136 sensor_msgs::convertPointCloud2ToPointCloud(*cloud_downsampled, cloud_tmp);
01137
01138 filtered_clusters.push_back(cloud_tmp);
01139 }
01140
01141 clusters.clear();
01142 clusters = filtered_clusters;
01143
01144 }
01145
01146 }