[CC]区域生长算法——点云分割

时间:2023-03-09 14:39:35
[CC]区域生长算法——点云分割

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

 void qLxPluginPCL::doRegionGrowing()
{
assert(m_app);
if (!m_app)
return; const ccHObject::Container& selectedEntities = m_app->getSelectedEntities();
size_t selNum = selectedEntities.size();
if (selNum!=)
{
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();
for (size_t i = ; 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 int> (time ()));
std::vector<unsigned char> colors;
for (size_t i_segment = ; i_segment < clusters.size (); i_segment++)
{
colors.push_back (static_cast<unsigned char> (rand () % ));
colors.push_back (static_cast<unsigned char> (rand () % ));
colors.push_back (static_cast<unsigned char> (rand () % ));
} if (ccCloud->resizeTheRGBTable(true))
{
int next_color = ;
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)
{
for (int i_point = ; 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
{
for (int i_point = ; 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_counter = ;
int seed = point_residual[seed_counter].second; int segmented_pts_num = ;
int number_of_segments = ;
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
for (int i_seed = seed_counter + ; i_seed < num_of_pts; i_seed++)
{
int index = point_residual[i_seed].second;
if (point_labels_[index] == -)
{
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;//第几个生长的区域 int num_pts_in_segment = ; 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];
if (point_labels_[index] != -)//未标记
{
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);
}

[CC]区域生长算法——点云分割

[CC]区域生长算法——点云分割