PCL中分割方法的介紹(3)


(3)上兩篇介紹了關於歐幾里德分割,條件分割,最小分割法等等還有之前就有用RANSAC法的分割方法,這一篇是關於區域生成的分割法,

區 域生長的基本 思想是: 將具有相似性的像素集合起來構成區域。首先對每個需要分割的區域找出一個種子像素作為生長的起點,然后將種子像素周圍鄰域中與種子有相同或相似性質的像素 (根據事先確定的生長或相似准則來確定)合並到種子像素所在的區域中。而新的像素繼續作為種子向四周生長,直到再沒有滿足條件的像素可以包括進來,一個區 域就生長而成了。

區域生長算法直觀感覺上和歐幾里德算法相差不大,都是從一個點出發,最終占領整個被分割區域,歐幾里德算法是通過距離遠近,對於普通點雲的區域生長,其可由法線、曲率估計算法獲得其法線和曲率值。通過法線和曲率來判斷某點是否屬於該類。

算法的主要思想是:首先依據點的曲率值對點進行排序,之所以排序是因為,區域生長算法是從曲率最小的點開始生長的,這個點就是初始種子點,初始種子點所在的區域即為最平滑的區域,從最平滑的區域開始生長可減少分割片段的總數,提高效率,設置一空的種子點序列和空的聚類區域,選好初始種子后,將其加入到種子點序列中,並搜索鄰域點,對每一個鄰域點,比較鄰域點的法線與當前種子點的法線之間的夾角,小於平滑閥值的將當前點加入到當前區域,然后檢測每一個鄰域點的曲率值,小於曲率閥值的加入到種子點序列中,刪除當前的種子點,循環執行以上步驟,直到種子序列為空,

其算法可以總結為:

  1. 種子周圍的臨近點和種子點雲相比較
  2. 法線的方向是否足夠相近
  3. 曲率是否足夠小
  4. 如果滿足1,2則該點可用做種子點
  5. 如果只滿足1,則歸類而不做種
  6. 從某個種子出發,其“子種子”不再出現則一類聚集完成
  7. 類的規模既不能太大也不能太小

 

  顯然,上述算法是針對小曲率變化面設計的。尤其適合對連續階梯平面進行分割:比如SLAM算法所獲得的建築走廊

那么就看一下代碼的效果

#include <iostream>
#include <vector>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/search/search.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/region_growing.h>

int
main (int argc, char** argv)
{ 
  //點雲的類型
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  //打開點雲
  if ( pcl::io::loadPCDFile <pcl::PointXYZ> ("region_growing_tutorial.pcd", *cloud) == -1)
  {
    std::cout << "Cloud reading failed." << std::endl;
    return (-1);
  }
 //設置搜索的方式或者說是結構
  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 (cloud);
  normal_estimator.setKSearch (50);
  normal_estimator.compute (*normals);
   //直通濾波在Z軸的0到1米之間
  pcl::IndicesPtr indices (new std::vector <int>);
  pcl::PassThrough<pcl::PointXYZ> pass;
  pass.setInputCloud (cloud);
  pass.setFilterFieldName ("z");
  pass.setFilterLimits (0.0, 1.0);
  pass.filter (*indices);
  //聚類對象<點,法線>
  pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
  reg.setMinClusterSize (50);  //最小的聚類的點數
  reg.setMaxClusterSize (1000000);  //最大的
  reg.setSearchMethod (tree);    //搜索方式
  reg.setNumberOfNeighbours (30);    //設置搜索的鄰域點的個數
  reg.setInputCloud (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);

  std::cout << "Number of clusters is equal to " << clusters.size () << std::endl;
  std::cout << "First cluster has " << clusters[0].indices.size () << " points." << endl;
  std::cout << "These are the indices of the points of the initial" <<
    std::endl << "cloud that belong to the first cluster:" << std::endl;
 
 int counter = 0;
  while (counter < clusters[0].indices.size ())
  {
    std::cout << clusters[0].indices[counter] << ", ";
    counter++;
    if (counter % 10 == 0)
      std::cout << std::endl;
  }
  std::cout << std::endl;
  
  //可視化聚類的結果
  pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();
  pcl::visualization::CloudViewer viewer ("Cluster viewer");
  viewer.showCloud(colored_cloud);
  while (!viewer.wasStopped ())
  {
  }

  return (0);
}

看一下結果

                                                     原始點雲

                                                            區域生成后的點雲

(4)基於顏色的區域生長分割法

除了普通點雲之外,還有一種特殊的點雲,成為RGB點雲。顯而易見,這種點雲除了結構信息之外,還存在顏色信息。將物體通過顏色分類,是人類在辨認果實的 過程中進化出的能力,顏色信息可以很好的將復雜場景中的特殊物體分割出來。比如Xbox Kinect就可以輕松的捕捉顏色點雲。基於顏色的區域生長分割原理上和基於曲率,法線的分割方法是一致的。只不過比較目標換成了顏色,去掉了點雲規模上 限的限制。可以認為,同一個顏色且挨得近,是一類的可能性很大,不需要上限來限制。所以這種方式比較適合用於室內場景分割。尤其是復雜室內場景,顏色分割 可以輕松的將連續的場景點雲變成不同的物體。哪怕是高低不平的地面,沒法用采樣一致分割器抽掉,顏色分割算法同樣能完成分割任務。

算法分為兩步:

(1)分割,當前種子點和領域點之間色差小於色差閥值的視為一個聚類

 (2)合並,聚類之間的色差小於色差閥值和並為一個聚類,且當前聚類中點的數量小於聚類點數量的與最近的聚類合並在一起

查看代碼

#include <iostream>
#include <vector>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/search/search.h>
#include <pcl/search/kdtree.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/region_growing_rgb.h>

int
main (int argc, char** argv)
{
  pcl::search::Search <pcl::PointXYZRGB>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZRGB> > (new pcl::search::KdTree<pcl::PointXYZRGB>);

  pcl::PointCloud <pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud <pcl::PointXYZRGB>);
  if ( pcl::io::loadPCDFile <pcl::PointXYZRGB> ("region_growing_rgb_tutorial.pcd", *cloud) == -1 )
  {
    std::cout << "Cloud reading failed." << std::endl;
    return (-1);
  }
  //存儲點雲的容器
  pcl::IndicesPtr indices (new std::vector <int>);
  //濾波
  pcl::PassThrough<pcl::PointXYZRGB> pass;
  pass.setInputCloud (cloud);
  pass.setFilterFieldName ("z");
  pass.setFilterLimits (0.0, 1.0);
  pass.filter (*indices);
  
 //基於顏色的區域生成的對象
  pcl::RegionGrowingRGB<pcl::PointXYZRGB> reg;
  reg.setInputCloud (cloud);
  reg.setIndices (indices);   //點雲的索引
  reg.setSearchMethod (tree);
  reg.setDistanceThreshold (10);  //距離的閥值
  reg.setPointColorThreshold (6);  //點與點之間顏色容差
  reg.setRegionColorThreshold (5);  //區域之間容差
  reg.setMinClusterSize (600);       //設置聚類的大小

  std::vector <pcl::PointIndices> clusters;
  reg.extract (clusters);

  pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();
  pcl::visualization::CloudViewer viewer ("Cluster viewer");
  viewer.showCloud (colored_cloud);
  while (!viewer.wasStopped ())
  {
    boost::this_thread::sleep (boost::posix_time::microseconds (100));
  }

  return (0);
}

恩  就這樣實際應用就是調參數,

 

 

-------------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------------------

版權所有,轉載請注明出處

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM