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 "object_segmentation_gui/object_segmenter.h"
00031
00032 #include "active_realtime_segmentation/pyra/tpimageutil.h"
00033 #include <sensor_msgs/image_encodings.h>
00034 #include "rviz_interaction_tools/image_tools.h"
00035
00036
00037
00038 namespace enc = sensor_msgs::image_encodings;
00039
00040
00041
00042
00043 namespace object_segmentation_gui {
00044
00045 ObjectSegmenter::ObjectSegmenter( float grad_weight, int n_iter,
00046 bool use_gpu, float w_size,
00047 float b_size)
00048 : w_(640)
00049 , h_(480)
00050 , grad_weight_(grad_weight)
00051 , window_size_(w_size)
00052 , ball_size_(b_size)
00053 , use_gpu_(use_gpu)
00054 , n_iter_(n_iter)
00055 , init_(true)
00056 , num_fg_hypos_(0)
00057 , fgbgsegment(0)
00058 , gpu_image( w_, h_)
00059 , gpu_disparities( w_, h_)
00060 , init_mask( w_, h_)
00061 , segm_mask( w_, h_)
00062 , thread_(0)
00063 {}
00064
00065 ObjectSegmenter::~ObjectSegmenter()
00066 {
00067 if(thread_!=0){
00068 stopThread();
00069 thread_->join();
00070 delete thread_;
00071 thread_=0;
00072 }
00073
00074 if(fgbgsegment!=0){
00075 delete fgbgsegment;
00076 }
00077
00078 }
00079
00080 void ObjectSegmenter::setNewData( const sensor_msgs::Image &image,
00081 const stereo_msgs::DisparityImage &disparity)
00082 {
00083 stereo_msgs::DisparityImage local_disp = disparity;
00084
00085
00086 w_ = image.width;
00087 h_ = image.height;
00088 drange_ = disparity.max_disparity - disparity.min_disparity;
00089 ROS_DEBUG("Image Width %d, Image Height %d", w_, h_);
00090 ROS_DEBUG("Disparity Range %d", drange_);
00091 ROS_DEBUG("Disparity steps %f", disparity.delta_d);
00092 ROS_DEBUG("Min and Max Disparity %f %f",
00093 disparity.min_disparity, disparity.max_disparity);
00094
00095
00096
00097
00098 for(int x=0; x<w_; ++x){
00099 for(int y=0; y<h_; ++y){
00100 if(!rviz_interaction_tools::hasDisparityValue(disparity, y, x)){
00101 float val;
00102 rviz_interaction_tools::getValue(disparity.image, y, x, val);
00103 val =- disparity.min_disparity;
00104 rviz_interaction_tools::setValue(local_disp.image, y, x, -1.0f);
00105 }
00106 }
00107 }
00108
00109
00110 gpu_image.SetDataAlign(image, 3*w_, h_, true);
00111 gpu_disparities.SetDataAlign(local_disp.image, w_, h_);
00112
00113
00114
00115 init_mask.SetSize(w_,h_);
00116 segm_mask.SetSize(w_,h_);
00117
00118 Fill(init_mask, (uchar)0);
00119 Fill(segm_mask, (uchar)0);
00120
00121 if(fgbgsegment!=0)
00122 delete fgbgsegment;
00123 fgbgsegment = new FgBgSegment(w_, h_, drange_, grad_weight_,
00124 window_size_, ball_size_);
00125
00126 #ifdef USE_CUDA
00127 fgbgsegment->UseGPU(use_gpu_);
00128 #else
00129 if(use_gpu_)
00130 ROS_WARN("CUDA support not enabled! Running segmentation on CPU.");
00131 fgbgsegment->UseGPU(false);
00132
00133 #endif //USE_CUDA
00134
00135
00136 init_ = true;
00137
00138 startThread( boost::bind( &ObjectSegmenter::doSegment, this) );
00139 }
00140
00141 void ObjectSegmenter::queueAction( const Action &action)
00142 {
00143 boost::mutex::scoped_lock lock(queue_mutex_);
00144 if(action.type_==STOP)
00145 action_queue_.clear();
00146 action_queue_.push_back(action);
00147 cond_var_.notify_all();
00148
00149 }
00150
00151
00152 bool ObjectSegmenter::dequeueAction( Action &action)
00153 {
00154
00155 boost::mutex::scoped_lock lock(queue_mutex_);
00156
00157 if(!action_queue_.empty()){
00158 action = action_queue_[0];
00159 action_queue_.pop_front();
00160 return true;
00161 } else {
00162 return false;
00163 }
00164
00165 }
00166
00167 void ObjectSegmenter::clearQueue()
00168 {
00169 boost::mutex::scoped_lock lock(queue_mutex_);
00170 action_queue_.clear();
00171 }
00172
00173 void ObjectSegmenter::waitForAction(){
00174
00175 boost::mutex::scoped_lock q_lock(queue_mutex_);
00176
00177 while(init_ && action_queue_.empty()){
00178 cond_var_.wait(q_lock);
00179 }
00180 }
00181
00182 void ObjectSegmenter::pause()
00183 {
00184 ROS_INFO("Entering pause");
00185 boost::mutex::scoped_lock q_lock(queue_mutex_);
00186 ROS_INFO("Before pause condition variable waiting");
00187 cond_var_.wait(q_lock);
00188 ROS_INFO("After pause condition variable waiting");
00189
00190 }
00191
00192 bool ObjectSegmenter::getCurrentResult( sensor_msgs::Image &image)
00193 {
00194
00195 boost::mutex::scoped_lock lock(image_mutex_);
00196 fillImage(image, segm_mask);
00197 return true;
00198
00199 }
00200
00201
00202 void ObjectSegmenter::setCurrentResult( )
00203 {
00204 boost::mutex::scoped_lock lock(image_mutex_);
00205 fgbgsegment->MakeSegmentImage(segm_mask);
00206 fgbgsegment->GetSurfaceParameters( alpha_, beta_, gamma_);
00207 }
00208
00209 bool ObjectSegmenter::validResult( const Image<uint8_t> &segm_mask)
00210 {
00211 boost::mutex::scoped_lock lock(image_mutex_);
00212
00213 int w = segm_mask.GetWidth();
00214 int h = segm_mask.GetHeight();
00215
00216 uint8_t *segm_d = segm_mask.GetData();
00217
00218 std::vector<int> segm_size;
00219 segm_size.resize(num_fg_hypos_+1,0);
00220
00221 for(int i=0; i<w; ++i)
00222 for(int j=0; j<h; ++j){
00223 int adr = j*w+i;
00224 int label = segm_d[adr];
00225 if(label>1)
00226 segm_size[label-1]++;
00227 else if (label==1)
00228 segm_size[0]++;
00229 }
00230
00231 int sum = 0;
00232 for(int i=1; i<(int)segm_size.size(); ++i)
00233 sum += segm_size[i];
00234
00235 if((int)segm_size.size()>1 && sum==0)
00236 return false;
00237 else
00238 return true;
00239 }
00240
00241 void ObjectSegmenter::getCurrentSurface(float &alpha, float &beta,
00242 float &gamma)
00243 {
00244 boost::mutex::scoped_lock lock(image_mutex_);
00245 alpha = alpha_;
00246 beta = beta_;
00247 gamma = gamma_;
00248 }
00249
00250 void ObjectSegmenter::getCurrentSegmFlags( bool &with_colors,
00251 bool &with_color_holes,
00252 bool &uniform,
00253 bool &with_disparities,
00254 bool &with_surface )
00255 {
00256 with_colors = fgbgsegment->GetWithColors();
00257 with_color_holes = fgbgsegment->GetWithColorHoles();
00258 uniform = fgbgsegment->GetUniform();
00259 with_disparities = fgbgsegment->GetWithDisparities();
00260 with_surface = fgbgsegment->GetWithSurface();
00261 }
00262
00263 void ObjectSegmenter::setCurrentSegmFlags( bool with_colors,
00264 bool with_color_holes,
00265 bool uniform,
00266 bool with_disparities,
00267 bool with_surface )
00268 {
00269 fgbgsegment->SetWithColors(with_colors);
00270 fgbgsegment->SetWithColorHoles(with_color_holes);
00271 fgbgsegment->SetUniform(uniform);
00272 fgbgsegment->SetWithDisparities(with_disparities);
00273 fgbgsegment->SetWithSurface(with_surface);
00274 }
00275
00276
00277 void ObjectSegmenter::doSegment()
00278 {
00279
00280 bool stop = false;
00281
00282 while(true){
00283
00284
00285 waitForAction();
00286
00287 fgbgsegment->Execute(gpu_image, gpu_disparities, init_, n_iter_);
00288 if(init_)
00289 init_ = false;
00290
00291 setCurrentResult();
00292
00293 Action ac;
00294 if( dequeueAction(ac) ){
00295 switch(ac.type_){
00296 case REGION:
00297 fillInitMask(init_mask, ac.box_.p_tl_.x, ac.box_.p_tl_.y,
00298 ac.box_.p_br_.x, ac.box_.p_br_.y);
00299 fgbgsegment->SetNewForeground(init_mask, gpu_disparities, drange_);
00300 num_fg_hypos_++;
00301 break;
00302 case CLICK:
00303 if( !(ac.box_.p_tl_.x==-1 && ac.box_.p_tl_.y==-1)){
00304 fgbgsegment->SetNewForeground( ac.box_.p_tl_.x, ac.box_.p_tl_.y,
00305 gpu_disparities, drange_);
00306 num_fg_hypos_++;
00307 }
00308 break;
00309 case RESET:
00310 setCurrentSegmFlags(ac.with_colors_,
00311 ac.with_color_holes_,
00312 ac.uniform_,
00313 ac.with_disparities_,
00314 ac.with_surface_);
00315 init_ = true;
00316 Fill(init_mask, (uchar)0);
00317 Fill(segm_mask, (uchar)0);
00318 break;
00319 case GRADCHANGE:
00320 fgbgsegment->SetGradWeight( ac.grad_weight_);
00321 break;
00322 case STOP:
00323 stop = true;
00324 clearQueue();
00325 break;
00326 case PAUSE:
00327 pause();
00328 break;
00329 }
00330 }
00331
00332 if(stop)
00333 break;
00334 }
00335
00336 }
00337
00338 template <typename Callable>
00339 void ObjectSegmenter::startThread( Callable f )
00340 {
00341 if ( thread_ != 0) {
00342 thread_->join();
00343 delete thread_;
00344 }
00345 thread_ = new boost::thread( f );
00346 }
00347
00348 void ObjectSegmenter::stopThread(){
00349
00350 ObjectSegmenter::Action action;
00351 action.type_ = ObjectSegmenter::STOP;
00352 queueAction(action);
00353 }
00354
00355
00356 void ObjectSegmenter::fillInitMask( Image<uint8_t> &init_mask,
00357 int start_x, int start_y,
00358 int stop_x, int stop_y){
00359
00360 uint8_t *init_d = init_mask.GetData();
00361 Fill(init_mask, (uchar)0);
00362
00363 if(start_x>stop_x)
00364 swap(start_x, stop_x);
00365
00366 if(start_y>stop_y)
00367 swap(start_y, stop_y);
00368
00369 for(int y=start_y; y<stop_y; ++y){
00370 for(int x=start_x; x<stop_x; ++x){
00371 int i = y*w_ + x;
00372 init_d[i] = 1;
00373 }
00374 }
00375 }
00376
00377
00378 void ObjectSegmenter::fillImage(sensor_msgs::Image &image,
00379 const Image<uint8_t> &segm_mask)
00380 {
00381 uint8_t *segm_d = segm_mask.GetData();
00382
00383 image.header.frame_id = "narrow_stereo_optical_frame";
00384 image.header.stamp = ros::Time::now();
00385 image.height = segm_mask.GetHeight();
00386 image.width = segm_mask.GetWidth();
00387 image.encoding = enc::MONO8;
00388 image.is_bigendian = false;
00389 image.step = segm_mask.GetWidth();
00390 size_t size = image.step * image.height;
00391 image.data.resize(size);
00392
00393 for(unsigned int x=0; x<image.width; ++x){
00394 for(unsigned int y=0; y<image.height; ++y){
00395 int i = y * image.width + x;
00396 image.data[i] = segm_d[i];
00397 }
00398 }
00399 }
00400
00401
00402 }
00403