PCL中分割_欧式分割(1)
基于歐式距離的分割和基于區域生長的分割本質上都是用區分鄰里關系遠近來完成的。由于點云數據提供了更高維度的數據,故有很多信息可以提取獲得。歐幾里得算法使用鄰居之間距離作為判定標準,而區域生長算法則利用了法線,曲率,顏色等信息來判斷點云是否應該聚成一類。
(1)歐幾里德算法
具體的實現方法大致是:
因為點云總是連成片的,很少有什么東西會浮在空中來區分。但是如果結合此算法可以應用很多東東。比如
當然,一旦桌面被剔除,桌上的物體就自然成了一個個的浮空點云團。就能夠直接用歐幾里德算法進行分割了,這樣就可以提取出我們想要識別的東西
?在這里我們就可以使用提取平面,利用聚類的方法平面去掉再顯示剩下的所有聚類的結果,在這里也就是有關注我的微信公眾號的小伙伴向我請教,說雖然都把平面和各種非平面提取出來了,但是怎么把非平面的聚類對象可視化出來呢?
哈哈,剛開始我也以為沒有例程實現這樣的可視化,也許比較難吧,但是仔細一想,提取出來的聚類的對象都是單獨的顯示在相對與源文件不變的位置所以我們直接相加就應該可以實現阿~所以廢話沒多說我就直接寫程序,的確可視化的結果就是我想要的結果
那么我們看一下我的代碼吧
#include <pcl/ModelCoefficients.h> #include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/filters/extract_indices.h> #include <pcl/filters/voxel_grid.h> #include <pcl/features/normal_3d.h> #include <pcl/kdtree/kdtree.h> #include <pcl/sample_consensus/method_types.h> #include <pcl/sample_consensus/model_types.h> #include <pcl/segmentation/sac_segmentation.h> #include <pcl/segmentation/extract_clusters.h>/******************************************************************************打開點云數據,并對點云進行濾波重采樣預處理,然后采用平面分割模型對點云進行分割處理提取出點云中所有在平面上的點集,并將其存盤 ******************************************************************************/ int main (int argc, char** argv) {// 讀取文件 pcl::PCDReader reader;pcl::PointCloud<pcl::PointXYZ>::Ptr add_cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);reader.read ("table_scene_lms400.pcd", *cloud);std::cout << "PointCloud before filtering has: " << cloud->points.size () << " data points." << std::endl; //*// 下采樣,體素葉子大小為0.01pcl::VoxelGrid<pcl::PointXYZ> vg;pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);vg.setInputCloud (cloud);vg.setLeafSize (0.01f, 0.01f, 0.01f);vg.filter (*cloud_filtered);std::cout << "PointCloud after filtering has: " << cloud_filtered->points.size () << " data points." << std::endl; //*//創建平面模型分割的對象并設置參數pcl::SACSegmentation<pcl::PointXYZ> seg;pcl::PointIndices::Ptr inliers (new pcl::PointIndices); //設置聚類的內點索引pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);//平面模型的因子pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZ> ());pcl::PCDWriter writer;seg.setOptimizeCoefficients (true);seg.setModelType (pcl::SACMODEL_PLANE); //分割模型seg.setMethodType (pcl::SAC_RANSAC); //隨機參數估計方法seg.setMaxIterations (100); //最大的迭代的次數seg.setDistanceThreshold (0.02); //設置閥值int i=0, nr_points = (int) cloud_filtered->points.size ();//剩余點云的數量while (cloud_filtered->points.size () > 0.3 * nr_points){// 從剩余點云中再分割出最大的平面分量 (因為我們要處理的點云的數據是兩個平面的存在的) seg.setInputCloud (cloud_filtered);seg.segment (*inliers, *coefficients);if (inliers->indices.size () == 0) //如果內點的數量已經等于0,就說明沒有 {std::cout << "Could not estimate a planar model for the given dataset." << std::endl;break;}// 從輸入的點云中提取平面模型的內點pcl::ExtractIndices<pcl::PointXYZ> extract;extract.setInputCloud (cloud_filtered);extract.setIndices (inliers); //提取內點的索引并存儲在其中extract.setNegative (false);// 得到與平面表面相關聯的點云數據extract.filter (*cloud_plane);std::cout << "PointCloud representing the planar component: " << cloud_plane->points.size () << " data points." << std::endl;// // 移去平面局內點,提取剩余點云extract.setNegative (true);extract.filter (*cloud_f);*cloud_filtered = *cloud_f;}// 創建用于提取搜索方法的kdtree樹對象pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);tree->setInputCloud (cloud_filtered);std::vector<pcl::PointIndices> cluster_indices;pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec; //歐式聚類對象ec.setClusterTolerance (0.02); // 設置近鄰搜索的搜索半徑為2cmec.setMinClusterSize (100); //設置一個聚類需要的最少的點數目為100ec.setMaxClusterSize (25000); //設置一個聚類需要的最大點數目為25000ec.setSearchMethod (tree); //設置點云的搜索機制 ec.setInputCloud (cloud_filtered);ec.extract (cluster_indices); //從點云中提取聚類,并將點云索引保存在cluster_indices中//迭代訪問點云索引cluster_indices,直到分割處所有聚類int j = 0;for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it){ //迭代容器中的點云的索引,并且分開保存索引的點云pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); ++pit)//設置保存點云的屬性問題cloud_cluster->points.push_back (cloud_filtered->points[*pit]); //*cloud_cluster->width = cloud_cluster->points.size ();cloud_cluster->height = 1;cloud_cluster->is_dense = true;std::cout << "PointCloud representing the Cluster: " << cloud_cluster->points.size () << " data points." << std::endl;std::stringstream ss;ss << "cloud_cluster_" << j << ".pcd";writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false); //*//————————————以上就是實現所有的聚類的步驟,并且保存了————————————————————————————// //以下就是我為了回答網友提問解決可視化除了平面以后的可視化的代碼也就兩行 j++;*add_cloud+=*cloud_cluster;pcl::io::savePCDFileASCII("add_cloud.pcd",*add_cloud);}return (0); }編譯生成可執行文件后結果如下
?那么我們查看以下源文件可視化的結果
再可視化我們聚類后除了平面的可視化的結果,從中可以看出效果還是很明顯的。
當然總結一下,我們在實際應用的過程中可能沒那么輕松,因為我們要根據實際的點云的大小來設置相關的參數,如果參數錯誤就不太能實現現在的效果。
所以對實際應用中參數的設置是需要經驗的吧,下一期會介紹其他的分割方法
有興趣這關注微信公眾號,加入我們與更多的人交流,同時也歡迎更多的來自網友的分享
?
?
轉載于:https://www.cnblogs.com/li-yao7758258/p/6694873.html
總結
以上是生活随笔為你收集整理的PCL中分割_欧式分割(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shinhan是什么银行
- 下一篇: Android攻城狮ListView