1. 程式人生 > >[CC]區域生長演算法——點雲分割

[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 }

相關推薦

[CC]區域生長演算法——分割

 基於CC寫的外掛,利用PCL中演算法實現: 1 void qLxPluginPCL::doRegionGrowing() 2 { 3 assert(m_app); 4 if (!m_app) 5 return; 6 7

區域生長演算法

影象分割是一種重要的影象處理技術,而區域生長是影象分割技術的一種。區域生長的基本思想是將具有相似性的畫素集合起來構成區域。首先對每個需要分割的區域找出一個種子畫素作為生長的七點,然後將種子畫素周圍鄰域中與種子有相同或相似性質的畫素(根據事先確定的生長或相似準則來確定)合併到種子畫素所在的區

區域生長演算法

1、理論基礎 區域生長演算法的基本思想是將有相似性質的畫素點合併到一起。對每一個區域要先指定一個種子點作為生長的起點,然後將種子點周圍領域的畫素點和種子點進行對比,將具有相似性質的點合併起來繼續向外生長,直到沒有滿足條件的畫素被包括進來為止。這樣一個區域的生長就完成了。這個過程中有幾個

分割之基於邊界的分割演算法(一)

基於邊界的點雲分割演算法通過檢測區域邊界得到分割塊。主要演算法有: 一、通過點雲強度的劇烈變化得到點雲邊界; 二、計算邊界梯度,計算點雲表面的法矢方向梯度變化以及3D線匹配; 三、對於距離影象的掃描線分割演算法,但不適用於密度不均勻的點雲資料。 四、通過

深度學習演算法分割-PointNet(五)

大家好,今天給大家介紹下cvpr2017 一篇文章Pointnet 語義分割,該網路基於tensorflow 寫的,非常輕巧方便,但是文章和程式碼有一定出入,在訓練過程中出現過擬合現象,大概訓練了10個小時多.1    需要準備的東東(1) Ubuntu 16.04  GTX1060 6G(2) CUDA 安

深度學習演算法分割-Pointnet++(一)

   在過去的這些年裡,對二維影象已經有了大量深入的研究,並且有著長足的發展。它在分類任務上取得了極好的結果主要得益於一下兩個關鍵因素:1.卷積神經網路。2.資料 - 大量影象資料可用。   但是對於3D點雲,資料正在迅速增長。大有從2D向3D發展的趨勢,比如在opencv中就已經慢慢包含了3D點雲的處理的相

PCL—分割(最小割算法)

number 作用 早就 有效 好的 介紹 不同的 優勢 bsp 1.點雲分割的精度   在之前的兩個章節裏介紹了基於采樣一致的點雲分割和基於臨近搜索的點雲分割算法。基於采樣一致的點雲分割算法顯然是意識流的,它只能割出大概的點雲(可能是杯子的一部分,但杯把兒肯定沒分割出來)

Efficient Online Segmentation for Sparse 3D Laser Scans-- 線上的稀疏分割

在基於鐳射的自動駕駛或者移動機器人的應用中,在移動場景中提取單個物件的能力是十分重要的。因為這樣的系統需要在動態的感知環境中感知到周圍發生變化或者移動的物件,在感知系統中,將影象或者點雲資料預處理成單個物體是進行進一步分析的第一個步驟。   在這篇文章中就提出了一種十分高效的分割方法。首先是將掃

#讀原始碼+論文# 三維分割Deep Learning Based Semantic Labelling of 3D Point Cloud in Visual SLAM

from Deep Learning Based Semantic Labelling of 3D Point Cloud in Visual SLAM 超體素方法進行預分割,將點雲根據相似性變成表層面片(surface patches)降低計算複雜度。  

區域生長演算法的一種C++實現

https://www.cnblogs.com/xuhui24/p/6262011.html   區域生長演算法是一種影象分割方法,能夠將影象中具有相同特徵的連通區域分割出來,同時保證較好的邊緣資訊。   區域生長演算法的優點是簡單,容易實現;但空間和時間複雜度較高,對分割影象

ros/pcl 分割——分離地面

程式碼  #include <ros/ros.h> // PCL specific includes #include <sensor_msgs/PointCloud2.h> #include <pcl_conversions/pcl_conv

區域生長演算法原理及MATLAB實現

% Segment based on area, Region Growing; clear all; close all; clc [fileName,pathName] = uigetfile('*.*','Please select an image');%檔案筐,選擇檔案 if(fileName)

基於歐幾里德聚類的鐳射雷達分割及ROS實現——學習總結

1、特別說明 本部落格是在復現大神部落格的過程中遇到問題的解決方式,具體的部落格地址是: https://blog.csdn.net/AdamShan/article/details/83015570#commentsedit 寫的非常好的博主,在此大力推薦!!! 2、實現過程

基於霍夫變換的分割方法

基於霍夫變換的點雲平面分割方法 (1)標準霍夫變換方法 (2)概率霍夫變換 (3)漸進概率霍夫變換 (4)隨機霍夫變換 (5)自適應霍夫變換 參考文獻: 1. Borrmann, D., et al., The 3D Hough Transform for plane det

三維計算機視覺(三)--分割

轉自:http://www.cnblogs.com/ironstark/p/5000147.html 點雲分割   點雲分割可謂點雲處理的精髓,也是三維影象相對二維影象最大優勢的體現。   點雲分割的目的提取點雲中的不同物體,從而實現分而治之,突出重點,單獨處理的目的。而在

PCL庫學習(3)----基於平面模型的分割(地面分割)(Plane Model Segmentation)

執行環境: VS2013,PCL1.8.0 程式碼參考:        最近做的專案需要對採集到的點雲場景進行去除地面的操作。在參考了CSDN博主:有夢想的田園犬對於PCL官方几種例程中的點雲分割方法的實驗後,考慮到系統的實時性要求,選擇基於平面模型的地面點雲去噪方

PCL 3D-NDT演算法配準

本節我們將介紹如何使用正態分佈變換演算法來確定兩個大型點雲(都超過100,000個點)之間的剛體變換。正態分佈變換演算法是一個配准算法,它應用於三維點的統計模型,使用標準最優化技術來確定兩個點雲間的最優的匹配,因為其在配準過程中不利用對應點的特徵計算和匹配,所以

PCL分割(1)

點雲分割是根據空間,幾何和紋理等特徵對點雲進行劃分,使得同一劃分內的點雲擁有相似的特徵,點雲的有效分割往往是許多應用的前提,例如逆向工作,CAD領域對零件的不同掃描表面進行分割,然後才能更好的進行空洞修復曲面重建,特徵描述和提取,進而進行基於3D內容的檢索,組合重用等。 案例

你不知道的SVD 演算法------配準+絕對定向+座標轉換

Sfm那篇部落格已經介紹,3D-3D的變換,不同學科稱呼不同。 在測繪領域,稱作為座標轉換,即七引數轉換—(3個旋轉,3個平移,1個尺度),通常尺度因子可以不計。最常見的情景諸如,54座標到80座標,80到CGS200座標等。 在攝影測量學科裡,稱為絕對定向

區域增長演算法實現影象分割(網路)

下面程式碼採用堆疊的方式實現了給定種子點的區域生長,該方法步驟如下:   (1)為輸出影象申請緩衝區,並初始化白色;   (2)將種子點入棧,並將輸出影象對應位置編輯黑色;   (3)從棧中彈出一個畫素點(該畫素點已在輸出緩衝區標記過),考察該畫素點的8鄰域中有畫素與種子點灰度差小於給定的閥值T,且該點在輸出