• [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     if (selNum!=1)
     10     {
     11         m_app->dispToConsole("Please select two cloud!",ccMainAppInterface::ERR_CONSOLE_MESSAGE);
     12         return;
     13     }
     14 
     15     ccHObject* ent = selectedEntities[0];
     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 (50);
     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 (50);
     43     reg.setMaxClusterSize (1000000);
     44     reg.setSearchMethod (tree);
     45     reg.setNumberOfNeighbours (30);
     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(1);
     65     for (size_t i = 0; 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 int> (time (0)));
     74     std::vector<unsigned char> colors;
     75     for (size_t i_segment = 0; i_segment < clusters.size (); i_segment++)
     76     {
     77         colors.push_back (static_cast<unsigned char> (rand () % 256));
     78         colors.push_back (static_cast<unsigned char> (rand () % 256));
     79         colors.push_back (static_cast<unsigned char> (rand () % 256));
     80     }
     81 
     82     if (ccCloud->resizeTheRGBTable(true))
     83     {
     84         int next_color = 0;
     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[3 * next_color],colors[3 * next_color + 1],colors[3 * next_color + 2]);
     93                 ccCloud->setPointColor(index,rgb.rgb);
     94             }
     95             next_color++;
     96         }
     97     }
     98     ccHObject* group = 0;
     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_ = 0;
    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 (), -1);
     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     for (int i_point = 0; 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     for (int i_point = 0; i_point < num_of_pts; i_point++)
    24     {
    25       int point_index = (*indices_)[i_point];
    26       point_residual[i_point].first = 0;
    27       point_residual[i_point].second = point_index;
    28     }
    29   }
    30   int seed_counter = 0;
    31   int seed = point_residual[seed_counter].second;
    32 
    33   int segmented_pts_num = 0;
    34   int number_of_segments = 0;
    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     for (int i_seed = seed_counter + 1; i_seed < num_of_pts; i_seed++)
    45     {
    46       int index = point_residual[i_seed].second;
    47       if (point_labels_[index] == -1)
    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   int num_pts_in_segment = 1;
     9 
    10   while (!seeds.empty ())
    11   {
    12     int curr_seed;
    13     curr_seed = seeds.front ();
    14     seeds.pop ();
    15 
    16     size_t i_nghbr = 0;
    17     while ( i_nghbr < neighbour_number_ && i_nghbr < point_neighbours_[curr_seed].size () )
    18     {
    19       int index = point_neighbours_[curr_seed][i_nghbr];
    20       if (point_labels_[index] != -1)//未标记
    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 }

  • 相关阅读:
    iOS开发UI篇—在UITableview的应用中使用动态单元格来完成app应用程序管理界面的搭建
    python读文件和写文件
    asp.net中FileUpload得到上传文件的完整路径
    Derek解读Bytom源码-P2P网络 upnp端口映射
    Derek解读Bytom源码-启动与停止
    Derek解读Bytom源码-P2P网络 地址簿
    比原链社区项目一览(持续更新)
    Derek解读Bytom源码-protobuf生成比原核心代码
    Derek解读Bytom源码-Api Server接口服务
    Derek解读Bytom源码-孤块管理
  • 原文地址:https://www.cnblogs.com/yhlx125/p/5919950.html
Copyright © 2020-2023  润新知