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
00090
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
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
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
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();
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);
00137
00138 Eigen::Vector3f n_n = c->getOrientation();
00139
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
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
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
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 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
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();
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
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)
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
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
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
00237 for (typename std::vector<ClusterPtr>::iterator a_it = adj_list.begin(); a_it != adj_list.end(); ++a_it)
00238 {
00239
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
00253
00254
00255
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)
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