depth_segmentation.hpp
Go to the documentation of this file.
00001 
00063 #ifndef __IMPL_DEPTH_SEGMENTATION_HPP__
00064 #define __IMPL_DEPTH_SEGMENTATION_HPP__
00065 
00066 #include <set>
00067 
00068 #include <pcl/common/eigen.h>
00069 #include <Eigen/LU>
00070 
00071 #include "cob_3d_mapping_common/label_defines.h"
00072 #include "cob_3d_segmentation/depth_segmentation.h"
00073 #include "cob_3d_features/organized_normal_estimation.h"
00074 
00075 template <typename ClusterGraphT, typename PointT, typename PointNT, typename PointLabelT> void
00076 cob_3d_segmentation::DepthSegmentation<ClusterGraphT,PointT,PointNT,PointLabelT>::addIfIsValid(
00077   int u, int v, int idx, int idx_prev, float dist_th, float p_z, Eigen::Vector3f& n,
00078   SegmentationQueue& seg_queue, ClusterPtr c)
00079 {
00080   if (p_z < 1.2)
00081   {
00082     if (fabs(p_z - surface_->points[idx].z) > (dist_th + 0.01f)) return;
00083   }
00084   else if (fabs(p_z - surface_->points[idx].z) > dist_th) return;
00085   int* p_label = &(labels_->points[idx].label);
00086   if (*p_label == I_UNDEF)
00087   {
00088 
00089     /*float angle = fabs( atan2((n.cross(normals_->points[idx].getNormalVector3fMap())).norm(),
00090       n.dot(normals_->points[idx].getNormalVector3fMap())) );*/
00091     float dot_value = fabs( n.dot(normals_->points[idx].getNormalVector3fMap()) );
00092     if ( (int)c->size() < min_cluster_size_ || dot_value > min_dot_normals_)
00093     {
00094       *p_label = c->id();
00095       seg_queue.push( SegmentationCandidate::Ptr(new SegmentationCandidate(u, v, dot_value)) );
00096     }
00097   }
00098   else if (*p_label > I_EDGE && c->id() != *p_label)
00099   {
00100     graph_->edges()->updateProperties(graph_->connect(c->id(), *p_label), c->id(), idx_prev, *p_label, idx);
00101   }
00102 }
00103 
00104 template <typename ClusterGraphT, typename PointT, typename PointNT, typename PointLabelT> void
00105 cob_3d_segmentation::DepthSegmentation<ClusterGraphT,PointT,PointNT,PointLabelT>::performInitialSegmentation()
00106 {
00107   int width = labels_->width, height = labels_->height;
00108   // reset graph and property handlers:
00109   graph_->clear();
00110   graph_->clusters()->setLabelCloudInOut(labels_);
00111   graph_->clusters()->setPointCloudIn(surface_);
00112   graph_->clusters()->setNormalCloudIn(normals_);
00113   graph_->edges()->setLabelCloudIn(labels_);
00114   graph_->edges()->setPointCloudIn(surface_);
00115   graph_->clusters()->createCluster(I_NAN)->type = I_NAN;
00116   graph_->clusters()->createCluster(I_BORDER)->type = I_BORDER;
00117   graph_->clusters()->createCluster(I_EDGE)->type = I_EDGE;
00118 
00119   // fire!
00120   for(size_t i=0; i<labels_->points.size(); ++i)
00121   {
00122     if (labels_->points[i].label == I_UNDEF)
00123     {
00124       ClusterPtr c = graph_->clusters()->createCluster();
00125       //std::multiset<SegmentationCandidate> seg_queue;
00126       SegmentationQueue seg_queue;
00127       seg_queue.push( SegmentationCandidate::Ptr(new SegmentationCandidate(i%width, i/width, 0.0)) );
00128       labels_->points[i].label = c->id();
00129       while (seg_queue.size() != 0)
00130       {
00131         SegmentationCandidate p = *seg_queue.top(); // get point with max dot_value!
00132         seg_queue.pop();
00133         int p_idx = p.v * width + p.u;
00134         float p_z = surface_->points[p_idx].z;
00135         float dist_th = 2.0 * 0.003 * p_z * p_z;
00136         graph_->clusters()->addPoint(c, p_idx); // clusterhandler takes care of properties
00137 
00138         Eigen::Vector3f n_n = c->getOrientation();
00139         // Look right
00140         if (p.u+1 < width) { addIfIsValid(p.u+1, p.v, p_idx+1, p_idx, dist_th, p_z, n_n, seg_queue, c); }
00141         // Look down
00142         if (p.v+1 < height) { addIfIsValid(p.u, p.v+1, p_idx+width, p_idx, dist_th, p_z, n_n, seg_queue, c); }
00143         // Look left
00144         if (p.u > 0) { addIfIsValid(p.u-1, p.v, p_idx-1, p_idx, dist_th, p_z, n_n, seg_queue, c); }
00145         // Look up
00146         if (p.v > 0) { addIfIsValid(p.u, p.v-1, p_idx-width, p_idx, dist_th, p_z, n_n, seg_queue, c); }
00147       } // end while
00148 
00149       // merge small clusters
00150       /*
00151       if (c->size() < min_cluster_size_)
00152       {
00153         std::vector<ClusterPtr> adj_list;
00154         graph_->getAdjacentClusters(c->id(), adj_list);
00155         if (adj_list.size() != 0)
00156         {
00157           int max_cluster_id = adj_list.front()->id();
00158           int max_edge_width = 0;
00159           for (typename std::vector<ClusterPtr>::iterator it = adj_list.begin(); it != adj_list.end(); ++it)
00160           {
00161             EdgePtr e = graph_->getConnection(c->id(), (*it)->id());
00162             if (e->size() > max_edge_width) { max_cluster_id = (*it)->id(); max_edge_width = e->size(); }
00163           }
00164           graph_->merge( c->id(), max_cluster_id );
00165         }
00166       }
00167       */
00168     }
00169     else if(labels_->points[i].label <= I_EDGE)
00170     {
00171       graph_->clusters()->getCluster(labels_->points[i].label)->addIndex(i);
00172     }
00173     else
00174       continue;
00175   }
00176   return;
00177 }
00178 
00179 template <typename ClusterGraphT, typename PointT, typename PointNT, typename PointLabelT> void
00180 cob_3d_segmentation::DepthSegmentation<ClusterGraphT,PointT,PointNT,PointLabelT>::refineSegmentation()
00181 {
00182   graph_->clusters()->addBorderIndicesToClusters();
00183   graph_->clusters()->sortBySize(); // Ascending order
00184   ClusterPtr c_it, c_end;
00185   for (boost::tie(c_it,c_end) = graph_->clusters()->getClusters(); c_it != c_end; ++c_it)
00186   {
00187     //std::cout << c_it->size() << std::endl;
00188     if (c_it->size() < 20) continue;
00189     if (c_it->type == I_EDGE || c_it->type == I_NAN || c_it->type == I_BORDER) continue;
00190     computeBoundaryProperties(c_it);
00191   }
00192   computeEdgeSmoothness();
00193   for ( --c_end; c_end != graph_->clusters()->begin(); --c_end) // iterate from back to front
00194   {
00195     if ( c_end->size() < 5 ) continue;
00196     if ( c_end->type == I_EDGE || c_end->type == I_NAN || c_end->type == I_BORDER) continue;
00197     std::vector<ClusterPtr> adj_list;
00198     //graph_->getConnectedClusters(c_end->id(), adj_list, graph_->edges()->edge_validator);
00199     graph_->getAdjacentClusters(c_end->id(), adj_list);
00200     for (typename std::vector<ClusterPtr>::iterator a_it = adj_list.begin(); a_it != adj_list.end(); ++a_it)
00201     {
00202       EdgePtr e = graph_->getConnection(c_end->id(), (*a_it)->id());
00203       if ( e->smoothness < 0.8 ) continue;
00204       //std::cout << sqrt((*a_it)->size()) * 1.0f << " > " << e->size() << std::endl;
00205       if ( e->size() < sqrt((*a_it)->size()) * 0.6f ) continue;
00206       std::vector<EdgePtr> updated_edges;
00207       graph_->merge( (*a_it)->id(), c_end->id(), updated_edges );
00208       for (typename std::vector<EdgePtr>::iterator e_it = updated_edges.begin(); e_it != updated_edges.end(); ++e_it)
00209       {
00210         computeBoundaryProperties(c_end, *e_it);
00211         computeEdgeSmoothness(*e_it);
00212       }
00213     }
00214   }
00215   graph_->clusters()->addBorderIndicesToClusters();
00216 }
00217 
00218 template <typename ClusterGraphT, typename PointT, typename PointNT, typename PointLabelT> void
00219 cob_3d_segmentation::DepthSegmentation<ClusterGraphT,PointT,PointNT,PointLabelT>::computeBoundaryProperties(
00220   ClusterPtr c, EdgePtr e)
00221 {
00222   int window_size = ceil( std::min( sqrt( static_cast<float>(c->size()) ) / e->boundary_pairs[c->id()].size()
00223                                     + pow(c->getCentroid()(2), 2) + 5.0, 30.0) );
00224   for (std::list<int>::iterator b_it = e->boundary_pairs[c->id()].begin(); b_it != e->boundary_pairs[c->id()].end(); ++b_it)
00225   {
00226     cob_3d_features::OrganizedNormalEstimationHelper::computeSegmentNormal<PointT,PointLabelT>(
00227       graph_->edges()->getBoundaryPoint(*b_it).normal, *b_it, surface_, labels_, window_size, 1);
00228   }
00229 }
00230 
00231 template <typename ClusterGraphT, typename PointT, typename PointNT, typename PointLabelT> void
00232 cob_3d_segmentation::DepthSegmentation<ClusterGraphT,PointT,PointNT,PointLabelT>::computeBoundaryProperties(ClusterPtr c)
00233 {
00234   std::vector<ClusterPtr> adj_list;
00235   graph_->getAdjacentClusters(c->id(), adj_list);
00236   //if (adj_list.size()) std::cout << c->size() << " : " << std::endl;
00237   for (typename std::vector<ClusterPtr>::iterator a_it = adj_list.begin(); a_it != adj_list.end(); ++a_it)
00238   {
00239     //std::cout << (*a_it)->size() << ", " << std::endl;
00240     computeBoundaryProperties(c, graph_->getConnection(c->id(), (*a_it)->id()));
00241   }
00242 }
00243 
00244 template <typename ClusterGraphT, typename PointT, typename PointNT, typename PointLabelT> void
00245 cob_3d_segmentation::DepthSegmentation<ClusterGraphT,PointT,PointNT,PointLabelT>::computeEdgeSmoothness(EdgePtr e)
00246 {
00247   int smooth_points = 0;
00248   std::list<int>::iterator bp_it, bp_end;
00249   for (boost::tie(bp_it,bp_end) = e->getBoundaryPairs(); bp_it != bp_end; ++bp_it)
00250   {
00251     BoundaryPoint bp_this = graph_->edges()->getBoundaryPoint(*bp_it);
00252     /*float angle = fabs( atan2(bp_this.normal.cross(graph_->edges()->getBoundaryPoint(bp_this.brother).normal).norm(),
00253       bp_this.normal.dot(graph_->edges()->getBoundaryPoint(bp_this.brother).normal)) );*/
00254     //if (angle < max_boundary_angle_)
00255     // No fabs for dot product here, normals are correct aligned
00256     if (bp_this.normal.dot(graph_->edges()->getBoundaryPoint(bp_this.brother).normal) > min_dot_boundary_)
00257       ++smooth_points;
00258   }
00259   e->smoothness = static_cast<float>(smooth_points) / static_cast<float>(e->size());
00260 }
00261 
00262 template <typename ClusterGraphT, typename PointT, typename PointNT, typename PointLabelT> void
00263 cob_3d_segmentation::DepthSegmentation<ClusterGraphT,PointT,PointNT,PointLabelT>::computeEdgeSmoothness()
00264 {
00265   EdgePtr e_it, e_end;
00266   for (boost::tie(e_it,e_end) = graph_->edges()->getEdges(); e_it != e_end; ++e_it) { computeEdgeSmoothness(e_it); }
00267 }
00268 
00269 template <typename ClusterGraphT, typename PointT, typename PointNT, typename PointLabelT> void
00270 cob_3d_segmentation::DepthSegmentation<ClusterGraphT,PointT,PointNT,PointLabelT>::getPotentialObjects(
00271   std::map<int,int>& objs, int max_size) //objs[cluster_id] = object_id
00272 {
00273   std::set<int> processed;
00274   ClusterPtr c_it, c_end;
00275   int obj_counter = 0, prev_size;
00276   for ( boost::tie(c_it,c_end) = graph_->clusters()->getClusters(); c_it != c_end; ++c_it )
00277   {
00278     if (processed.find(c_it->id()) != processed.end()) continue;
00279     processed.insert(c_it->id());
00280     if (c_it->size() > max_size) continue;
00281     objs[c_it->id()] = obj_counter;
00282     prev_size = objs.size();
00283     addSmallNeighbors(c_it, objs, processed, obj_counter, max_size);
00284     if (objs.size() == prev_size) objs.erase(c_it->id());
00285     else ++obj_counter;
00286   }
00287 }
00288 
00289 template <typename ClusterGraphT, typename PointT, typename PointNT, typename PointLabelT> void
00290 cob_3d_segmentation::DepthSegmentation<ClusterGraphT,PointT,PointNT,PointLabelT>::addSmallNeighbors(
00291   ClusterPtr c, std::map<int,int>& objs, std::set<int>& processed, int obj_counter, int max_size)
00292 {
00293   std::vector<ClusterPtr> c_adj;
00294   graph_->getAdjacentClusters(c->id(),c_adj);
00295   for (typename std::vector<ClusterPtr>::iterator it=c_adj.begin(); it!=c_adj.end(); ++it)
00296   {
00297     if (processed.find((*it)->id()) != processed.end()) continue;
00298     processed.insert((*it)->id());
00299     if ((*it)->size() > max_size) continue;
00300 
00301     objs[(*it)->id()] = obj_counter;
00302     addSmallNeighbors(*it, objs, processed, obj_counter, max_size);
00303   }
00304   return;
00305 }
00306 
00307 #endif


cob_3d_segmentation
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:03:03