基于CC写的插件,利用PCL中算法实现:
- void qLxPluginPCL::doRegionGrowing()
- {
- assert(m_app);
- if (!m_app)
- return;
- const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
- size_t selNum = selectedEntities.size();
- )
- {
- m_app->dispToConsole("Please select two cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
- return;
- }
- ccHObject* ent = selectedEntities[];
- assert(ent);
- if (!ent || !ent->isA(CC_TYPES::POINT_CLOUD))
- {
- m_app->dispToConsole("Select a real point cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
- return;
- }
- ccPointCloud* m_cloud = static_cast<ccPointCloud*>(ent);
- pcl::PointCloud<PointXYZ>::Ptr pcl_t_cloud (new pcl::PointCloud<PointXYZ>);
- ConvertccPointcloud_to_pclPointCloud(*m_cloud,*pcl_t_cloud);
- pcl::search::Search<pcl::PointXYZ>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> > (new pcl::search::KdTree<pcl::PointXYZ>);
- pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
- pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
- normal_estimator.setSearchMethod (tree);
- normal_estimator.setInputCloud (pcl_t_cloud);
- normal_estimator.setKSearch ();
- normal_estimator.compute (*normals);
- pcl::IndicesPtr indices (new std::vector <int>);
- pcl::PassThrough<pcl::PointXYZ> pass;
- pass.setInputCloud (pcl_t_cloud);
- pass.setFilterFieldName ("z");
- pass.setFilterLimits (0.0, 1.0);
- pass.filter (*indices);
- pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
- reg.setMinClusterSize ();
- reg.setMaxClusterSize ();
- reg.setSearchMethod (tree);
- reg.setNumberOfNeighbours ();
- reg.setInputCloud (pcl_t_cloud);
- //reg.setIndices (indices);
- reg.setInputNormals (normals);
- reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
- reg.setCurvatureThreshold (1.0);
- std::vector <pcl::PointIndices> clusters;
- reg.extract (clusters);
- pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();
- int pointCount=colored_cloud->size();
- ccPointCloud* ccCloud =new ccPointCloud();
- if (!ccCloud->reserve(static_cast<unsigned>(pointCount)))
- return ;
- ccCloud->enableScalarField();
- ccCloud->setName(QString("RegionGrowing"));
- ccCloud->showColors(true);
- ccCloud->setPointSize();
- ; i < pointCount; ++i)
- {
- CCVector3 P(colored_cloud->at(i).x,colored_cloud->at(i).y,colored_cloud->at(i).z);
- ccCloud->addPoint(P);
- }
- std::vector< pcl::PointIndices >::iterator i_segment;
- srand (static_cast<unsigned )));
- std::vector<unsigned char> colors;
- ; i_segment < clusters.size (); i_segment++)
- {
- colors.push_back (static_cast<unsigned ));
- colors.push_back (static_cast<unsigned ));
- colors.push_back (static_cast<unsigned ));
- }
- if (ccCloud->resizeTheRGBTable(true))
- {
- ;
- for (i_segment = clusters.begin (); i_segment != clusters.end (); i_segment++)
- {
- std::vector<int>::iterator i_point;
- for (i_point = i_segment->indices.begin (); i_point != i_segment->indices.end (); i_point++)
- {
- int index;
- index = *i_point;
- ccColor::Rgb rgb=ccColor::Rgb( colors[ * next_color],colors[ * next_color + ],colors[ * next_color + ]);
- ccCloud->setPointColor(index,rgb.rgb);
- }
- next_color++;
- }
- }
- ccHObject* group = ;
- if (!group)
- group = new ccHObject(QString("RegionGrowing(%1)").arg(ent->getName()));
- group->addChild(ccCloud);
- group->setVisible(true);
- m_app->addToDB(group);
- }
具体实现参考RegionGrowing类:
- template <typename PointT, typename NormalT> void
- pcl::RegionGrowing<PointT, NormalT>::extract (std::vector <pcl::PointIndices>& clusters)
- {
- clusters_.clear ();
- clusters.clear ();
- point_neighbours_.clear ();
- point_labels_.clear ();
- num_pts_in_segment_.clear ();
- number_of_segments_ = ;
- bool segmentation_is_possible = initCompute ();
- if ( !segmentation_is_possible )
- {
- deinitCompute ();
- return;
- }
- segmentation_is_possible = prepareForSegmentation ();
- if ( !segmentation_is_possible )
- {
- deinitCompute ();
- return;
- }
- findPointNeighbours ();
- applySmoothRegionGrowingAlgorithm ();
- assembleRegions ();
- clusters.resize (clusters_.size ());
- std::vector<pcl::PointIndices>::iterator cluster_iter_input = clusters.begin ();
- for (std::vector<pcl::PointIndices>::const_iterator cluster_iter = clusters_.begin (); cluster_iter != clusters_.end (); cluster_iter++)
- {
- if ((static_cast<int> (cluster_iter->indices.size ()) >= min_pts_per_cluster_) &&
- (static_cast<int> (cluster_iter->indices.size ()) <= max_pts_per_cluster_))
- {
- *cluster_iter_input = *cluster_iter;
- cluster_iter_input++;
- }
- }
- clusters_ = std::vector<pcl::PointIndices> (clusters.begin (), cluster_iter_input);
- clusters.resize(clusters_.size());
- deinitCompute ();
- }
算法实现的关键多了一步种子点选取的过程,需要根据某一种属性排序。
- template <typename PointT, typename NormalT> void
- pcl::RegionGrowing<PointT, NormalT>::applySmoothRegionGrowingAlgorithm ()
- {
- int num_of_pts = static_cast<int> (indices_->size ());
- point_labels_.resize (input_->points.size (), -);
- std::vector< std::pair<float, int> > point_residual;
- std::pair<float, int> pair;
- point_residual.resize (num_of_pts, pair);
- if (normal_flag_ == true)
- {
- ; i_point < num_of_pts; i_point++)
- {
- int point_index = (*indices_)[i_point];
- point_residual[i_point].first = normals_->points[point_index].curvature;
- point_residual[i_point].second = point_index;
- }
- std::sort (point_residual.begin (), point_residual.end (), comparePair);
- }
- else
- {
- ; i_point < num_of_pts; i_point++)
- {
- int point_index = (*indices_)[i_point];
- point_residual[i_point].first = ;
- point_residual[i_point].second = point_index;
- }
- }
- ;
- int seed = point_residual[seed_counter].second;
- ;
- ;
- while (segmented_pts_num < num_of_pts)
- {
- int pts_in_segment;
- pts_in_segment = growRegion (seed, number_of_segments);
- segmented_pts_num += pts_in_segment;
- num_pts_in_segment_.push_back (pts_in_segment);
- number_of_segments++;
- //find next point that is not segmented yet
- ; i_seed < num_of_pts; i_seed++)
- {
- int index = point_residual[i_seed].second;
- )
- {
- seed = index;
- break;
- }
- }
- }
- }
区域生长的主要流程:
- template <typename PointT, typename NormalT> int
- pcl::RegionGrowing<PointT, NormalT>::growRegion (int initial_seed, int segment_number)
- {
- std::queue<int> seeds;
- seeds.push (initial_seed);
- point_labels_[initial_seed] = segment_number;//第几个生长的区域
- ;
- while (!seeds.empty ())
- {
- int curr_seed;
- curr_seed = seeds.front ();
- seeds.pop ();
- size_t i_nghbr = ;
- while ( i_nghbr < neighbour_number_ && i_nghbr < point_neighbours_[curr_seed].size () )
- {
- int index = point_neighbours_[curr_seed][i_nghbr];
- )//未标记
- {
- i_nghbr++;
- continue;
- }
- bool is_a_seed = false;
- //判断近邻是否属于当前的标记类,是否可以作为新的种子点
- bool belongs_to_segment = validatePoint (initial_seed, curr_seed, index, is_a_seed);
- if (belongs_to_segment == false)
- {
- i_nghbr++;
- continue;
- }
- point_labels_[index] = segment_number;//当前近邻属于标记类
- num_pts_in_segment++;
- if (is_a_seed)
- {
- seeds.push (index);//加入新的种子点
- }
- i_nghbr++;
- }// next neighbour
- }// next seed
- return (num_pts_in_segment);
- }