00001 #include "shape_reconstruction/ShapeReconstruction.h"
00002
00003 #include <pcl/conversions.h>
00004 #include <pcl/io/pcd_io.h>
00005 #include <pcl/filters/filter_indices.h>
00006 #include <sensor_msgs/Image.h>
00007
00008 #include <opencv2/imgproc/imgproc.hpp>
00009 #include <opencv2/video/tracking.hpp>
00010 #include <opencv2/highgui/highgui.hpp>
00011 #include <opencv2/video/tracking.hpp>
00012
00013 #include <pcl_conversions/pcl_conversions.h>
00014
00015 #include <ros/package.h>
00016
00017 #include <cmath>
00018
00019 #include <ros/console.h>
00020
00021 #include "shape_reconstruction/RangeImagePlanar.hpp"
00022
00023 #include "shape_reconstruction/Passthrough.hpp"
00024
00025 #include <pcl/point_cloud.h>
00026 #include <pcl/point_types.h>
00027 #include <pcl/io/pcd_io.h>
00028 #include <pcl/visualization/pcl_visualizer.h>
00029 #include <pcl/filters/passthrough.h>
00030
00031 #include <boost/lexical_cast.hpp>
00032 #include <sensor_msgs/image_encodings.h>
00033
00034 #include <pcl/point_types_conversion.h>
00035
00036 #include <pcl/registration/icp.h>
00037
00038 #include <pcl/common/centroid.h>
00039
00040 #include <pcl/surface/poisson.h>
00041 #include <pcl/surface/mls.h>
00042
00043 #include <math.h>
00044
00045 using namespace omip;
00046
00047 ShapeReconstruction::ShapeReconstruction()
00048 :
00049 _accumulate_change_candidates(true),
00050 _min_depth_change(0.08),
00051 _remove_inconsistent_points(true),
00052 _t(0),
00053 _extend_to_neighbor_sv(false),
00054 _acc_candidates_of_current(IMG_HEIGHT, IMG_WIDTH, CV_8UC1),
00055 _similarity_in_normal(0),
00056 _similarity_in_h(0)
00057 {
00058
00059 this->_acc_candidates_of_current.setTo(0);
00060
00061
00062 this->_rip_temp = pcl::RangeImagePlanar::Ptr(new pcl::RangeImagePlanar());
00063
00064
00065 this->_moving_pts_of_current_idx_depth = pcl::PointIndices::Ptr(new pcl::PointIndices ());
00066 this->_moving_pts_of_previous_idx_depth = pcl::PointIndices::Ptr(new pcl::PointIndices ());
00067 this->_out_of_view_pts_of_current_idx= pcl::PointIndices::Ptr(new pcl::PointIndices ());
00068 this->_occluded_pts_of_current_idx= pcl::PointIndices::Ptr(new pcl::PointIndices ());
00069
00070 this->_moving_pts_of_current_idx_color = pcl::PointIndices::Ptr(new pcl::PointIndices ());
00071 this->_moving_pts_of_previous_idx_color = pcl::PointIndices::Ptr(new pcl::PointIndices ());
00072
00073 this->_knn = pcl::search::Search<omip::SRPoint>::Ptr(new pcl::search::KdTree<omip::SRPoint>);
00074
00075 this->_rb_shape = omip::SRPointCloud::Ptr(new omip::SRPointCloud);
00076 this->_rb_shape->height=1;
00077
00078 this->_supporting_features = pcl::PointCloud<pcl::PointXYZL>::Ptr(new pcl::PointCloud<pcl::PointXYZL>());
00079
00080 this->_candidates = SRPointCloud::Ptr(new SRPointCloud);
00081 this->_candidates->height=1;
00082
00083 this->_candidates_in_current = SRPointCloud::Ptr(new SRPointCloud);
00084
00085 this->_rb_segment.reset(new SRPointCloud);
00086
00090 this->_rb_polygon_data_ptr = vtkSmartPointer<vtkPolyData>::New ();
00091 this->_rb_normal_estimator_ptr.reset(new pcl::NormalEstimationOMP<omip::SRPoint, pcl::Normal>());
00092 this->_rb_normal_estimator_ptr->setKSearch (50);
00093 this->_rb_estimated_normals_pc_ptr.reset(new pcl::PointCloud<pcl::Normal>());
00094 this->_rb_tree_for_normal_estimation_ptr.reset(new pcl::search::KdTree<omip::SRPoint>());
00095 this->_rb_position_color_and_normals_pc_ptr.reset(new pcl::PointCloud<pcl::PointXYZRGBNormal>());
00096 this->_rb_tree_for_triangulation_ptr.reset(new pcl::search::KdTree<pcl::PointXYZRGBNormal>());
00097 this->_rb_greedy_projection_triangulator_ptr.reset(new pcl::GreedyProjectionTriangulation<pcl::PointXYZRGBNormal>());
00098
00099 this->_rb_greedy_projection_triangulator_ptr->setMu (2.5);
00100 this->_rb_greedy_projection_triangulator_ptr->setMaximumNearestNeighbors (100);
00101 this->_rb_greedy_projection_triangulator_ptr->setMaximumSurfaceAngle(M_PI);
00102 this->_rb_greedy_projection_triangulator_ptr->setMinimumAngle(0.0);
00103 this->_rb_greedy_projection_triangulator_ptr->setMaximumAngle(M_PI);
00104 this->_rb_greedy_projection_triangulator_ptr->setNormalConsistency(true);
00105 this->_rb_greedy_projection_triangulator_ptr->setConsistentVertexOrdering(true);
00106
00107 this->_rb_greedy_projection_triangulator_ptr->setSearchRadius (0.1);
00108 this->_rb_polygon_writer_ptr = vtkSmartPointer<vtkSTLWriter>::New ();
00109 this->_rb_polygon_writer_ptr->SetFileTypeToBinary();
00110 this->_rb_triangulated_mesh_ptr.reset(new pcl::PolygonMesh());
00111 }
00112
00113 void ShapeReconstruction::setInitialFullRGBDPCAndRBT(const SRPointCloud::Ptr &initial_pc_msg,
00114 const geometry_msgs::TwistWithCovariance &rb_transformation_initial)
00115 {
00116
00117 pcl::copyPointCloud(*initial_pc_msg, *this->_initial_ffs._pc);
00118
00119
00120 this->_initial_ffs._time.fromNSec(initial_pc_msg->header.stamp);
00121
00122
00123 pcl::removeNaNFromPointCloud<SRPoint>(*this->_initial_ffs._pc,*this->_initial_ffs._pc_without_nans, this->_initial_ffs._not_nan_indices);
00124
00125
00126 pcl::toROSMsg (*initial_pc_msg, this->_initial_ffs._rgb);
00127
00128
00129 this->_initial_ffs._transformation = geometry_msgs::TwistWithCovariance(rb_transformation_initial);
00130
00131
00132 OrganizedPC2DepthMap(this->_initial_ffs._pc, this->_initial_ffs._dm->image);
00133
00134 if(this->_depth_filling)
00135 {
00136 fillNaNsCBF(this->_initial_ffs._rgb, this->_initial_ffs._dm->image, this->_initial_ffs._dm_filled, this->_initial_ffs._time);
00137 }
00138 }
00139
00140 void ShapeReconstruction::initialize()
00141 {
00142 std::stringstream pub_topic_name_ext_d_and_c;
00143 pub_topic_name_ext_d_and_c << "/shape_recons/shape_rb" << this->_rb_id;
00144 this->_rb_shape_pub = this->_node_handle.advertise<sensor_msgs::PointCloud2>(pub_topic_name_ext_d_and_c.str(), 1);
00145
00146 std::stringstream pub_segment_topic_name;
00147 pub_segment_topic_name << "/shape_recons/segment_rb" << this->_rb_id;
00148 this->_rb_segment_pub = this->_node_handle.advertise<sensor_msgs::PointCloud2>(pub_segment_topic_name.str(), 1);
00149
00150 std::stringstream pub_occlusion_topic_name;
00151 pub_occlusion_topic_name << "/shape_recons/pc_occlusions_rb" << this->_rb_id;
00152 this->_occlusions_pub = this->_node_handle.advertise<sensor_msgs::PointCloud2>(pub_occlusion_topic_name.str(), 1);
00153
00154 std::stringstream pub_occlusion_t_topic_name;
00155 pub_occlusion_t_topic_name << "/shape_recons/pc_occlusions_transf_rb" << this->_rb_id;
00156 this->_occlusions_transformed_pub = this->_node_handle.advertise<sensor_msgs::PointCloud2>(pub_occlusion_t_topic_name.str(), 1);
00157
00158 this->_approximate_voxel_grid_filter.setLeafSize(this->_leaf_size,
00159 this->_leaf_size,
00160 this->_leaf_size);
00161
00162
00163
00164
00165
00166 this->_radius_outlier_removal.setRadiusSearch (this->_ror_radius_search);
00167
00168 this->_radius_outlier_removal.setMinNeighborsInRadius (this->_ror_min_neighbors);
00169
00170 if(this->_record_videos)
00171 {
00172 std::string videos_path = ros::package::getPath("shape_reconstruction") + std::string("/videos/");
00173
00174
00175 boost::filesystem::path videos_folder(videos_path);
00176 if (!boost::filesystem::exists(videos_folder)) {
00177 if (!boost::filesystem::create_directories(videos_folder)) {
00178 ROS_ERROR_NAMED("ShapeReconstruction.ShapeReconstruction", "Output directory for video bag does not exist and cannot be created!");
00179 return;
00180 }
00181 }
00182
00183 this->_videos.open(videos_path + std::string("videos_rb") + boost::lexical_cast<std::string>(this->_rb_id)+std::string(".bag"),rosbag::bagmode::Write);
00184
00185 sensor_msgs::ImagePtr initial_dm_msg;
00186 DepthImage2CvImage(this->_initial_ffs._dm->image, initial_dm_msg);
00187 this->_videos.write("original_dm", this->_initial_ffs._time, initial_dm_msg);
00188
00189 if(this->_depth_filling)
00190 {
00191 sensor_msgs::ImagePtr initial_dm_filled_msg;
00192 DepthImage2CvImage(this->_initial_ffs._dm_filled, initial_dm_filled_msg);
00193 this->_videos.write("filled_dm", this->_initial_ffs._time, initial_dm_filled_msg);
00194 }
00195 }
00196 }
00197
00198 ShapeReconstruction::ShapeReconstruction(const ShapeReconstruction &sr)
00199 {
00200 ROS_ERROR_STREAM_NAMED("ShapeReconstruction.ShapeReconstruction", "Do not use this copy constructor! It is not complete!");
00201
00202 this->_rb_id = sr._rb_id;
00203
00204 this->_to_initial = sr._to_initial;
00205 this->_depth_filling = sr._depth_filling;
00206
00207 this->_initial_ffs = sr._initial_ffs.clone();
00208 this->_previous_ffs = sr._previous_ffs.clone();
00209 this->_current_ffs = sr._current_ffs.clone();
00210
00211 this->_rip_temp = pcl::RangeImagePlanar::Ptr(new pcl::RangeImagePlanar(*sr._rip_temp));
00212
00213 this->_moving_pts_of_current_idx_depth = pcl::PointIndices::Ptr(new pcl::PointIndices(*sr._moving_pts_of_current_idx_depth));
00214 this->_moving_pts_of_previous_idx_depth = pcl::PointIndices::Ptr(new pcl::PointIndices(*sr._moving_pts_of_previous_idx_depth));
00215 this->_out_of_view_pts_of_current_idx = pcl::PointIndices::Ptr(new pcl::PointIndices(*sr._out_of_view_pts_of_current_idx));
00216 this->_occluded_pts_of_current_idx = pcl::PointIndices::Ptr(new pcl::PointIndices(*sr._occluded_pts_of_current_idx));
00217
00218 }
00219
00220 ShapeReconstruction::~ShapeReconstruction()
00221 {
00222 if(this->_record_videos)
00223 {
00224 _videos.close();
00225 }
00226 }
00227
00228 void ShapeReconstruction::setCameraInfo(const sensor_msgs::CameraInfo& camera_info)
00229 {
00230 this->_ci = sensor_msgs::CameraInfo(camera_info);
00231 }
00232
00233 void ShapeReconstruction::setFullRGBDPCandRBT(const SRPointCloud::Ptr &pc_msg,
00234 const geometry_msgs::TwistWithCovariance &rb_transformation)
00235 {
00236 ros::Time t1 = ros::Time::now();
00237
00238 _previous_k_indices.clear();
00239 _current_k_indices.clear();
00240
00241 ROS_WARN_STREAM_NAMED("ShapeReconstruction.setFullRGBDPCandRBT", "[RB" << this->_rb_id << "]: t = " << _t);
00242
00243
00244 if(this->_current_ffs._pc->points.size() > 0 )
00245 {
00246 this->_previous_ffs = this->_current_ffs;
00247 }else{
00248 this->_previous_ffs = this->_initial_ffs;
00249 }
00250 this->_current_ffs.reset();
00251
00252 ros::Time t2 = ros::Time::now();
00253
00254 pcl::copyPointCloud(*pc_msg, *this->_current_ffs._pc);
00255
00256 ros::Time t3 = ros::Time::now();
00257
00258
00259 this->_current_ffs._not_nan_indices.clear();
00260 pcl::removeNaNFromPointCloud<SRPoint>(*this->_current_ffs._pc,*this->_current_ffs._pc_without_nans, this->_current_ffs._not_nan_indices);
00261
00262 ros::Time t4 = ros::Time::now();
00263
00264 ROS_WARN_STREAM_NAMED("ShapeReconstruction.setFullRGBDPCandRBT", "[RB" << this->_rb_id << "]: " << "Point cloud time stamp: "
00265 <<this->_current_ffs._pc->header.stamp << ", not nan points "
00266 << this->_current_ffs._not_nan_indices.size() << "/" << this->_current_ffs._pc_without_nans->size());
00267
00268
00269 this->_current_ffs._time = pcl_conversions::fromPCL(pc_msg->header.stamp);
00270 pcl::toROSMsg (*pc_msg, this->_current_ffs._rgb);
00271 this->_current_ffs._transformation = geometry_msgs::TwistWithCovariance(rb_transformation);
00272
00273 ros::Time t5 = ros::Time::now();
00274
00275
00276 OrganizedPC2DepthMap(this->_current_ffs._pc, this->_current_ffs._dm->image);
00277
00278 ros::Time t6 = ros::Time::now();
00279
00280
00281
00282
00283 if(this->_depth_filling)
00284 {
00285 fillNaNsCBF(this->_current_ffs._rgb, this->_current_ffs._dm->image, this->_current_ffs._dm_filled, this->_current_ffs._time);
00286 this->_current_ffs._dm->image.copyTo(this->_current_ffs._dm_filled, this->_current_ffs._dm->image == this->_current_ffs._dm->image);
00287 }
00288
00289 ros::Time t7 = ros::Time::now();
00290
00291 if(this->_record_videos)
00292 {
00293 sensor_msgs::ImagePtr current_dm_msg;
00294 DepthImage2CvImage(this->_current_ffs._dm->image, current_dm_msg);
00295 this->_videos.write("original_dm", this->_current_ffs._time, current_dm_msg);
00296
00297 if(this->_depth_filling)
00298 {
00299 sensor_msgs::ImagePtr current_dm_filled_msg;
00300 DepthImage2CvImage(this->_current_ffs._dm_filled, current_dm_filled_msg);
00301 this->_videos.write("filled_dm", this->_current_ffs._time, current_dm_filled_msg);
00302 }
00303 }
00304
00305
00306 this->_DetectImageLocationsWhereDepthChanges();
00307 ros::Time t8 = ros::Time::now();
00308 this->_TestMotionCoherencyOfPointsInImageLocationsWhereDepthChanged();
00309 ros::Time t9 = ros::Time::now();
00310
00311
00312 this->_DetectImageLocationsWhereColorChanges();
00313 ros::Time t10 = ros::Time::now();
00314 this->_TestMotionCoherencyOfPointsInImageLocationsWhereColorChanged();
00315 ros::Time t11 = ros::Time::now();
00316
00317
00318 this->_MergeValidPointsIntoModels();
00319
00320 ros::Time t12 = ros::Time::now();
00321
00322 this->_RemoveInconsistentPointsFromModelsAndExtendToRegions();
00323
00324 ros::Time t12b = ros::Time::now();
00325
00326 this->_FilterModel();
00327
00328 ros::Time t13 = ros::Time::now();
00329
00330 _t++;
00331
00332
00333
00334
00335
00336
00337
00338 }
00339
00340 void ShapeReconstruction::_DetectImageLocationsWhereDepthChanges()
00341 {
00342
00343 if(this->_depth_filling)
00344 {
00345 this->_difference_in_depth = this->_current_ffs._dm_filled - this->_previous_ffs._dm_filled;
00346 }else{
00347 this->_difference_in_depth = this->_current_ffs._dm->image - this->_previous_ffs._dm->image;
00348 }
00349
00350 if(this->_record_videos)
00351 {
00352 sensor_msgs::ImagePtr dm_msg;
00353 DepthImage2CvImage(_difference_in_depth, dm_msg);
00354 this->_videos.write("changes_in_depth", this->_current_ffs._time, dm_msg);
00355 }
00356
00357
00358
00359
00360 cv::threshold(this->_difference_in_depth, this->_candidates_of_current, -_min_depth_change, 255, cv::THRESH_BINARY_INV);
00361
00362 if(this->_record_videos)
00363 {
00364 sensor_msgs::ImagePtr dm_msg;
00365 DepthImage2CvImage(_candidates_of_current, dm_msg);
00366 this->_videos.write("candidates_of_current", this->_current_ffs._time, dm_msg);
00367 }
00368
00369
00370
00371 cv::threshold(this->_difference_in_depth, this->_candidates_of_previous, _min_depth_change, 255, cv::THRESH_BINARY);
00372
00373 if(this->_record_videos)
00374 {
00375 sensor_msgs::ImagePtr dm_msg;
00376 DepthImage2CvImage(_candidates_of_previous, dm_msg);
00377 this->_videos.write("candidates_of_previous", this->_current_ffs._time, dm_msg);
00378 }
00379
00380 this->_previous_depth_mask = this->_previous_ffs._dm->image > 1.5 | this->_previous_ffs._dm->image < 0.3 | this->_previous_ffs._dm->image != this->_previous_ffs._dm->image;
00381 this->_current_depth_mask = this->_current_ffs._dm->image > 1.5 | this->_current_ffs._dm->image < 0.3 | this->_current_ffs._dm->image != this->_current_ffs._dm->image;
00382
00383 this->_candidates_of_current.convertTo(this->_candidates_of_current_8u, CV_8U);
00384 this->_candidates_of_previous.convertTo(this->_candidates_of_previous_8u, CV_8U);
00385
00386
00387 this->_acc_candidates_of_current = _acc_candidates_of_current | this->_candidates_of_current_8u;
00388 this->_acc_candidates_of_current.setTo(0,this->_candidates_of_previous_8u);
00389
00390 if(this->_record_videos)
00391 {
00392 sensor_msgs::ImagePtr dm_msg;
00393 DepthImage2CvImage(_acc_candidates_of_current, dm_msg);
00394 this->_videos.write("acc_candidates_of_current", this->_current_ffs._time, dm_msg);
00395 }
00396
00397 if (!this->_depth_filling)
00398 {
00399 ROS_INFO_STREAM_NAMED("ShapeReconstruction._DetectImageLocationsWhereDepthChanges", "[RB" << this->_rb_id << "]: Removing nan points from accumulator");
00400 this->_acc_candidates_of_current.setTo(0, this->_current_ffs._dm->image != this->_current_ffs._dm->image);
00401 }
00402
00403 if(this->_accumulate_change_candidates)
00404 {
00405 this->_acc_candidates_of_current.copyTo(this->_candidates_of_current_8u);
00406 }
00407
00408 this->_candidates_of_current_8u.setTo(0, this->_current_depth_mask);
00409 this->_candidates_of_previous_8u.setTo(0, this->_previous_depth_mask);
00410
00411 this->_moving_pts_of_current_idx_depth->indices.clear();
00412 this->_moving_pts_of_previous_idx_depth->indices.clear();
00413
00414 Image8u2Indices(this->_candidates_of_current_8u, this->_moving_pts_of_current_idx_depth);
00415 Image8u2Indices(this->_candidates_of_previous_8u, this->_moving_pts_of_previous_idx_depth);
00416 }
00417
00418 void ShapeReconstruction::_TestMotionCoherencyOfPointsInImageLocationsWhereDepthChanged()
00419 {
00420
00421 this->_EstimateTransformations();
00422
00423 ROS_INFO_STREAM_NAMED("ShapeReconstruction._TestMotionCoherencyOfPointsInImageLocationsWhereDepthChanged",
00424 "[RB" << this->_rb_id << "]: Estimating which of the points that changed DEPTH moved coherently with the RB motion.");
00425
00426
00427 this->_sqrt_dist.clear();
00428 this->_FindCandidatesInPreviousPC(this->_previous_ffs,
00429 this->_current_ffs,
00430 this->_moving_pts_of_previous_idx_depth,
00431 this->_current_to_previous_HTransform,
00432 this->_current_k_indices,
00433 this->_sqrt_dist);
00434
00435
00436 this->_sqrt_dist.clear();
00437 this->_FindCandidatesInCurrentPC(this->_previous_ffs,
00438 this->_current_ffs,
00439 this->_moving_pts_of_current_idx_depth,
00440 this->_previous_to_current_HTransform,
00441 this->_previous_k_indices,
00442 this->_sqrt_dist);
00443
00444 std::vector<int > invalid_indices;
00445
00446 for (unsigned int i = 0; i < _previous_k_indices.size(); i++)
00447 {
00448 if (_previous_k_indices[i].size() == 0)
00449 {
00450 invalid_indices.push_back(_moving_pts_of_current_idx_depth->indices.at(i));
00451 }
00452 }
00453
00454 cv::Mat not_coherent_points = cv::Mat(IMG_HEIGHT, IMG_WIDTH, CV_8UC1);
00455 Indices2Image8u(invalid_indices, not_coherent_points);
00456
00457 this->_acc_candidates_of_current.setTo(0, not_coherent_points);
00458 }
00459
00460
00461 void ShapeReconstruction::_DetectImageLocationsWhereColorChanges()
00462 {
00463
00464 cv::Mat current_hsv_image, current_h_channel, current_s_channel, current_v_channel;
00465 cv::Mat previous_hsv_image, previous_h_channel, previous_s_channel, previous_v_channel;
00466 cv::Mat difference_h_channel, circular_difference_h_channel, thresholded_difference_h_channel, difference_h_channel_wo_black, thresholded_difference_h_channel_wo_black;
00467
00468
00469 cv_bridge::CvImagePtr previous_rgb_cv;
00470 previous_rgb_cv = cv_bridge::toCvCopy(this->_previous_ffs._rgb);
00471
00472 cv_bridge::CvImagePtr current_rgb_cv;
00473 current_rgb_cv = cv_bridge::toCvCopy(this->_current_ffs._rgb);
00474
00475 #ifdef DISPLAY_IMAGES_DILWCC
00476
00477 cv::imshow("color current", current_rgb_cv->image);
00478 cv::imshow("color previous", previous_rgb_cv->image);
00479 #endif
00480
00481
00482 cv::cvtColor(previous_rgb_cv->image, previous_hsv_image, CV_BGR2HSV);
00483 cv::cvtColor(current_rgb_cv->image, current_hsv_image, CV_BGR2HSV);
00484
00485
00486
00487
00488
00489
00490 cv::extractChannel(current_hsv_image,current_h_channel,0);
00491 cv::extractChannel(current_hsv_image,current_s_channel,1);
00492 cv::extractChannel(current_hsv_image,current_v_channel,2);
00493
00494 cv::extractChannel(previous_hsv_image,previous_h_channel,0);
00495 cv::extractChannel(previous_hsv_image,previous_s_channel,1);
00496 cv::extractChannel(previous_hsv_image,previous_v_channel,2);
00497
00498
00499
00500 cv::absdiff(current_h_channel, previous_h_channel, difference_h_channel );
00501 circular_difference_h_channel = 180.0 - difference_h_channel;
00502 circular_difference_h_channel.copyTo(difference_h_channel, difference_h_channel >89);
00503
00504 #ifdef DISPLAY_IMAGES_DILWCC
00505
00506 cv::imshow("Circular difference of HUE", difference_h_channel);
00507 #endif
00508
00509
00510 difference_h_channel.copyTo(difference_h_channel_wo_black);
00511
00512 difference_h_channel_wo_black.setTo(cv::Scalar(0), current_s_channel < 90 | previous_s_channel < 90 );
00513
00514 #ifdef DISPLAY_IMAGES_DILWCC
00515
00516 cv::imshow("Low current_s_channel", current_s_channel < 90);
00517
00518 cv::imshow("Low previous_s_channel", previous_s_channel < 90);
00519
00520 #endif
00521
00522
00523 cv::threshold(difference_h_channel, thresholded_difference_h_channel, 20, 255, cv::THRESH_BINARY);
00524
00525 #ifdef DISPLAY_IMAGES_DILWCC
00526 cv::imshow("Thresholded circular difference of HUE", thresholded_difference_h_channel);
00527 #endif
00528
00529
00530 cv::threshold(difference_h_channel_wo_black, thresholded_difference_h_channel_wo_black, 15, 255, cv::THRESH_BINARY);
00531
00532 #ifdef DISPLAY_IMAGES_DILWCC
00533 cv::imshow("Thresholded circular difference of HUE without black pixels", thresholded_difference_h_channel_wo_black);
00534 #endif
00535
00536 cv::Mat thresholded_difference_h_channel_wo_black_wo_noisy_pixels;
00537 int openning_size = 1;
00538
00539 int openning_element_type = 2;
00540 cv::Mat openning_element = cv::getStructuringElement( openning_element_type, cv::Size( 2*openning_size + 1, 2*openning_size+1 ), cv::Point( openning_size, openning_size ) );
00541 cv::morphologyEx(thresholded_difference_h_channel_wo_black, thresholded_difference_h_channel_wo_black_wo_noisy_pixels, cv::MORPH_OPEN, openning_element);
00542
00543 #ifdef DISPLAY_IMAGES_DILWCC
00544 cv::imshow("Thresholded circular difference of HUE without black pixels nor NOISY pixels", thresholded_difference_h_channel_wo_black_wo_noisy_pixels);
00545 #endif
00546
00547
00548
00549 cv::Mat changing_depth_points;
00550 if(this->_depth_filling)
00551 {
00552 cv::absdiff(this->_current_ffs._dm_filled, this->_previous_ffs._dm_filled, changing_depth_points);
00553 }else{
00554 cv::absdiff(this->_current_ffs._dm->image, this->_previous_ffs._dm->image, changing_depth_points);
00555 }
00556
00557
00558 cv::Mat motion_mask_current= thresholded_difference_h_channel_wo_black_wo_noisy_pixels.clone();
00559 motion_mask_current.setTo(cv::Scalar(0), this->_current_depth_mask);
00560
00561
00562 cv::Mat motion_mask_previous = thresholded_difference_h_channel_wo_black_wo_noisy_pixels.clone();
00563 motion_mask_previous.setTo(cv::Scalar(0), this->_previous_depth_mask);
00564
00565 #ifdef DISPLAY_IMAGES_DILWCC
00566 cv::imshow("Current color candidates", motion_mask_current);
00567 cv::imshow("Previous color candidates", motion_mask_previous);
00568 #endif
00569
00570 #ifdef DISPLAY_IMAGES_DILWCC
00571 cv::waitKey(-1);
00572 #endif
00573
00574 Image8u2Indices(motion_mask_current, this->_moving_pts_of_current_idx_color);
00575 Image8u2Indices(motion_mask_previous, this->_moving_pts_of_previous_idx_color);
00576
00577 if(this->_record_videos)
00578 {
00579 _videos.write("original_color",ros::Time::now(), current_rgb_cv->toImageMsg());
00580 sensor_msgs::ImagePtr dm_msg;
00581 DepthImage2CvImage(thresholded_difference_h_channel, dm_msg);
00582 this->_videos.write("changes_in_color", this->_current_ffs._time, dm_msg);
00583 }
00584 }
00585
00586 void ShapeReconstruction::_TestMotionCoherencyOfPointsInImageLocationsWhereColorChanged()
00587 {
00588 ROS_INFO_STREAM_NAMED("ShapeReconstruction._TestMotionCoherencyOfPointsInImageLocationsWhereColorChanged",
00589 "[RB" << this->_rb_id << "]: Estimating which of the points that changed COLOR moved coherently with the RB motion.");
00590
00591
00592 this->_FindCandidatesInPreviousPC(this->_previous_ffs,
00593 this->_current_ffs,
00594 this->_moving_pts_of_previous_idx_color,
00595 this->_current_to_previous_HTransform,
00596 this->_current_k_indices,
00597 this->_sqrt_dist);
00598
00599
00600 this->_FindCandidatesInCurrentPC(this->_previous_ffs,
00601 this->_current_ffs,
00602 this->_moving_pts_of_current_idx_color,
00603 this->_previous_to_current_HTransform,
00604 this->_previous_k_indices,
00605 this->_sqrt_dist);
00606 }
00607
00608 void ShapeReconstruction::_FindCandidatesInPreviousPC(FrameForSegmentation& _previous_ffs,
00609 const FrameForSegmentation& _current_ffs,
00610 pcl::PointIndices::Ptr& _moving_pts_of_previous_idx,
00611 Eigen::Matrix4d& _current_to_previous_HTransform,
00612 std::vector<std::vector<int > >& _previous_k_indices,
00613 std::vector<std::vector<float > >& _previous_sqrt_dist)
00614 {
00615 _previous_ffs._pc_moving_pts = omip::SRPointCloud::Ptr(new omip::SRPointCloud);
00616 this->_extractor.setInputCloud(_previous_ffs._pc);
00617 this->_extractor.setIndices(_moving_pts_of_previous_idx);
00618 this->_extractor.setNegative(false);
00619 this->_extractor.filter(*_previous_ffs._pc_moving_pts);
00620
00621 std::vector<std::vector<int > > previous_k_indices;
00622 if(_previous_ffs._pc_moving_pts->points.size())
00623 {
00624 pcl::transformPointCloud<SRPoint>(*_previous_ffs._pc_moving_pts, *_previous_ffs._pc_moving_pts_transf, _current_to_previous_HTransform.cast<float>());
00625
00626 this->_knn->setInputCloud(_current_ffs._pc_without_nans);
00627 std::vector<int> empty;
00628
00629 this->_knn->radiusSearch(*_previous_ffs._pc_moving_pts_transf, empty, this->_knn_min_radius, previous_k_indices, _previous_sqrt_dist);
00630
00631 ROS_INFO_STREAM_NAMED("ShapeReconstruction._FindCandidatesInPreviousPC", "[RB" << this->_rb_id << "]: After radius search for finding candidates in previous PC. Queries: "
00632 << _previous_ffs._pc_moving_pts_transf->points.size() );
00633
00634 }
00635
00636 _previous_k_indices.insert(_previous_k_indices.end(), previous_k_indices.begin(), previous_k_indices.end());
00637 }
00638
00639 void ShapeReconstruction::_FindCandidatesInCurrentPC(const FrameForSegmentation& _previous_ffs,
00640 FrameForSegmentation& _current_ffs,
00641 pcl::PointIndices::Ptr& _moving_pts_of_current_idx,
00642 Eigen::Matrix4d& _previous_to_current_HTransform,
00643 std::vector<std::vector<int > >& _current_k_indices,
00644 std::vector<std::vector<float > >& _current_sqrt_dist)
00645 {
00646 _current_ffs._pc_moving_pts = omip::SRPointCloud::Ptr(new omip::SRPointCloud);
00647 this->_extractor.setInputCloud(_current_ffs._pc);
00648 this->_extractor.setIndices(_moving_pts_of_current_idx);
00649 this->_extractor.setNegative(false);
00650 this->_extractor.filter(*_current_ffs._pc_moving_pts);
00651
00652 std::vector<std::vector<int > > current_k_indices;
00653 if(_current_ffs._pc_moving_pts->points.size())
00654 {
00655 pcl::transformPointCloud<SRPoint>(*_current_ffs._pc_moving_pts, *_current_ffs._pc_moving_pts_transf, _previous_to_current_HTransform.cast<float>());
00656
00657 this->_knn->setInputCloud(_previous_ffs._pc_without_nans);
00658
00659 std::vector<int> empty;
00660 this->_knn->radiusSearch(*_current_ffs._pc_moving_pts_transf, empty, this->_knn_min_radius, current_k_indices, _current_sqrt_dist);
00661
00662 ROS_INFO_STREAM_NAMED("ShapeReconstruction._FindCandidatesInPreviousPC", "[RB" << this->_rb_id << "]: After radius search for finding candidates in current PC. Queries: "
00663 << _current_ffs._pc_moving_pts_transf->points.size() );
00664 }
00665
00666 _current_k_indices.insert(_current_k_indices.end(), current_k_indices.begin(), current_k_indices.end());
00667 }
00668
00669
00670 void ShapeReconstruction::_MergeValidPointsIntoModels()
00671 {
00672
00673
00674
00675 omip::SRPointCloud::Ptr points_of_current_in_origin(new omip::SRPointCloud);
00676 pcl::transformPointCloud<SRPoint>(*this->_current_ffs._pc_without_nans, *points_of_current_in_origin, this->_current_HTransform_inv.cast<float>());
00677
00678
00679 omip::SRPointCloud::Ptr points_of_previous_in_origin(new omip::SRPointCloud);
00680 pcl::transformPointCloud<SRPoint>(*this->_previous_ffs._pc_without_nans, *points_of_previous_in_origin, this->_previous_HTransform_inv.cast<float>());
00681
00682
00683 _MergeValidPointsIntoModels("DEPTHANDCOLOR",
00684 points_of_current_in_origin,
00685 points_of_previous_in_origin,
00686 this->_rb_shape,
00687 this->_current_k_indices,
00688 this->_previous_k_indices);
00689
00690 this->_candidates->points.clear();
00691 this->_candidates->width = 0;
00692 }
00693
00694 void ShapeReconstruction::_MergeValidPointsIntoModels(const std::string& logger_name,
00695 omip::SRPointCloud::Ptr& points_of_current_in_origin,
00696 omip::SRPointCloud::Ptr& points_of_previous_in_origin,
00697 omip::SRPointCloud::Ptr& rb_model,
00698 const std::vector<std::vector<int > >& current_k_indices,
00699 const std::vector<std::vector<int > >& previous_k_indices)
00700 {
00701 int model_size_before_adding = rb_model->width;
00702
00703
00704 for (unsigned int i = 0; i < current_k_indices.size(); i++) {
00705 if (current_k_indices[i].size() > 0){
00706 rb_model->points.push_back(points_of_current_in_origin->points[current_k_indices[i].at(0)]);
00707 rb_model->width++;
00708 }
00709 }
00710
00711
00712 for (unsigned int i = 0; i < previous_k_indices.size(); i++) {
00713 if (previous_k_indices[i].size() > 0){
00714 rb_model->points.push_back(points_of_previous_in_origin->points[previous_k_indices[i].at(0)]);
00715 rb_model->width++;
00716 }
00717 }
00718
00719 int number_of_points_added = rb_model->width - model_size_before_adding;
00720 ROS_INFO_STREAM_NAMED("ShapeReconstruction._MergeValidPointsIntoModels", "[RB" << this->_rb_id << "] "
00721 << ": Added " << number_of_points_added << " points to the model based on changes in " << logger_name);
00722 }
00723
00724 void ShapeReconstruction::_RemoveInconsistentPointsFromModelsAndExtendToRegions()
00725 {
00726
00727 this->_RemoveInconsistentPointsFromRBModel("BeforeExtendingToRegions", this->_current_HTransform,
00728 this->_rb_shape,this->_current_ffs._dm->image,this->_current_ffs._pc,this->_rb_segment);
00729
00730 if(_estimate_supervoxels)
00731 {
00732
00733 this->_ExtendPointsToRegions();
00734
00735 this->_RemoveInconsistentPointsFromRBModel("AfterExtendingToRegions", this->_current_HTransform,
00736 this->_rb_shape,this->_current_ffs._dm->image,this->_current_ffs._pc,this->_rb_segment);
00737 }
00738 }
00739
00740 void ShapeReconstruction::_FilterModel()
00741 {
00742 ROS_INFO_STREAM_NAMED("ShapeReconstruction._FilterModel", "[RB" << this->_rb_id << "]: Before approximate voxel grid filter. Num of points: "
00743 << this->_rb_shape->points.size() );
00744 this->_approximate_voxel_grid_filter.setInputCloud (this->_rb_shape);
00745 this->_approximate_voxel_grid_filter.filter (*this->_rb_shape);
00746 ROS_INFO_STREAM_NAMED("ShapeReconstruction._FilterModel", "[RB" << this->_rb_id << "]: After approximate voxel grid filter. Num of points: "
00747 << this->_rb_shape->points.size() );
00748
00749
00750 ROS_INFO_STREAM_NAMED("ShapeReconstruction._FilterModel", "[RB" << this->_rb_id << "] " << ": Before outlier removal. Num of points: "
00751 << this->_rb_shape->points.size() );
00752 this->_radius_outlier_removal.setInputCloud(this->_rb_shape);
00753 this->_radius_outlier_removal.filter (*this->_rb_shape);
00754 ROS_INFO_STREAM_NAMED("ShapeReconstruction._FilterModel", "[RB" << this->_rb_id << "] " << ": After outlier removal. Num of points: "
00755 << this->_rb_shape->points.size() );
00756
00757 }
00758
00759 void ShapeReconstruction::_RemoveInconsistentPointsFromRBModel(const std::string logger_name,
00760 const Eigen::Matrix4d& HTransform,
00761 SRPointCloud::Ptr& rb_shape,
00762 cv::Mat& current_dm,
00763 SRPointCloud::Ptr current_pc,
00764 SRPointCloud::Ptr& rb_segment)
00765 {
00766
00767
00768
00769
00770 ROS_INFO_STREAM_NAMED("ShapeReconstruction._RemoveInconsistentPointsFromRBModel", "[RB" << this->_rb_id << "] " << logger_name <<
00771 ": Removing inconsistent points");
00772
00773
00774 omip::SRPointCloud::Ptr rb_shape_current(new omip::SRPointCloud);
00775 pcl::transformPointCloud<SRPoint>(*rb_shape, *rb_shape_current, HTransform.cast<float>());
00776
00777
00778 omip::SRPointCloud::Ptr rb_shape_current_new(new omip::SRPointCloud);
00779 *rb_shape_current_new = *rb_shape_current;
00780
00781 std::stringstream rb_id_str;
00782 rb_id_str << _rb_id;
00783
00784 pcl::PointIndicesPtr indices_to_remove(new pcl::PointIndices);
00785
00786
00787
00788 pcl::PointIndicesPtr indices_matching_in_model(new pcl::PointIndices);
00789 pcl::PointIndicesPtr indices_matching_in_current(new pcl::PointIndices);
00790
00791
00792
00793 _FindInconsistentPoints(rb_shape_current_new, current_dm,
00794 indices_to_remove,
00795 indices_matching_in_model,
00796 indices_matching_in_current
00797 );
00798
00799
00800 SRPointCloud::Ptr rb_new_clean(new SRPointCloud);
00801 if (_remove_inconsistent_points)
00802 {
00803
00804 this->_extractor.setNegative(true);
00805 this->_extractor.setInputCloud(rb_shape);
00806 this->_extractor.setIndices(indices_to_remove);
00807 this->_extractor.setKeepOrganized(false);
00808 this->_extractor.filter(*rb_new_clean);
00809 } else {
00810 indices_to_remove->indices.clear();
00811 }
00812
00813
00814 SRPointCloud::Ptr rb_segment_new(new SRPointCloud);
00815 this->_extractor.setNegative(false);
00816 this->_extractor.setInputCloud(current_pc);
00817 this->_extractor.setIndices(indices_matching_in_current);
00818 this->_extractor.setKeepOrganized(true);
00819 this->_extractor.filter(*rb_segment_new);
00820 this->_extractor.setKeepOrganized(false);
00821
00822 cv::Mat rb_segment_new_dm(IMG_HEIGHT, IMG_WIDTH, CV_32FC1);
00823 OrganizedPC2DepthMap(rb_segment_new, rb_segment_new_dm);
00824
00825 ROS_INFO_STREAM_NAMED("ShapeReconstruction._RemoveInconsistentPointsAndComputeSegment", "[RB" << this->_rb_id << "] " << logger_name << ":" << std::endl
00826 << "\tPoints of the original model: " << rb_shape->points.size() << "," << std::endl
00827 << "\tPoints matching in model: " << indices_matching_in_model->indices.size() << "," << std::endl
00828 << "\tPoints matching in model: " << rb_new_clean->points.size() << "," << std::endl
00829 << "\tPoints matching in current point cloud: " << indices_matching_in_current->indices.size() << std::endl
00830 << "\tPoints removed: " << indices_to_remove->indices.size() << (indices_to_remove->indices.empty() ? " (NO POINTS REMOVED) " : "")
00831 );
00832
00833 if (_remove_inconsistent_points)
00834 {
00835 rb_shape = rb_new_clean;
00836 }
00837 rb_segment = rb_segment_new;
00838 }
00839
00840 void ShapeReconstruction::_FindInconsistentPoints(const omip::SRPointCloud::Ptr& pc_source,
00841 const cv::Mat & dm_true,
00842 pcl::PointIndicesPtr& indices_to_remove,
00843 pcl::PointIndicesPtr& indices_matching_in_true,
00844 pcl::PointIndicesPtr& indices_matching_in_dm,
00845 const double min_depth_error) {
00846
00847 indices_to_remove->indices.clear();
00848
00849 using ::shape_reconstruction::RangeImagePlanar;
00850 RangeImagePlanar::Ptr dm_source_rip(new RangeImagePlanar);
00851
00852 Eigen::Affine3f sensor_pose;
00853 sensor_pose.matrix() = Eigen::Matrix4f::Identity();
00854 pcl::RangeImagePlanar::CoordinateFrame coordinate_frame = pcl::RangeImagePlanar::CAMERA_FRAME;
00855
00856 int width = dm_true.cols, height = dm_true.rows;
00857 dm_source_rip->matchPointCloudAndImage (
00858 *pc_source,
00859 width,
00860 height,
00861 this->_ci.P[2],
00862 this->_ci.P[6],
00863 this->_ci.P[0],
00864 this->_ci.P[5],
00865 sensor_pose,
00866 coordinate_frame,
00867 dm_true,
00868 min_depth_error,
00869 indices_matching_in_true,
00870 indices_matching_in_dm,
00871 indices_to_remove
00872 );
00873
00874 }
00875
00876 void ShapeReconstruction::growSVRecursively(uint32_t label_sv_seed,
00877 std::vector<uint32_t>& labels_extension,
00878 std::multimap<uint32_t, uint32_t>& supervoxel_adjacency,
00879 std::vector<uint32_t>& sv_containing_supporting_features,
00880 int& distance_to_feature_sv,
00881 std::map<uint32_t, std::unordered_set<int> >& labels_of_segments_to_extend)
00882 {
00883 std::pair< std::multimap<uint32_t, uint32_t>::iterator, std::multimap<uint32_t, uint32_t>::iterator > neighbors;
00884
00885
00886 neighbors =supervoxel_adjacency.equal_range(label_sv_seed);
00887
00888
00889 for(std::multimap<uint32_t, uint32_t>::iterator neighbor_it = neighbors.first; neighbor_it!= neighbors.second; ++neighbor_it)
00890 {
00891 bool add_neighbor = false;
00892
00893 if(std::find(labels_extension.begin(), labels_extension.end(), neighbor_it->second) != labels_extension.end())
00894 {
00895 add_neighbor = false;
00896 }else{
00897
00898
00899 if(std::find(sv_containing_supporting_features.begin(), sv_containing_supporting_features.end(), neighbor_it->second) != sv_containing_supporting_features.end())
00900 {
00901 add_neighbor = true;
00902 distance_to_feature_sv = 0;
00903 }else{
00904 std::map<uint32_t, std::unordered_set<int> >::iterator set_it = labels_of_segments_to_extend.find(neighbor_it->second);
00905 if(set_it != labels_of_segments_to_extend.end())
00906 {
00907 if(set_it->second.size() > this->_min_number_model_pixels_in_sv)
00908 {
00909 if(distance_to_feature_sv <= 2)
00910 {
00911 add_neighbor = true;
00912 distance_to_feature_sv++;
00913 }
00914 }
00915 }
00916
00917 }
00918 }
00919
00920 if(add_neighbor)
00921 {
00922 labels_extension.push_back(neighbor_it->second);
00923 growSVRecursively(neighbor_it->second,
00924 labels_extension,
00925 supervoxel_adjacency,
00926 sv_containing_supporting_features,
00927 distance_to_feature_sv,
00928 labels_of_segments_to_extend);
00929 }
00930 }
00931 }
00932
00933 void ShapeReconstruction::_ExtendPointsToRegions()
00934 {
00935 std::vector<uint32_t> labels_to_extend;
00936
00937
00938 pcl::PointCloud<pcl::PointXYZL>::Ptr labeled_cloud = (*_supervoxelizer_ptr_ptr)->getLabeledCloud();
00939
00940
00941 pcl::PointCloud<pcl::PointXYZL>::Ptr labeled_cloud_not_nans(new pcl::PointCloud<pcl::PointXYZL>());
00942 std::vector<int> unused;
00943 pcl::removeNaNFromPointCloud< pcl::PointXYZL >(*labeled_cloud, *labeled_cloud_not_nans, unused);
00944
00945
00946 omip::SRPointCloud::Ptr labeled_cloud_not_nans_xyzrgb(new omip::SRPointCloud);
00947 pcl::copyPointCloud(*labeled_cloud_not_nans, *labeled_cloud_not_nans_xyzrgb);
00948
00949
00950 this->_knn->setInputCloud(labeled_cloud_not_nans_xyzrgb);
00951
00952
00953 pcl::PointCloud<pcl::PointXYZ>::Ptr supporting_feats_no_labels(new pcl::PointCloud<pcl::PointXYZ>);
00954 pcl::copyPointCloud(*this->_supporting_features, *supporting_feats_no_labels);
00955
00956
00957
00958 for(int idx_sf =0; idx_sf<supporting_feats_no_labels->points.size(); idx_sf++)
00959 {
00960 std::vector<int> neighbors;
00961 std::vector<float> distances;
00962 this->_knn->nearestKSearchT<pcl::PointXYZ>(supporting_feats_no_labels->points[idx_sf], 1, neighbors, distances);
00963 if(std::find(labels_to_extend.begin(), labels_to_extend.end(), labeled_cloud_not_nans->points[neighbors[0]].label) == labels_to_extend.end())
00964 {
00965 if(labeled_cloud_not_nans->points[neighbors[0]].label != 0 )
00966 {
00967 labels_to_extend.push_back(labeled_cloud_not_nans->points[neighbors[0]].label);
00968 }
00969 }
00970 }
00971
00972
00973
00974
00975 omip::SRPointCloud::Ptr model_in_current_frame(new omip::SRPointCloud);
00976 std::vector<std::vector<int > > indices_model;
00977 std::vector<std::vector<float > > unused2;
00978 unused.clear();
00979 if(this->_rb_shape->points.size())
00980 {
00981 pcl::transformPointCloud<SRPoint>(*this->_rb_shape, *model_in_current_frame, this->_current_HTransform.cast<float>());
00982 this->_knn->radiusSearch(*model_in_current_frame, unused, this->_knn_min_radius, indices_model, unused2);
00983 }
00984
00985
00986
00987 std::map<uint32_t, std::unordered_set<int> > labels_of_segments_to_extend;
00988 for (unsigned int i = 0; i < indices_model.size(); i++)
00989 {
00990 for(unsigned int k=0; k < indices_model[i].size(); k++)
00991 {
00992 if(indices_model[i].at(k))
00993 {
00994
00995 if(labels_of_segments_to_extend.find(labeled_cloud_not_nans->points.at(indices_model[i].at(k)).label) == labels_of_segments_to_extend.end())
00996 {
00997 std::unordered_set<int> initial_set_of_indices = {indices_model[i].at(k)};
00998 labels_of_segments_to_extend[labeled_cloud_not_nans->points.at(indices_model[i].at(k)).label] = initial_set_of_indices;
00999 }
01000 else{
01001
01002 if(labels_of_segments_to_extend.at(labeled_cloud_not_nans->points.at(indices_model[i].at(k)).label).find(indices_model[i].at(k))
01003 == labels_of_segments_to_extend.at(labeled_cloud_not_nans->points.at(indices_model[i].at(k)).label).end())
01004 {
01005 labels_of_segments_to_extend.at(labeled_cloud_not_nans->points.at(indices_model[i].at(k)).label).insert(indices_model[i].at(k));
01006 }
01007 }
01008 }
01009 }
01010 }
01011
01012 std::map<uint32_t, std::unordered_set<int> >::iterator it = labels_of_segments_to_extend.begin();
01013 std::map<uint32_t, std::unordered_set<int> >::iterator itend = labels_of_segments_to_extend.end();
01014
01015 for(; it != itend; it++)
01016 {
01017 if(it->second.size() > _min_number_model_pixels_in_sv && std::find(labels_to_extend.begin(), labels_to_extend.end(), it->first) == labels_to_extend.end())
01018 {
01019 if(it->first != 0)
01020 {
01021 labels_to_extend.push_back(it->first);
01022 }
01023 }
01024 }
01025
01026
01027 std::multimap<uint32_t, uint32_t> supervoxel_adjacency;
01028 (*_supervoxelizer_ptr_ptr)->getSupervoxelAdjacency (supervoxel_adjacency);
01029
01030 ROS_INFO_STREAM_NAMED("ShapeReconstruction._ExtendPointsToRegions",
01031 "[RB" << this->_rb_id << "]: Superpixels to extend the results: " << labels_to_extend.size());
01032
01033 if(this->_extend_to_neighbor_sv)
01034 {
01035 this->_ExtendToNeighborSV(supervoxel_adjacency, labels_to_extend);
01036
01037 ROS_INFO_STREAM_NAMED("ShapeReconstruction._ExtendPointsToRegions",
01038 "[RB" << this->_rb_id << "]: Superpixels to extend the results (after extending to SV of similar properties): " << labels_to_extend.size());
01039 }
01040
01041
01042 shape_reconstruction::PassThrough<pcl::PointXYZL>::Ptr pt_filter(new shape_reconstruction::PassThrough<pcl::PointXYZL>());
01043 pt_filter->setInputCloud(boost::shared_ptr<pcl::PointCloud<pcl::PointXYZL> >(labeled_cloud_not_nans));
01044 pt_filter->setFilterFieldName("label");
01045 omip::SRPointCloud::Ptr points_of_current_in_origin(new omip::SRPointCloud);
01046 pcl::transformPointCloud<SRPoint>(*this->_current_ffs._pc_without_nans, *points_of_current_in_origin, this->_current_HTransform_inv.cast<float>());
01047
01048 pt_filter->setLabels(labels_to_extend);
01049
01050 boost::shared_ptr<std::vector<int> > passing_indices_ptr = boost::shared_ptr<std::vector<int> >(new std::vector<int>());
01051 pt_filter->filter(*passing_indices_ptr);
01052
01053 ROS_INFO_STREAM_NAMED("ShapeReconstruction._ExtendPointsToRegions",
01054 "[RB" << this->_rb_id << "]: Adding " << (*passing_indices_ptr).size() << " points to the extended model (currently " <<this->_rb_shape->width << " points)");
01055 for (unsigned int i = 0; i < (*passing_indices_ptr).size(); i++)
01056 {
01057 this->_rb_shape->points.push_back(points_of_current_in_origin->points[(*passing_indices_ptr)[i]]);
01058 this->_rb_shape->width++;
01059 }
01060 }
01061
01062 void ShapeReconstruction::_ExtendToNeighborSV(std::multimap<uint32_t, uint32_t>& supervoxel_adjacency,
01063 std::vector<uint32_t>& labels_extension)
01064 {
01065
01066
01067 int number_of_sv = _supervoxel_clusters_ptr->size();
01068 std::vector<uint32_t> labels_extension_safety_copy = labels_extension;
01069
01070
01071 std::pair< std::multimap<uint32_t, uint32_t>::iterator, std::multimap<uint32_t, uint32_t>::iterator > neighbors;
01072
01073 int num_extended_labels = labels_extension.size();
01074 int num_extended_labels_with_neigbors = 0;
01075
01076
01077 while(num_extended_labels != num_extended_labels_with_neigbors)
01078 {
01079 num_extended_labels = labels_extension.size();
01080 std::vector<uint32_t> labels_extension_copy = labels_extension;
01081 for(std::vector<uint32_t>::iterator labels_it = labels_extension.begin(); labels_it!=labels_extension.end(); labels_it++)
01082 {
01083
01084 neighbors =supervoxel_adjacency.equal_range(*labels_it);
01085
01086
01087 if(_supervoxel_clusters_ptr->find(*labels_it) != _supervoxel_clusters_ptr->end())
01088 {
01089 pcl::Supervoxel<pcl::PointXYZRGB>::Ptr sv = _supervoxel_clusters_ptr->at(*labels_it);
01090
01091
01092 Eigen::Vector3d sv_normal(sv->normal_.data_n[0], sv->normal_.data_n[1], sv->normal_.data_n[2]);
01093
01094
01095 pcl::PointXYZRGB sv_centroid_xyzrgb( sv->centroid_.r, sv->centroid_.g, sv->centroid_.b);
01096 sv_centroid_xyzrgb.x = sv->centroid_.x;
01097 sv_centroid_xyzrgb.y = sv->centroid_.y;
01098 sv_centroid_xyzrgb.z = sv->centroid_.z;
01099
01100
01101 pcl::PointXYZHSV sv_centroid_xyzhsv;
01102 pcl::PointXYZRGBtoXYZHSV(sv_centroid_xyzrgb, sv_centroid_xyzhsv);
01103
01104
01105 for(std::multimap<uint32_t, uint32_t>::iterator neighbor_it = neighbors.first; neighbor_it!= neighbors.second; ++neighbor_it)
01106 {
01107
01108 if(std::find(labels_extension_copy.begin(), labels_extension_copy.end(), neighbor_it->second) == labels_extension_copy.end() )
01109 {
01110
01111 pcl::Supervoxel<pcl::PointXYZRGB>::Ptr nsv = _supervoxel_clusters_ptr->at(neighbor_it->second);
01112
01113
01114 Eigen::Vector3d nsv_normal(nsv->normal_.data_n[0], nsv->normal_.data_n[1], nsv->normal_.data_n[2]);
01115
01116
01117 pcl::PointXYZRGB nsv_centroid_xyzrgb( nsv->centroid_.r, nsv->centroid_.g, nsv->centroid_.b);
01118 nsv_centroid_xyzrgb.x = nsv->centroid_.x;
01119 nsv_centroid_xyzrgb.y = nsv->centroid_.y;
01120 nsv_centroid_xyzrgb.z = nsv->centroid_.z;
01121
01122
01123 pcl::PointXYZHSV nsv_centroid_xyzhsv;
01124 pcl::PointXYZRGBtoXYZHSV(nsv_centroid_xyzrgb, nsv_centroid_xyzhsv);
01125
01126
01127
01128 double h_diff = std::fabs(sv_centroid_xyzhsv.h - nsv_centroid_xyzhsv.h);
01129 h_diff = std::fmod(h_diff, 360.0);
01130 h_diff = h_diff > 180.0 ? 360.0 - h_diff : h_diff;
01131
01132
01133 if(std::fabs(sv_normal.dot(nsv_normal) - 1.0) < _similarity_in_normal*(M_PI/180.0) && h_diff < _similarity_in_h)
01134 {
01135 labels_extension_copy.push_back(neighbor_it->second);
01136 }
01137 }
01138 }
01139 }
01140 }
01141 num_extended_labels_with_neigbors = labels_extension_copy.size();
01142 labels_extension = labels_extension_copy;
01143 }
01144
01145
01146 int added_supervoxels = labels_extension.size() - labels_extension_safety_copy.size();
01147
01148 if((double)added_supervoxels/(double)number_of_sv > 0.2 )
01149 {
01150 ROS_INFO_STREAM_NAMED("ShapeReconstruction._ExtendPointsToRegions","We are adding too many supervoxels! Undo!");
01151 labels_extension = labels_extension_safety_copy;
01152 }
01153 }
01154
01155 void ShapeReconstruction::_EstimateTransformations()
01156 {
01157 ROSTwist2EigenTwist(this->_previous_ffs._transformation.twist, this->_previous_twist);
01158 Twist2TransformMatrix(this->_previous_twist, this->_previous_HTransform);
01159 this->_previous_HTransform_inv = this->_previous_HTransform.inverse();
01160
01161 ROSTwist2EigenTwist(this->_current_ffs._transformation.twist, this->_current_twist);
01162 Twist2TransformMatrix(this->_current_twist, this->_current_HTransform);
01163 this->_current_HTransform_inv = this->_current_HTransform.inverse();
01164
01165 ROS_DEBUG_STREAM_NAMED("ShapeReconstruction._EstimateTransformations", "[RB" << this->_rb_id << "]: _current_HTransform " << std::endl <<
01166 _current_HTransform);
01167
01168 this->_current_to_previous_HTransform = this->_current_HTransform*this->_previous_HTransform_inv;
01169
01170 this->_previous_to_current_HTransform = this->_current_to_previous_HTransform.inverse();
01171
01172 ROS_DEBUG_STREAM_NAMED("ShapeReconstruction._EstimateTransformations", "[RB" << this->_rb_id << "]: current to previous " << std::endl <<
01173 _current_to_previous_HTransform);
01174 }
01175
01176 void ShapeReconstruction::_GenerateMesh(const omip::SRPointCloud::Ptr& pc_source,
01177 std::string shape_file_prefix)
01178 {
01179 if(pc_source->points.size())
01180 {
01181
01182 this->_rb_tree_for_normal_estimation_ptr->setInputCloud(pc_source);
01183 this->_rb_normal_estimator_ptr->setInputCloud(pc_source);
01184 this->_rb_normal_estimator_ptr->setSearchMethod (this->_rb_tree_for_normal_estimation_ptr);
01185 this->_rb_normal_estimator_ptr->compute(*this->_rb_estimated_normals_pc_ptr);
01186
01187
01188 pcl::concatenateFields (*pc_source, *this->_rb_estimated_normals_pc_ptr, *this->_rb_position_color_and_normals_pc_ptr);
01189 this->_rb_tree_for_triangulation_ptr->setInputCloud (this->_rb_position_color_and_normals_pc_ptr);
01190
01191
01192 this->_rb_greedy_projection_triangulator_ptr->setInputCloud(this->_rb_position_color_and_normals_pc_ptr);
01193 this->_rb_greedy_projection_triangulator_ptr->setSearchMethod(this->_rb_tree_for_triangulation_ptr);
01194 this->_rb_greedy_projection_triangulator_ptr->reconstruct(*this->_rb_triangulated_mesh_ptr);
01195
01196
01197
01198
01199
01200 std::string mesh_path = ros::package::getPath("shape_reconstruction") + std::string("/meshes/");
01201 std::stringstream rb_name_ss;
01202 rb_name_ss << shape_file_prefix << this->_rb_id << ".stl";
01203
01204 std::string rb_mesh_full_file_name = mesh_path + rb_name_ss.str();
01205
01206 pcl::io::mesh2vtk(*this->_rb_triangulated_mesh_ptr, this->_rb_polygon_data_ptr);
01207
01208 this->_rb_polygon_writer_ptr->SetInput (this->_rb_polygon_data_ptr);
01209 this->_rb_polygon_writer_ptr->SetFileName (rb_mesh_full_file_name.c_str ());
01210 this->_rb_polygon_writer_ptr->Write ();
01211
01212 ROS_INFO_STREAM_NAMED("ShapeReconstruction.generateMesh", "[RB" << this->_rb_id << "]: Resulting triangular mesh written to " << rb_mesh_full_file_name);
01213 }else{
01214 ROS_WARN_STREAM_NAMED("ShapeReconstruction.generateMesh", "[RB" << this->_rb_id << "]: Impossible to generate a triangular mesh for this model, it doesn't contain any points!");
01215 }
01216 }
01217
01218 void ShapeReconstruction::generateMesh()
01219 {
01220 ROS_INFO_STREAM_NAMED("ShapeReconstruction.generateMesh", "[RB" << this->_rb_id << "]: Called the generation of 3D triangular mesh from the model of RB" << this->_rb_id <<
01221 " based on extending other models with supervoxels.");
01222 std::string shape_ext_d_and_c_file_prefix("shape_ext_d_and_c_rb");
01223 this->_GenerateMesh(this->_rb_shape, shape_ext_d_and_c_file_prefix);
01224
01225
01226 ROS_INFO_STREAM_NAMED("ShapeReconstruction.generateMesh", "[RB" << this->_rb_id << "]: Finished the generation of 3D triangular mesh from the point cloud of RB " << this->_rb_id);
01227 }
01228
01229 void ShapeReconstruction::getShapeModel(omip_msgs::ShapeModelsPtr shapes)
01230 {
01231 omip_msgs::ShapeModel shape;
01232 shape.rb_id = this->_rb_id;
01233 sensor_msgs::PointCloud2 rb_shape_ros;
01234 rb_shape_ros.header.frame_id = "/camera_rgb_optical_frame";
01235
01236 this->_rb_shape->header = this->_current_ffs._pc->header;
01237 pcl::toROSMsg(*this->_rb_shape, rb_shape_ros);
01238
01239 shape.rb_shape_model = rb_shape_ros;
01240 shapes->rb_shape_models.push_back(shape);
01241 }
01242
01243 void ShapeReconstruction::PublishMovedModelAndSegment(const ros::Time current_time,
01244 const geometry_msgs::TwistWithCovariance &rb_transformation,
01245 rosbag::Bag& bag,
01246 bool bagOpen)
01247 {
01248 Eigen::Twistd current_twist;
01249 ROSTwist2EigenTwist(rb_transformation.twist, current_twist);
01250
01251 Eigen::Matrix4d current_HTransform;
01252 Twist2TransformMatrix(current_twist, current_HTransform);
01253
01254 ROS_INFO_STREAM_NAMED("ShapeReconstruction._PublishMovedModel", "[RB" << this->_rb_id << "]: Publishing " << this->_rb_shape->points.size() << " points reconstructed from RB" << this->_rb_id
01255 << " based on extending both depth and color model with supervoxels.");
01256 this->_rb_shape->header = this->_current_ffs._pc->header;
01257 this->_rb_shape->header.frame_id = "/camera_rgb_optical_frame";
01258 this->_rb_shape_in_current_frame.reset(new omip::SRPointCloud);
01259 pcl::transformPointCloud<SRPoint>(*this->_rb_shape, *this->_rb_shape_in_current_frame, current_HTransform.cast<float>());
01260 sensor_msgs::PointCloud2 rb_shape_ext_d_and_c_in_current_frame_ros;
01261 pcl::toROSMsg(*this->_rb_shape_in_current_frame, rb_shape_ext_d_and_c_in_current_frame_ros);
01262 rb_shape_ext_d_and_c_in_current_frame_ros.header.frame_id = "/camera_rgb_optical_frame";
01263 this->_rb_shape_pub.publish(rb_shape_ext_d_and_c_in_current_frame_ros);
01264
01265 if (bagOpen){
01266 bag.write(_rb_shape_pub.getTopic(), current_time, rb_shape_ext_d_and_c_in_current_frame_ros);
01267 }
01268
01269
01270 {
01271 this->_rb_segment->header = this->_current_ffs._pc->header;
01272 this->_rb_segment->header.frame_id = "/camera_rgb_optical_frame";
01273 sensor_msgs::PointCloud2 rb_segment_in_current_frame_ros;
01274 pcl::toROSMsg(*this->_rb_segment, rb_segment_in_current_frame_ros);
01275 rb_segment_in_current_frame_ros.header.frame_id = "/camera_rgb_optical_frame";
01276 this->_rb_segment_pub.publish(rb_segment_in_current_frame_ros);
01277 if (bagOpen){
01278 bag.write(_rb_segment_pub.getTopic(), current_time, rb_segment_in_current_frame_ros);
01279 }
01280 }
01281 }
01282
01283 void ShapeReconstruction::RemoveInconsistentPoints(const SRPointCloud::Ptr &pc_msg,
01284 const geometry_msgs::TwistWithCovariance &rb_transformation)
01285 {
01286 Eigen::Twistd current_twist;
01287 ROSTwist2EigenTwist(rb_transformation.twist, current_twist);
01288 Eigen::Matrix4d current_HTransform;
01289 Twist2TransformMatrix(current_twist, current_HTransform);
01290
01291 SRPointCloud::Ptr current_pc(new SRPointCloud());
01292 pcl::copyPointCloud(*pc_msg, *current_pc);
01293
01294
01295 cv::Mat current_dm;
01296 this->_current_ffs._dm->image.copyTo(current_dm);
01297 OrganizedPC2DepthMap(current_pc, current_dm);
01298
01299 this->_RemoveInconsistentPointsFromRBModel("", current_HTransform, this->_rb_shape, current_dm,current_pc, this->_rb_segment);
01300
01301 }