PCL写的区域生长点云分割算法——CC插件

基于CC写的插件,利用PCL中算法实现:

  1. void qLxPluginPCL::doRegionGrowing()
  2. {
  3. assert(m_app);
  4. if (!m_app)
  5. return;
  6.  
  7. const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
  8. size_t selNum = selectedEntities.size();
  9. )
  10. {
  11. m_app->dispToConsole("Please select two cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
  12. return;
  13. }
  14.  
  15. ccHObject* ent = selectedEntities[];
  16. assert(ent);
  17. if (!ent || !ent->isA(CC_TYPES::POINT_CLOUD))
  18. {
  19. m_app->dispToConsole("Select a real point cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
  20. return;
  21. }
  22. ccPointCloud* m_cloud = static_cast<ccPointCloud*>(ent);
  23. pcl::PointCloud<PointXYZ>::Ptr pcl_t_cloud (new pcl::PointCloud<PointXYZ>);
  24. ConvertccPointcloud_to_pclPointCloud(*m_cloud,*pcl_t_cloud);
  25.  
  26. pcl::search::Search<pcl::PointXYZ>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> > (new pcl::search::KdTree<pcl::PointXYZ>);
  27. pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
  28. pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
  29. normal_estimator.setSearchMethod (tree);
  30. normal_estimator.setInputCloud (pcl_t_cloud);
  31. normal_estimator.setKSearch ();
  32. normal_estimator.compute (*normals);
  33.  
  34. pcl::IndicesPtr indices (new std::vector <int>);
  35. pcl::PassThrough<pcl::PointXYZ> pass;
  36. pass.setInputCloud (pcl_t_cloud);
  37. pass.setFilterFieldName ("z");
  38. pass.setFilterLimits (0.0, 1.0);
  39. pass.filter (*indices);
  40.  
  41. pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
  42. reg.setMinClusterSize ();
  43. reg.setMaxClusterSize ();
  44. reg.setSearchMethod (tree);
  45. reg.setNumberOfNeighbours ();
  46. reg.setInputCloud (pcl_t_cloud);
  47. //reg.setIndices (indices);
  48. reg.setInputNormals (normals);
  49. reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
  50. reg.setCurvatureThreshold (1.0);
  51.  
  52. std::vector <pcl::PointIndices> clusters;
  53. reg.extract (clusters);
  54.  
  55. pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();
  56. int pointCount=colored_cloud->size();
  57. ccPointCloud* ccCloud =new ccPointCloud();
  58. if (!ccCloud->reserve(static_cast<unsigned>(pointCount)))
  59. return ;
  60. ccCloud->enableScalarField();
  61. ccCloud->setName(QString("RegionGrowing"));
  62. ccCloud->showColors(true);
  63.  
  64. ccCloud->setPointSize();
  65. ; i < pointCount; ++i)
  66. {
  67. CCVector3 P(colored_cloud->at(i).x,colored_cloud->at(i).y,colored_cloud->at(i).z);
  68. ccCloud->addPoint(P);
  69.  
  70. }
  71.  
  72. std::vector< pcl::PointIndices >::iterator i_segment;
  73. srand (static_cast<unsigned )));
  74. std::vector<unsigned char> colors;
  75. ; i_segment < clusters.size (); i_segment++)
  76. {
  77. colors.push_back (static_cast<unsigned ));
  78. colors.push_back (static_cast<unsigned ));
  79. colors.push_back (static_cast<unsigned ));
  80. }
  81.  
  82. if (ccCloud->resizeTheRGBTable(true))
  83. {
  84. ;
  85. for (i_segment = clusters.begin (); i_segment != clusters.end (); i_segment++)
  86. {
  87. std::vector<int>::iterator i_point;
  88. for (i_point = i_segment->indices.begin (); i_point != i_segment->indices.end (); i_point++)
  89. {
  90. int index;
  91. index = *i_point;
  92. ccColor::Rgb rgb=ccColor::Rgb( colors[ * next_color],colors[ * next_color + ],colors[ * next_color + ]);
  93. ccCloud->setPointColor(index,rgb.rgb);
  94. }
  95. next_color++;
  96. }
  97. }
  98. ccHObject* group = ;
  99. if (!group)
  100. group = new ccHObject(QString("RegionGrowing(%1)").arg(ent->getName()));
  101. group->addChild(ccCloud);
  102. group->setVisible(true);
  103. m_app->addToDB(group);
  104. }

具体实现参考RegionGrowing类:

 
  1. template <typename PointT, typename NormalT> void
  2. pcl::RegionGrowing<PointT, NormalT>::extract (std::vector <pcl::PointIndices>& clusters)
  3. {
  4. clusters_.clear ();
  5. clusters.clear ();
  6. point_neighbours_.clear ();
  7. point_labels_.clear ();
  8. num_pts_in_segment_.clear ();
  9. number_of_segments_ = ;
  10.  
  11. bool segmentation_is_possible = initCompute ();
  12. if ( !segmentation_is_possible )
  13. {
  14. deinitCompute ();
  15. return;
  16. }
  17.  
  18. segmentation_is_possible = prepareForSegmentation ();
  19. if ( !segmentation_is_possible )
  20. {
  21. deinitCompute ();
  22. return;
  23. }
  24.  
  25. findPointNeighbours ();
  26. applySmoothRegionGrowingAlgorithm ();
  27. assembleRegions ();
  28.  
  29. clusters.resize (clusters_.size ());
  30. std::vector<pcl::PointIndices>::iterator cluster_iter_input = clusters.begin ();
  31. for (std::vector<pcl::PointIndices>::const_iterator cluster_iter = clusters_.begin (); cluster_iter != clusters_.end (); cluster_iter++)
  32. {
  33. if ((static_cast<int> (cluster_iter->indices.size ()) >= min_pts_per_cluster_) &&
  34. (static_cast<int> (cluster_iter->indices.size ()) <= max_pts_per_cluster_))
  35. {
  36. *cluster_iter_input = *cluster_iter;
  37. cluster_iter_input++;
  38. }
  39. }
  40.  
  41. clusters_ = std::vector<pcl::PointIndices> (clusters.begin (), cluster_iter_input);
  42. clusters.resize(clusters_.size());
  43.  
  44. deinitCompute ();
  45. }

算法实现的关键多了一步种子点选取的过程,需要根据某一种属性排序。

 
  1. template <typename PointT, typename NormalT> void
  2. pcl::RegionGrowing<PointT, NormalT>::applySmoothRegionGrowingAlgorithm ()
  3. {
  4. int num_of_pts = static_cast<int> (indices_->size ());
  5. point_labels_.resize (input_->points.size (), -);
  6.  
  7. std::vector< std::pair<float, int> > point_residual;
  8. std::pair<float, int> pair;
  9. point_residual.resize (num_of_pts, pair);
  10.  
  11. if (normal_flag_ == true)
  12. {
  13. ; i_point < num_of_pts; i_point++)
  14. {
  15. int point_index = (*indices_)[i_point];
  16. point_residual[i_point].first = normals_->points[point_index].curvature;
  17. point_residual[i_point].second = point_index;
  18. }
  19. std::sort (point_residual.begin (), point_residual.end (), comparePair);
  20. }
  21. else
  22. {
  23. ; i_point < num_of_pts; i_point++)
  24. {
  25. int point_index = (*indices_)[i_point];
  26. point_residual[i_point].first = ;
  27. point_residual[i_point].second = point_index;
  28. }
  29. }
  30. ;
  31. int seed = point_residual[seed_counter].second;
  32.  
  33. ;
  34. ;
  35. while (segmented_pts_num < num_of_pts)
  36. {
  37. int pts_in_segment;
  38. pts_in_segment = growRegion (seed, number_of_segments);
  39. segmented_pts_num += pts_in_segment;
  40. num_pts_in_segment_.push_back (pts_in_segment);
  41. number_of_segments++;
  42.  
  43. //find next point that is not segmented yet
  44. ; i_seed < num_of_pts; i_seed++)
  45. {
  46. int index = point_residual[i_seed].second;
  47. )
  48. {
  49. seed = index;
  50. break;
  51. }
  52. }
  53. }
  54. }

区域生长的主要流程:

 
  1. template <typename PointT, typename NormalT> int
  2. pcl::RegionGrowing<PointT, NormalT>::growRegion (int initial_seed, int segment_number)
  3. {
  4. std::queue<int> seeds;
  5. seeds.push (initial_seed);
  6. point_labels_[initial_seed] = segment_number;//第几个生长的区域
  7.  
  8. ;
  9.  
  10. while (!seeds.empty ())
  11. {
  12. int curr_seed;
  13. curr_seed = seeds.front ();
  14. seeds.pop ();
  15.  
  16. size_t i_nghbr = ;
  17. while ( i_nghbr < neighbour_number_ && i_nghbr < point_neighbours_[curr_seed].size () )
  18. {
  19. int index = point_neighbours_[curr_seed][i_nghbr];
  20. )//未标记
  21. {
  22. i_nghbr++;
  23. continue;
  24. }
  25.  
  26. bool is_a_seed = false;
  27. //判断近邻是否属于当前的标记类,是否可以作为新的种子点
  28. bool belongs_to_segment = validatePoint (initial_seed, curr_seed, index, is_a_seed);
  29.  
  30. if (belongs_to_segment == false)
  31. {
  32. i_nghbr++;
  33. continue;
  34. }
  35.  
  36. point_labels_[index] = segment_number;//当前近邻属于标记类
  37. num_pts_in_segment++;
  38.  
  39. if (is_a_seed)
  40. {
  41. seeds.push (index);//加入新的种子点
  42. }
  43.  
  44. i_nghbr++;
  45. }// next neighbour
  46. }// next seed
  47.  
  48. return (num_pts_in_segment);
  49. }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值