00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * * Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * * Redistributions in binary form must reproduce the above 00015 * copyright notice, this list of conditions and the following 00016 * disclaimer in the documentation and/or other materials provided 00017 * with the distribution. 00018 * * Neither the name of Willow Garage, Inc. nor the names of its 00019 * contributors may be used to endorse or promote products derived 00020 * from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00030 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00032 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00033 * POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 * Author : jpapon@gmail.com 00036 * Email : jpapon@gmail.com 00037 * 00038 */ 00039 00040 #ifndef PCL_SEGMENTATION_SUPERVOXEL_CLUSTERING_HPP_ 00041 #define PCL_SEGMENTATION_SUPERVOXEL_CLUSTERING_HPP_ 00042 00043 #include <pcl/segmentation/supervoxel_clustering.h> 00044 00045 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00046 template <typename PointT> 00047 pcl::SupervoxelClustering<PointT>::SupervoxelClustering (float voxel_resolution, float seed_resolution, bool use_single_camera_transform) : 00048 resolution_ (voxel_resolution), 00049 seed_resolution_ (seed_resolution), 00050 adjacency_octree_ (), 00051 voxel_centroid_cloud_ (), 00052 color_importance_(0.1f), 00053 spatial_importance_(0.4f), 00054 normal_importance_(1.0f), 00055 label_colors_ (0) 00056 { 00057 adjacency_octree_ = boost::make_shared <OctreeAdjacencyT> (resolution_); 00058 if (use_single_camera_transform) 00059 adjacency_octree_->setTransformFunction (boost::bind (&SupervoxelClustering::transformFunction, this, _1)); 00060 } 00061 00062 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00063 template <typename PointT> 00064 pcl::SupervoxelClustering<PointT>::~SupervoxelClustering () 00065 { 00066 00067 } 00068 00069 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00070 template <typename PointT> void 00071 pcl::SupervoxelClustering<PointT>::setInputCloud (typename pcl::PointCloud<PointT>::ConstPtr cloud) 00072 { 00073 if ( cloud->size () == 0 ) 00074 { 00075 PCL_ERROR ("[pcl::SupervoxelClustering::setInputCloud] Empty cloud set, doing nothing \n"); 00076 return; 00077 } 00078 00079 input_ = cloud; 00080 adjacency_octree_->setInputCloud (cloud); 00081 } 00082 00083 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00084 template <typename PointT> void 00085 pcl::SupervoxelClustering<PointT>::setNormalCloud (typename NormalCloudT::ConstPtr normal_cloud) 00086 { 00087 if ( normal_cloud->size () == 0 ) 00088 { 00089 PCL_ERROR ("[pcl::SupervoxelClustering::setNormalCloud] Empty cloud set, doing nothing \n"); 00090 return; 00091 } 00092 00093 input_normals_ = normal_cloud; 00094 } 00095 00096 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00097 template <typename PointT> void 00098 pcl::SupervoxelClustering<PointT>::extract (std::map<uint32_t,typename Supervoxel<PointT>::Ptr > &supervoxel_clusters) 00099 { 00100 //timer_.reset (); 00101 //double t_start = timer_.getTime (); 00102 //std::cout << "Init compute \n"; 00103 bool segmentation_is_possible = initCompute (); 00104 if ( !segmentation_is_possible ) 00105 { 00106 deinitCompute (); 00107 return; 00108 } 00109 00110 //std::cout << "Preparing for segmentation \n"; 00111 segmentation_is_possible = prepareForSegmentation (); 00112 if ( !segmentation_is_possible ) 00113 { 00114 deinitCompute (); 00115 return; 00116 } 00117 00118 //double t_prep = timer_.getTime (); 00119 //std::cout << "Placing Seeds" << std::endl; 00120 std::vector<PointT, Eigen::aligned_allocator<PointT> > seed_points; 00121 selectInitialSupervoxelSeeds (seed_points); 00122 //std::cout << "Creating helpers "<<std::endl; 00123 createSupervoxelHelpers (seed_points); 00124 //double t_seeds = timer_.getTime (); 00125 00126 00127 //std::cout << "Expanding the supervoxels" << std::endl; 00128 int max_depth = static_cast<int> (1.8f*seed_resolution_/resolution_); 00129 expandSupervoxels (max_depth); 00130 //double t_iterate = timer_.getTime (); 00131 00132 //std::cout << "Making Supervoxel structures" << std::endl; 00133 makeSupervoxels (supervoxel_clusters); 00134 //double t_supervoxels = timer_.getTime (); 00135 00136 // std::cout << "--------------------------------- Timing Report --------------------------------- \n"; 00137 // std::cout << "Time to prep (normals, neighbors, voxelization)="<<t_prep-t_start<<" ms\n"; 00138 // std::cout << "Time to seed clusters ="<<t_seeds-t_prep<<" ms\n"; 00139 // std::cout << "Time to expand clusters ="<<t_iterate-t_seeds<<" ms\n"; 00140 // std::cout << "Time to create supervoxel structures ="<<t_supervoxels-t_iterate<<" ms\n"; 00141 // std::cout << "Total run time ="<<t_supervoxels-t_start<<" ms\n"; 00142 // std::cout << "--------------------------------------------------------------------------------- \n"; 00143 00144 deinitCompute (); 00145 } 00146 00147 00148 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00149 template <typename PointT> void 00150 pcl::SupervoxelClustering<PointT>::refineSupervoxels (int num_itr, std::map<uint32_t,typename Supervoxel<PointT>::Ptr > &supervoxel_clusters) 00151 { 00152 if (supervoxel_helpers_.size () == 0) 00153 { 00154 PCL_ERROR ("[pcl::SupervoxelClustering::refineVoxelNormals] Supervoxels not extracted, doing nothing - (Call extract first!) \n"); 00155 return; 00156 } 00157 00158 int max_depth = static_cast<int> (1.8f*seed_resolution_/resolution_); 00159 for (int i = 0; i < num_itr; ++i) 00160 { 00161 for (typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr) 00162 { 00163 sv_itr->refineNormals (); 00164 } 00165 00166 reseedSupervoxels (); 00167 expandSupervoxels (max_depth); 00168 } 00169 00170 00171 makeSupervoxels (supervoxel_clusters); 00172 00173 } 00174 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00175 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00176 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00177 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00178 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00179 00180 00181 template <typename PointT> bool 00182 pcl::SupervoxelClustering<PointT>::prepareForSegmentation () 00183 { 00184 00185 // if user forgot to pass point cloud or if it is empty 00186 if ( input_->points.size () == 0 ) 00187 return (false); 00188 00189 //Add the new cloud of data to the octree 00190 //std::cout << "Populating adjacency octree with new cloud \n"; 00191 //double prep_start = timer_.getTime (); 00192 adjacency_octree_->addPointsFromInputCloud (); 00193 //double prep_end = timer_.getTime (); 00194 //std::cout<<"Time elapsed populating octree with next frame ="<<prep_end-prep_start<<" ms\n"; 00195 00196 //Compute normals and insert data for centroids into data field of octree 00197 //double normals_start = timer_.getTime (); 00198 computeVoxelData (); 00199 //double normals_end = timer_.getTime (); 00200 //std::cout << "Time elapsed finding normals and pushing into octree ="<<normals_end-normals_start<<" ms\n"; 00201 00202 return true; 00203 } 00204 00205 template <typename PointT> void 00206 pcl::SupervoxelClustering<PointT>::computeVoxelData () 00207 { 00208 voxel_centroid_cloud_ = boost::make_shared<PointCloudT> (); 00209 voxel_centroid_cloud_->resize (adjacency_octree_->getLeafCount ()); 00210 typename LeafVectorT::iterator leaf_itr = adjacency_octree_->begin (); 00211 typename PointCloudT::iterator cent_cloud_itr = voxel_centroid_cloud_->begin (); 00212 for (int idx = 0 ; leaf_itr != adjacency_octree_->end (); ++leaf_itr, ++cent_cloud_itr, ++idx) 00213 { 00214 VoxelData& new_voxel_data = (*leaf_itr)->getData (); 00215 //Add the point to the centroid cloud 00216 new_voxel_data.getPoint (*cent_cloud_itr); 00217 //voxel_centroid_cloud_->push_back(new_voxel_data.getPoint ()); 00218 new_voxel_data.idx_ = idx; 00219 } 00220 00221 //If normals were provided 00222 if (input_normals_) 00223 { 00224 //Verify that input normal cloud size is same as input cloud size 00225 assert (input_normals_->size () == input_->size ()); 00226 //For every point in the input cloud, find its corresponding leaf 00227 typename NormalCloudT::const_iterator normal_itr = input_normals_->begin (); 00228 for (typename PointCloudT::const_iterator input_itr = input_->begin (); input_itr != input_->end (); ++input_itr, ++normal_itr) 00229 { 00230 //If the point is not finite we ignore it 00231 if ( !pcl::isFinite<PointT> (*input_itr)) 00232 continue; 00233 //Otherwise look up its leaf container 00234 LeafContainerT* leaf = adjacency_octree_->getLeafContainerAtPoint (*input_itr); 00235 00236 //Get the voxel data object 00237 VoxelData& voxel_data = leaf->getData (); 00238 //Add this normal in (we will normalize at the end) 00239 voxel_data.normal_ += normal_itr->getNormalVector4fMap (); 00240 voxel_data.curvature_ += normal_itr->curvature; 00241 } 00242 //Now iterate through the leaves and normalize 00243 for (leaf_itr = adjacency_octree_->begin (); leaf_itr != adjacency_octree_->end (); ++leaf_itr) 00244 { 00245 VoxelData& voxel_data = (*leaf_itr)->getData (); 00246 voxel_data.normal_.normalize (); 00247 voxel_data.owner_ = 0; 00248 voxel_data.distance_ = std::numeric_limits<float>::max (); 00249 //Get the number of points in this leaf 00250 int num_points = (*leaf_itr)->getPointCounter (); 00251 voxel_data.curvature_ /= num_points; 00252 } 00253 } 00254 else //Otherwise just compute the normals 00255 { 00256 for (leaf_itr = adjacency_octree_->begin (); leaf_itr != adjacency_octree_->end (); ++leaf_itr) 00257 { 00258 VoxelData& new_voxel_data = (*leaf_itr)->getData (); 00259 //For every point, get its neighbors, build an index vector, compute normal 00260 std::vector<int> indices; 00261 indices.reserve (81); 00262 //Push this point 00263 indices.push_back (new_voxel_data.idx_); 00264 for (typename LeafContainerT::iterator neighb_itr=(*leaf_itr)->begin (); neighb_itr!=(*leaf_itr)->end (); ++neighb_itr) 00265 { 00266 VoxelData& neighb_voxel_data = (*neighb_itr)->getData (); 00267 //Push neighbor index 00268 indices.push_back (neighb_voxel_data.idx_); 00269 //Get neighbors neighbors, push onto cloud 00270 for (typename LeafContainerT::iterator neighb_neighb_itr=(*neighb_itr)->begin (); neighb_neighb_itr!=(*neighb_itr)->end (); ++neighb_neighb_itr) 00271 { 00272 VoxelData& neighb2_voxel_data = (*neighb_neighb_itr)->getData (); 00273 indices.push_back (neighb2_voxel_data.idx_); 00274 } 00275 } 00276 //Compute normal 00277 pcl::computePointNormal (*voxel_centroid_cloud_, indices, new_voxel_data.normal_, new_voxel_data.curvature_); 00278 pcl::flipNormalTowardsViewpoint (voxel_centroid_cloud_->points[new_voxel_data.idx_], 0.0f,0.0f,0.0f, new_voxel_data.normal_); 00279 new_voxel_data.normal_[3] = 0.0f; 00280 new_voxel_data.normal_.normalize (); 00281 new_voxel_data.owner_ = 0; 00282 new_voxel_data.distance_ = std::numeric_limits<float>::max (); 00283 } 00284 } 00285 00286 00287 } 00288 00289 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00290 template <typename PointT> void 00291 pcl::SupervoxelClustering<PointT>::expandSupervoxels ( int depth ) 00292 { 00293 00294 00295 for (int i = 1; i < depth; ++i) 00296 { 00297 //Expand the the supervoxels by one iteration 00298 for (typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr) 00299 { 00300 sv_itr->expand (); 00301 } 00302 00303 //Update the centers to reflect new centers 00304 for (typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ) 00305 { 00306 if (sv_itr->size () == 0) 00307 { 00308 sv_itr = supervoxel_helpers_.erase (sv_itr); 00309 } 00310 else 00311 { 00312 sv_itr->updateCentroid (); 00313 ++sv_itr; 00314 } 00315 } 00316 00317 } 00318 00319 } 00320 00321 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00322 template <typename PointT> void 00323 pcl::SupervoxelClustering<PointT>::makeSupervoxels (std::map<uint32_t,typename Supervoxel<PointT>::Ptr > &supervoxel_clusters) 00324 { 00325 supervoxel_clusters.clear (); 00326 for (typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr) 00327 { 00328 uint32_t label = sv_itr->getLabel (); 00329 supervoxel_clusters[label] = boost::make_shared<Supervoxel<PointT> > (); 00330 sv_itr->getXYZ (supervoxel_clusters[label]->centroid_.x,supervoxel_clusters[label]->centroid_.y,supervoxel_clusters[label]->centroid_.z); 00331 sv_itr->getRGB (supervoxel_clusters[label]->centroid_.rgba); 00332 sv_itr->getNormal (supervoxel_clusters[label]->normal_); 00333 sv_itr->getVoxels (supervoxel_clusters[label]->voxels_); 00334 sv_itr->getNormals (supervoxel_clusters[label]->normals_); 00335 } 00336 //Make sure that color vector is big enough 00337 initializeLabelColors (); 00338 } 00339 00340 00341 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00342 template <typename PointT> void 00343 pcl::SupervoxelClustering<PointT>::createSupervoxelHelpers (std::vector<PointT, Eigen::aligned_allocator<PointT> > &seed_points) 00344 { 00345 00346 supervoxel_helpers_.clear (); 00347 for (int i = 0; i < seed_points.size (); ++i) 00348 { 00349 supervoxel_helpers_.push_back (new SupervoxelHelper(i+1,this)); 00350 //Find which leaf corresponds to this seed index 00351 LeafContainerT* seed_leaf = adjacency_octree_->getLeafContainerAtPoint (seed_points[i]); 00352 if (seed_leaf) 00353 { 00354 supervoxel_helpers_.back ().addLeaf (seed_leaf); 00355 } 00356 else 00357 { 00358 PCL_WARN ("Could not find leaf in pcl::SupervoxelClustering<PointT>::createSupervoxelHelpers - supervoxel will be deleted \n"); 00359 } 00360 } 00361 00362 } 00363 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00364 template <typename PointT> void 00365 pcl::SupervoxelClustering<PointT>::selectInitialSupervoxelSeeds (std::vector<PointT, Eigen::aligned_allocator<PointT> > &seed_points) 00366 { 00367 //TODO THIS IS BAD - SEEDING SHOULD BE BETTER 00368 //TODO Switch to assigning leaves! Don't use Octree! 00369 00370 // std::cout << "Size of centroid cloud="<<voxel_centroid_cloud_->size ()<<", seeding resolution="<<seed_resolution_<<"\n"; 00371 //Initialize octree with voxel centroids 00372 pcl::octree::OctreePointCloudSearch <PointT> seed_octree (seed_resolution_); 00373 seed_octree.setInputCloud (voxel_centroid_cloud_); 00374 seed_octree.addPointsFromInputCloud (); 00375 // std::cout << "Size of octree ="<<seed_octree.getLeafCount ()<<"\n"; 00376 std::vector<PointT, Eigen::aligned_allocator<PointT> > voxel_centers; 00377 int num_seeds = seed_octree.getOccupiedVoxelCenters(voxel_centers); 00378 //std::cout << "Number of seed points before filtering="<<voxel_centers.size ()<<std::endl; 00379 00380 std::vector<int> seed_indices_orig; 00381 seed_indices_orig.resize (num_seeds, 0); 00382 seed_points.clear (); 00383 std::vector<int> closest_index; 00384 std::vector<float> distance; 00385 closest_index.resize(1,0); 00386 distance.resize(1,0); 00387 if (voxel_kdtree_ == 0) 00388 { 00389 voxel_kdtree_ = boost::make_shared< pcl::search::KdTree<PointT> >(); 00390 voxel_kdtree_ ->setInputCloud (voxel_centroid_cloud_); 00391 } 00392 00393 for (int i = 0; i < num_seeds; ++i) 00394 { 00395 voxel_kdtree_->nearestKSearch (voxel_centers[i], 1, closest_index, distance); 00396 seed_indices_orig[i] = closest_index[0]; 00397 } 00398 00399 std::vector<int> neighbors; 00400 std::vector<float> sqr_distances; 00401 seed_points.reserve (seed_indices_orig.size ()); 00402 float search_radius = 0.5f*seed_resolution_; 00403 // This is number of voxels which fit in a planar slice through search volume 00404 // Area of planar slice / area of voxel side 00405 float min_points = 0.05f * (search_radius)*(search_radius) * 3.1415926536f / (resolution_*resolution_); 00406 for (int i = 0; i < seed_indices_orig.size (); ++i) 00407 { 00408 int num = voxel_kdtree_->radiusSearch (seed_indices_orig[i], search_radius , neighbors, sqr_distances); 00409 int min_index = seed_indices_orig[i]; 00410 if ( num > min_points) 00411 { 00412 seed_points.push_back (voxel_centroid_cloud_->points[min_index]); 00413 } 00414 00415 } 00416 // std::cout << "Number of seed points after filtering="<<seed_points.size ()<<std::endl; 00417 00418 } 00419 00420 00421 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00422 template <typename PointT> void 00423 pcl::SupervoxelClustering<PointT>::reseedSupervoxels () 00424 { 00425 //Go through each supervoxel and remove all it's leaves 00426 for (typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr) 00427 { 00428 sv_itr->removeAllLeaves (); 00429 } 00430 00431 std::vector<int> closest_index; 00432 std::vector<float> distance; 00433 //Now go through each supervoxel, find voxel closest to its center, add it in 00434 for (typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr) 00435 { 00436 PointT point; 00437 sv_itr->getXYZ (point.x, point.y, point.z); 00438 voxel_kdtree_->nearestKSearch (point, 1, closest_index, distance); 00439 00440 LeafContainerT* seed_leaf = adjacency_octree_->getLeafContainerAtPoint (voxel_centroid_cloud_->points[closest_index[0]]); 00441 if (seed_leaf) 00442 { 00443 sv_itr->addLeaf (seed_leaf); 00444 } 00445 } 00446 00447 } 00448 00449 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00450 template <typename PointT> void 00451 pcl::SupervoxelClustering<PointT>::transformFunction (PointT &p) 00452 { 00453 p.x /= p.z; 00454 p.y /= p.z; 00455 p.z = std::log (p.z); 00456 } 00457 00458 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00459 template <typename PointT> float 00460 pcl::SupervoxelClustering<PointT>::voxelDataDistance (const VoxelData &v1, const VoxelData &v2) const 00461 { 00462 00463 float spatial_dist = (v1.xyz_ - v2.xyz_).norm () / seed_resolution_; 00464 float color_dist = (v1.rgb_ - v2.rgb_).norm () / 255.0f; 00465 float cos_angle_normal = 1.0f - std::abs (v1.normal_.dot (v2.normal_)); 00466 // std::cout << "s="<<spatial_dist<<" c="<<color_dist<<" an="<<cos_angle_normal<<"\n"; 00467 return cos_angle_normal * normal_importance_ + color_dist * color_importance_+ spatial_dist * spatial_importance_; 00468 00469 } 00470 00471 00472 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00473 ///////// GETTER FUNCTIONS 00474 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00475 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00476 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00477 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00478 template <typename PointT> void 00479 pcl::SupervoxelClustering<PointT>::getSupervoxelAdjacencyList (VoxelAdjacencyList &adjacency_list_arg) const 00480 { 00481 adjacency_list_arg.clear (); 00482 //Add a vertex for each label, store ids in map 00483 std::map <uint32_t, VoxelID> label_ID_map; 00484 for (typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr) 00485 { 00486 VoxelID node_id = add_vertex (adjacency_list_arg); 00487 adjacency_list_arg[node_id] = (sv_itr->getLabel ()); 00488 label_ID_map.insert (std::make_pair (sv_itr->getLabel (), node_id)); 00489 } 00490 00491 for (typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr) 00492 { 00493 uint32_t label = sv_itr->getLabel (); 00494 std::set<uint32_t> neighbor_labels; 00495 sv_itr->getNeighborLabels (neighbor_labels); 00496 for (std::set<uint32_t>::iterator label_itr = neighbor_labels.begin (); label_itr != neighbor_labels.end (); ++label_itr) 00497 { 00498 bool edge_added; 00499 EdgeID edge; 00500 VoxelID u = (label_ID_map.find (label))->second; 00501 VoxelID v = (label_ID_map.find (*label_itr))->second; 00502 boost::tie (edge, edge_added) = add_edge (u,v,adjacency_list_arg); 00503 //Calc distance between centers, set as edge weight 00504 if (edge_added) 00505 { 00506 VoxelData centroid_data = (sv_itr)->getCentroid (); 00507 //Find the neighbhor with this label 00508 VoxelData neighb_centroid_data; 00509 00510 for (typename HelperListT::const_iterator neighb_itr = supervoxel_helpers_.cbegin (); neighb_itr != supervoxel_helpers_.cend (); ++neighb_itr) 00511 { 00512 if (neighb_itr->getLabel () == (*label_itr)) 00513 { 00514 neighb_centroid_data = neighb_itr->getCentroid (); 00515 break; 00516 } 00517 } 00518 00519 float length = voxelDataDistance (centroid_data, neighb_centroid_data); 00520 adjacency_list_arg[edge] = length; 00521 } 00522 } 00523 00524 } 00525 00526 } 00527 00528 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00529 template <typename PointT> void 00530 pcl::SupervoxelClustering<PointT>::getSupervoxelAdjacency (std::multimap<uint32_t, uint32_t> &label_adjacency) const 00531 { 00532 label_adjacency.clear (); 00533 for (typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr) 00534 { 00535 uint32_t label = sv_itr->getLabel (); 00536 std::set<uint32_t> neighbor_labels; 00537 sv_itr->getNeighborLabels (neighbor_labels); 00538 for (std::set<uint32_t>::iterator label_itr = neighbor_labels.begin (); label_itr != neighbor_labels.end (); ++label_itr) 00539 label_adjacency.insert (std::pair<uint32_t,uint32_t> (label, *label_itr) ); 00540 //if (neighbor_labels.size () == 0) 00541 // std::cout << label<<"(size="<<sv_itr->size () << ") has "<<neighbor_labels.size () << "\n"; 00542 } 00543 00544 } 00545 00546 00547 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00548 template <typename PointT> pcl::PointCloud<pcl::PointXYZRGBA>::Ptr 00549 pcl::SupervoxelClustering<PointT>::getColoredCloud () const 00550 { 00551 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr colored_cloud = boost::make_shared <pcl::PointCloud<pcl::PointXYZRGBA> >(); 00552 pcl::copyPointCloud (*input_,*colored_cloud); 00553 00554 pcl::PointCloud <pcl::PointXYZRGBA>::iterator i_colored; 00555 typename pcl::PointCloud <PointT>::const_iterator i_input = input_->begin (); 00556 std::vector <int> indices; 00557 std::vector <float> sqr_distances; 00558 for (i_colored = colored_cloud->begin (); i_colored != colored_cloud->end (); ++i_colored,++i_input) 00559 { 00560 if ( !pcl::isFinite<PointT> (*i_input)) 00561 i_colored->rgb = 0; 00562 else 00563 { 00564 i_colored->rgb = 0; 00565 LeafContainerT *leaf = adjacency_octree_->getLeafContainerAtPoint (*i_input); 00566 VoxelData& voxel_data = leaf->getData (); 00567 if (voxel_data.owner_) 00568 i_colored->rgba = label_colors_[voxel_data.owner_->getLabel ()]; 00569 00570 } 00571 00572 } 00573 00574 return (colored_cloud); 00575 } 00576 00577 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00578 template <typename PointT> pcl::PointCloud<pcl::PointXYZRGBA>::Ptr 00579 pcl::SupervoxelClustering<PointT>::getColoredVoxelCloud () const 00580 { 00581 pcl::PointCloud<pcl::PointXYZRGBA>::Ptr colored_cloud = boost::make_shared< pcl::PointCloud<pcl::PointXYZRGBA> > (); 00582 for (typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr) 00583 { 00584 typename PointCloudT::Ptr voxels; 00585 sv_itr->getVoxels (voxels); 00586 pcl::PointCloud<pcl::PointXYZRGBA> rgb_copy; 00587 copyPointCloud (*voxels, rgb_copy); 00588 00589 pcl::PointCloud<pcl::PointXYZRGBA>::iterator rgb_copy_itr = rgb_copy.begin (); 00590 for ( ; rgb_copy_itr != rgb_copy.end (); ++rgb_copy_itr) 00591 rgb_copy_itr->rgba = label_colors_ [sv_itr->getLabel ()]; 00592 00593 *colored_cloud += rgb_copy; 00594 } 00595 00596 return colored_cloud; 00597 } 00598 00599 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00600 template <typename PointT> typename pcl::PointCloud<PointT>::Ptr 00601 pcl::SupervoxelClustering<PointT>::getVoxelCentroidCloud () const 00602 { 00603 typename PointCloudT::Ptr centroid_copy = boost::make_shared<PointCloudT> (); 00604 copyPointCloud (*voxel_centroid_cloud_, *centroid_copy); 00605 return centroid_copy; 00606 } 00607 00608 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00609 template <typename PointT> pcl::PointCloud<pcl::PointXYZL>::Ptr 00610 pcl::SupervoxelClustering<PointT>::getLabeledVoxelCloud () const 00611 { 00612 pcl::PointCloud<pcl::PointXYZL>::Ptr labeled_voxel_cloud = boost::make_shared< pcl::PointCloud<pcl::PointXYZL> > (); 00613 for (typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr) 00614 { 00615 typename PointCloudT::Ptr voxels; 00616 sv_itr->getVoxels (voxels); 00617 pcl::PointCloud<pcl::PointXYZL> xyzl_copy; 00618 copyPointCloud (*voxels, xyzl_copy); 00619 00620 pcl::PointCloud<pcl::PointXYZL>::iterator xyzl_copy_itr = xyzl_copy.begin (); 00621 for ( ; xyzl_copy_itr != xyzl_copy.end (); ++xyzl_copy_itr) 00622 xyzl_copy_itr->label = sv_itr->getLabel (); 00623 00624 *labeled_voxel_cloud += xyzl_copy; 00625 } 00626 00627 return labeled_voxel_cloud; 00628 } 00629 00630 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00631 template <typename PointT> pcl::PointCloud<pcl::PointXYZL>::Ptr 00632 pcl::SupervoxelClustering<PointT>::getLabeledCloud () const 00633 { 00634 pcl::PointCloud<pcl::PointXYZL>::Ptr labeled_cloud = boost::make_shared <pcl::PointCloud<pcl::PointXYZL> >(); 00635 pcl::copyPointCloud (*input_,*labeled_cloud); 00636 00637 pcl::PointCloud <pcl::PointXYZL>::iterator i_labeled; 00638 typename pcl::PointCloud <PointT>::const_iterator i_input = input_->begin (); 00639 std::vector <int> indices; 00640 std::vector <float> sqr_distances; 00641 for (i_labeled = labeled_cloud->begin (); i_labeled != labeled_cloud->end (); ++i_labeled,++i_input) 00642 { 00643 if ( !pcl::isFinite<PointT> (*i_input)) 00644 i_labeled->label = 0; 00645 else 00646 { 00647 i_labeled->label = 0; 00648 LeafContainerT *leaf = adjacency_octree_->getLeafContainerAtPoint (*i_input); 00649 VoxelData& voxel_data = leaf->getData (); 00650 if (voxel_data.owner_) 00651 i_labeled->label = voxel_data.owner_->getLabel (); 00652 00653 } 00654 00655 } 00656 00657 return (labeled_cloud); 00658 } 00659 00660 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00661 template <typename PointT> pcl::PointCloud<pcl::PointNormal>::Ptr 00662 pcl::SupervoxelClustering<PointT>::makeSupervoxelNormalCloud (std::map<uint32_t,typename Supervoxel<PointT>::Ptr > &supervoxel_clusters) 00663 { 00664 pcl::PointCloud<pcl::PointNormal>::Ptr normal_cloud = boost::make_shared<pcl::PointCloud<pcl::PointNormal> > (); 00665 normal_cloud->resize (supervoxel_clusters.size ()); 00666 typename std::map <uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator sv_itr,sv_itr_end; 00667 sv_itr = supervoxel_clusters.begin (); 00668 sv_itr_end = supervoxel_clusters.end (); 00669 pcl::PointCloud<pcl::PointNormal>::iterator normal_cloud_itr = normal_cloud->begin (); 00670 for ( ; sv_itr != sv_itr_end; ++sv_itr, ++normal_cloud_itr) 00671 { 00672 (sv_itr->second)->getCentroidPointNormal (*normal_cloud_itr); 00673 } 00674 return normal_cloud; 00675 } 00676 00677 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00678 template <typename PointT> float 00679 pcl::SupervoxelClustering<PointT>::getVoxelResolution () const 00680 { 00681 return (resolution_); 00682 } 00683 00684 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00685 template <typename PointT> void 00686 pcl::SupervoxelClustering<PointT>::setVoxelResolution (float resolution) 00687 { 00688 resolution_ = resolution; 00689 00690 } 00691 00692 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00693 template <typename PointT> float 00694 pcl::SupervoxelClustering<PointT>::getSeedResolution () const 00695 { 00696 return (resolution_); 00697 } 00698 00699 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00700 template <typename PointT> void 00701 pcl::SupervoxelClustering<PointT>::setSeedResolution (float seed_resolution) 00702 { 00703 seed_resolution_ = seed_resolution; 00704 } 00705 00706 00707 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00708 template <typename PointT> void 00709 pcl::SupervoxelClustering<PointT>::setColorImportance (float val) 00710 { 00711 color_importance_ = val; 00712 } 00713 00714 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00715 template <typename PointT> void 00716 pcl::SupervoxelClustering<PointT>::setSpatialImportance (float val) 00717 { 00718 spatial_importance_ = val; 00719 } 00720 00721 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00722 template <typename PointT> void 00723 pcl::SupervoxelClustering<PointT>::setNormalImportance (float val) 00724 { 00725 normal_importance_ = val; 00726 } 00727 00728 00729 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00730 template <typename PointT> void 00731 pcl::SupervoxelClustering<PointT>::initializeLabelColors () 00732 { 00733 int max_label = getMaxLabel (); 00734 //If we already have enough colors, return 00735 if (label_colors_.size () > max_label) 00736 return; 00737 00738 //Otherwise, generate new colors until we have enough 00739 label_colors_.reserve (max_label + 1); 00740 srand (static_cast<unsigned int> (time (0))); 00741 while (label_colors_.size () <= max_label ) 00742 { 00743 uint8_t r = static_cast<uint8_t>( (rand () % 256)); 00744 uint8_t g = static_cast<uint8_t>( (rand () % 256)); 00745 uint8_t b = static_cast<uint8_t>( (rand () % 256)); 00746 label_colors_.push_back (static_cast<uint32_t>(r) << 16 | static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(b)); 00747 } 00748 } 00749 00750 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00751 template <typename PointT> int 00752 pcl::SupervoxelClustering<PointT>::getMaxLabel () const 00753 { 00754 int max_label = 0; 00755 for (typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr) 00756 { 00757 int temp = sv_itr->getLabel (); 00758 if (temp > max_label) 00759 max_label = temp; 00760 } 00761 return max_label; 00762 } 00763 00764 namespace pcl 00765 { 00766 00767 namespace octree 00768 { 00769 //Explicit overloads for RGB types 00770 template<> 00771 void 00772 pcl::octree::OctreePointCloudAdjacencyContainer<pcl::PointXYZRGB,pcl::SupervoxelClustering<pcl::PointXYZRGB>::VoxelData>::addPoint (const pcl::PointXYZRGB &new_point) 00773 { 00774 ++num_points_; 00775 //Same as before here 00776 data_.xyz_[0] += new_point.x; 00777 data_.xyz_[1] += new_point.y; 00778 data_.xyz_[2] += new_point.z; 00779 //Separate sums for r,g,b since we cant sum in uchars 00780 data_.rgb_[0] += static_cast<float> (new_point.r); 00781 data_.rgb_[1] += static_cast<float> (new_point.g); 00782 data_.rgb_[2] += static_cast<float> (new_point.b); 00783 } 00784 00785 template<> 00786 void 00787 pcl::octree::OctreePointCloudAdjacencyContainer<pcl::PointXYZRGBA,pcl::SupervoxelClustering<pcl::PointXYZRGBA>::VoxelData>::addPoint (const pcl::PointXYZRGBA &new_point) 00788 { 00789 ++num_points_; 00790 //Same as before here 00791 data_.xyz_[0] += new_point.x; 00792 data_.xyz_[1] += new_point.y; 00793 data_.xyz_[2] += new_point.z; 00794 //Separate sums for r,g,b since we cant sum in uchars 00795 data_.rgb_[0] += static_cast<float> (new_point.r); 00796 data_.rgb_[1] += static_cast<float> (new_point.g); 00797 data_.rgb_[2] += static_cast<float> (new_point.b); 00798 } 00799 00800 00801 00802 //Explicit overloads for RGB types 00803 template<> void 00804 pcl::octree::OctreePointCloudAdjacencyContainer<pcl::PointXYZRGB,pcl::SupervoxelClustering<pcl::PointXYZRGB>::VoxelData>::computeData () 00805 { 00806 data_.rgb_[0] /= (static_cast<float> (num_points_)); 00807 data_.rgb_[1] /= (static_cast<float> (num_points_)); 00808 data_.rgb_[2] /= (static_cast<float> (num_points_)); 00809 data_.xyz_[0] /= (static_cast<float> (num_points_)); 00810 data_.xyz_[1] /= (static_cast<float> (num_points_)); 00811 data_.xyz_[2] /= (static_cast<float> (num_points_)); 00812 } 00813 00814 template<> void 00815 pcl::octree::OctreePointCloudAdjacencyContainer<pcl::PointXYZRGBA,pcl::SupervoxelClustering<pcl::PointXYZRGBA>::VoxelData>::computeData () 00816 { 00817 data_.rgb_[0] /= (static_cast<float> (num_points_)); 00818 data_.rgb_[1] /= (static_cast<float> (num_points_)); 00819 data_.rgb_[2] /= (static_cast<float> (num_points_)); 00820 data_.xyz_[0] /= (static_cast<float> (num_points_)); 00821 data_.xyz_[1] /= (static_cast<float> (num_points_)); 00822 data_.xyz_[2] /= (static_cast<float> (num_points_)); 00823 } 00824 00825 } 00826 } 00827 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00828 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00829 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00830 namespace pcl 00831 { 00832 00833 template<> void 00834 pcl::SupervoxelClustering<pcl::PointXYZRGB>::VoxelData::getPoint (pcl::PointXYZRGB &point_arg) const 00835 { 00836 point_arg.rgba = static_cast<uint32_t>(rgb_[0]) << 16 | 00837 static_cast<uint32_t>(rgb_[1]) << 8 | 00838 static_cast<uint32_t>(rgb_[2]); 00839 point_arg.x = xyz_[0]; 00840 point_arg.y = xyz_[1]; 00841 point_arg.z = xyz_[2]; 00842 } 00843 00844 template<> void 00845 pcl::SupervoxelClustering<pcl::PointXYZRGBA>::VoxelData::getPoint (pcl::PointXYZRGBA &point_arg ) const 00846 { 00847 point_arg.rgba = static_cast<uint32_t>(rgb_[0]) << 16 | 00848 static_cast<uint32_t>(rgb_[1]) << 8 | 00849 static_cast<uint32_t>(rgb_[2]); 00850 point_arg.x = xyz_[0]; 00851 point_arg.y = xyz_[1]; 00852 point_arg.z = xyz_[2]; 00853 } 00854 00855 template<typename PointT> void 00856 pcl::SupervoxelClustering<PointT>::VoxelData::getPoint (PointT &point_arg ) const 00857 { 00858 //XYZ is required or this doesn't make much sense... 00859 point_arg.x = xyz_[0]; 00860 point_arg.y = xyz_[1]; 00861 point_arg.z = xyz_[2]; 00862 } 00863 00864 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00865 template <typename PointT> void 00866 pcl::SupervoxelClustering<PointT>::VoxelData::getNormal (Normal &normal_arg) const 00867 { 00868 normal_arg.normal_x = normal_[0]; 00869 normal_arg.normal_y = normal_[1]; 00870 normal_arg.normal_z = normal_[2]; 00871 normal_arg.curvature = curvature_; 00872 } 00873 } 00874 00875 00876 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00877 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00878 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00879 template <typename PointT> void 00880 pcl::SupervoxelClustering<PointT>::SupervoxelHelper::addLeaf (LeafContainerT* leaf_arg) 00881 { 00882 leaves_.insert (leaf_arg); 00883 VoxelData& voxel_data = leaf_arg->getData (); 00884 voxel_data.owner_ = this; 00885 } 00886 00887 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00888 template <typename PointT> void 00889 pcl::SupervoxelClustering<PointT>::SupervoxelHelper::removeLeaf (LeafContainerT* leaf_arg) 00890 { 00891 leaves_.erase (leaf_arg); 00892 } 00893 00894 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00895 template <typename PointT> void 00896 pcl::SupervoxelClustering<PointT>::SupervoxelHelper::removeAllLeaves () 00897 { 00898 typename std::set<LeafContainerT*>::iterator leaf_itr; 00899 for (leaf_itr = leaves_.begin (); leaf_itr != leaves_.end (); ++leaf_itr) 00900 { 00901 VoxelData& voxel = ((*leaf_itr)->getData ()); 00902 voxel.owner_ = 0; 00903 voxel.distance_ = std::numeric_limits<float>::max (); 00904 } 00905 leaves_.clear (); 00906 } 00907 00908 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00909 template <typename PointT> void 00910 pcl::SupervoxelClustering<PointT>::SupervoxelHelper::expand () 00911 { 00912 //std::cout << "Expanding sv "<<label_<<", owns "<<leaves_.size ()<<" voxels\n"; 00913 //Buffer of new neighbors - initial size is just a guess of most possible 00914 std::vector<LeafContainerT*> new_owned; 00915 new_owned.reserve (leaves_.size () * 9); 00916 //For each leaf belonging to this supervoxel 00917 typename std::set<LeafContainerT*>::iterator leaf_itr; 00918 for (leaf_itr = leaves_.begin (); leaf_itr != leaves_.end (); ++leaf_itr) 00919 { 00920 //for each neighbor of the leaf 00921 for (typename LeafContainerT::iterator neighb_itr=(*leaf_itr)->begin (); neighb_itr!=(*leaf_itr)->end (); ++neighb_itr) 00922 { 00923 //Get a reference to the data contained in the leaf 00924 VoxelData& neighbor_voxel = ((*neighb_itr)->getData ()); 00925 //TODO this is a shortcut, really we should always recompute distance 00926 if(neighbor_voxel.owner_ == this) 00927 continue; 00928 //Compute distance to the neighbor 00929 float dist = parent_->voxelDataDistance (centroid_, neighbor_voxel); 00930 //If distance is less than previous, we remove it from its owner's list 00931 //and change the owner to this and distance (we *steal* it!) 00932 if (dist < neighbor_voxel.distance_) 00933 { 00934 neighbor_voxel.distance_ = dist; 00935 if (neighbor_voxel.owner_ != this) 00936 { 00937 if (neighbor_voxel.owner_) 00938 (neighbor_voxel.owner_)->removeLeaf(*neighb_itr); 00939 neighbor_voxel.owner_ = this; 00940 new_owned.push_back (*neighb_itr); 00941 } 00942 } 00943 } 00944 } 00945 //Push all new owned onto the owned leaf set 00946 typename std::vector<LeafContainerT*>::iterator new_owned_itr; 00947 for (new_owned_itr=new_owned.begin (); new_owned_itr!=new_owned.end (); ++new_owned_itr) 00948 { 00949 leaves_.insert (*new_owned_itr); 00950 } 00951 00952 } 00953 00954 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00955 template <typename PointT> void 00956 pcl::SupervoxelClustering<PointT>::SupervoxelHelper::refineNormals () 00957 { 00958 typename std::set<LeafContainerT*>::iterator leaf_itr; 00959 //For each leaf belonging to this supervoxel, get its neighbors, build an index vector, compute normal 00960 for (leaf_itr = leaves_.begin (); leaf_itr != leaves_.end (); ++leaf_itr) 00961 { 00962 VoxelData& voxel_data = (*leaf_itr)->getData (); 00963 std::vector<int> indices; 00964 indices.reserve (81); 00965 //Push this point 00966 indices.push_back (voxel_data.idx_); 00967 for (typename LeafContainerT::iterator neighb_itr=(*leaf_itr)->begin (); neighb_itr!=(*leaf_itr)->end (); ++neighb_itr) 00968 { 00969 //Get a reference to the data contained in the leaf 00970 VoxelData& neighbor_voxel_data = ((*neighb_itr)->getData ()); 00971 //If the neighbor is in this supervoxel, use it 00972 if (neighbor_voxel_data.owner_ == this) 00973 { 00974 indices.push_back (neighbor_voxel_data.idx_); 00975 //Also check its neighbors 00976 for (typename LeafContainerT::iterator neighb_neighb_itr=(*neighb_itr)->begin (); neighb_neighb_itr!=(*neighb_itr)->end (); ++neighb_neighb_itr) 00977 { 00978 VoxelData& neighb_neighb_voxel_data = (*neighb_neighb_itr)->getData (); 00979 if (neighb_neighb_voxel_data.owner_ == this) 00980 indices.push_back (neighb_neighb_voxel_data.idx_); 00981 } 00982 00983 00984 } 00985 } 00986 //Compute normal 00987 pcl::computePointNormal (*parent_->voxel_centroid_cloud_, indices, voxel_data.normal_, voxel_data.curvature_); 00988 pcl::flipNormalTowardsViewpoint (parent_->voxel_centroid_cloud_->points[voxel_data.idx_], 0.0f,0.0f,0.0f, voxel_data.normal_); 00989 voxel_data.normal_[3] = 0.0f; 00990 voxel_data.normal_.normalize (); 00991 } 00992 } 00993 00994 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00995 template <typename PointT> void 00996 pcl::SupervoxelClustering<PointT>::SupervoxelHelper::updateCentroid () 00997 { 00998 centroid_.normal_ = Eigen::Vector4f::Zero (); 00999 centroid_.xyz_ = Eigen::Vector3f::Zero (); 01000 centroid_.rgb_ = Eigen::Vector3f::Zero (); 01001 typename std::set<LeafContainerT*>::iterator leaf_itr = leaves_.begin (); 01002 for ( ; leaf_itr!= leaves_.end (); ++leaf_itr) 01003 { 01004 const VoxelData& leaf_data = (*leaf_itr)->getData (); 01005 centroid_.normal_ += leaf_data.normal_; 01006 centroid_.xyz_ += leaf_data.xyz_; 01007 centroid_.rgb_ += leaf_data.rgb_; 01008 } 01009 centroid_.normal_.normalize (); 01010 centroid_.xyz_ /= static_cast<float> (leaves_.size ()); 01011 centroid_.rgb_ /= static_cast<float> (leaves_.size ()); 01012 01013 } 01014 01015 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 01016 template <typename PointT> void 01017 pcl::SupervoxelClustering<PointT>::SupervoxelHelper::getVoxels (typename pcl::PointCloud<PointT>::Ptr &voxels) const 01018 { 01019 voxels = boost::make_shared<pcl::PointCloud<PointT> > (); 01020 voxels->clear (); 01021 voxels->resize (leaves_.size ()); 01022 typename pcl::PointCloud<PointT>::iterator voxel_itr = voxels->begin (); 01023 typename std::set<LeafContainerT*>::iterator leaf_itr; 01024 for (leaf_itr = leaves_.begin (); leaf_itr != leaves_.end (); ++leaf_itr, ++voxel_itr) 01025 { 01026 const VoxelData& leaf_data = (*leaf_itr)->getData (); 01027 leaf_data.getPoint (*voxel_itr); 01028 } 01029 } 01030 01031 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 01032 template <typename PointT> void 01033 pcl::SupervoxelClustering<PointT>::SupervoxelHelper::getNormals (typename pcl::PointCloud<Normal>::Ptr &normals) const 01034 { 01035 normals = boost::make_shared<pcl::PointCloud<Normal> > (); 01036 normals->clear (); 01037 normals->resize (leaves_.size ()); 01038 typename std::set<LeafContainerT*>::iterator leaf_itr; 01039 typename pcl::PointCloud<Normal>::iterator normal_itr = normals->begin (); 01040 for (leaf_itr = leaves_.begin (); leaf_itr != leaves_.end (); ++leaf_itr, ++normal_itr) 01041 { 01042 const VoxelData& leaf_data = (*leaf_itr)->getData (); 01043 leaf_data.getNormal (*normal_itr); 01044 } 01045 } 01046 01047 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 01048 template <typename PointT> void 01049 pcl::SupervoxelClustering<PointT>::SupervoxelHelper::getNeighborLabels (std::set<uint32_t> &neighbor_labels) const 01050 { 01051 neighbor_labels.clear (); 01052 //For each leaf belonging to this supervoxel 01053 typename std::set<LeafContainerT*>::iterator leaf_itr; 01054 for (leaf_itr = leaves_.begin (); leaf_itr != leaves_.end (); ++leaf_itr) 01055 { 01056 //for each neighbor of the leaf 01057 for (typename LeafContainerT::iterator neighb_itr=(*leaf_itr)->begin (); neighb_itr!=(*leaf_itr)->end (); ++neighb_itr) 01058 { 01059 //Get a reference to the data contained in the leaf 01060 VoxelData& neighbor_voxel = ((*neighb_itr)->getData ()); 01061 //If it has an owner, and it's not us - get it's owner's label insert into set 01062 if (neighbor_voxel.owner_ != this && neighbor_voxel.owner_) 01063 { 01064 neighbor_labels.insert (neighbor_voxel.owner_->getLabel ()); 01065 } 01066 } 01067 } 01068 } 01069 01070 01071 #endif // PCL_SUPERVOXEL_CLUSTERING_HPP_ 01072
Except where otherwise noted, the PointClouds.org web pages are licensed under Creative Commons Attribution 3.0.
Pages generated on Wed Mar 25 00:25:43 2015