当前位置:网站首页>PCL—点云数据分割
PCL—点云数据分割
2022-08-02 03:19:00 【龙虾在剥我的壳】
一.算法原理
欧式聚类是一种基于欧氏距离度量的聚类算法,过程如下:
1.首先选取种子点,利用kd-tree对种子点进行半径r邻域搜索,若邻域内存在点,则与种子点归为同一聚类簇Q;
2.在聚类簇Q中选取新的种子点,继续执行步骤1),若Q中点数不再增加,则Q聚类结束;
3.设置聚类点数阈值区间[Num_min, Num_max],若聚类簇Q中点数在阈值区间内,则保存聚类结果;
4.在剩余点云中选取新的种子点,继续执行以上步骤,直到遍历完成点云中所有点。
流程图如下:
二.代码实现
#include <iostream>
#include <boost/thread.hpp>
#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>
#include <pcl/visualization/pcl_visualizer.h>
int color_bar[][3] =
{
{
255,0,0},
{
0,255,0 },
{
0,0,255 },
{
0,255,255 },
{
255,255,0 },
{
100,100,100 },
{
255,0,255 }
};
int
main(int argc, char** argv)
{
// Read in the cloud data
pcl::PCDReader reader;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>), cloud_f(new pcl::PointCloud<pcl::PointXYZ>);
reader.read("D:\\.....\\03.pcd", *cloud);
std::cout << "PointCloud before filtering has: " << cloud->points.size() << " data points." << std::endl; //*
// Create the filtering object: downsample the dataset using a leaf size of 1cm
pcl::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);//设置体素栅格叶大小,向量参数leaf_ size 是体素栅格叶大小参数,每个元素分别表示体素在XYZ方向上的尺寸
vg.filter(*cloud_filtered);
// std::cout << "PointCloud after filtering has: " << cloud_filtered->points.size() << " data points." << std::endl; //*
std::cout << "PointCloud after filtering has: " << cloud_filtered->points.size() << " data points." << std::endl; //*
// Create the segmentation object for the planar model and set all the parameters
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.9 * nr_points)
{
// Segment the largest planar component from the remaining cloud
seg.setInputCloud(cloud_filtered);
seg.segment(*inliers, *coefficients);
if (inliers->indices.size() == 0)
{
std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
break;
}
// Extract the planar inliers from the input cloud
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud(cloud_filtered);
extract.setIndices(inliers);
extract.setNegative(false);
// Write the planar inliers to disk
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;
}
// Creating the KdTree object for the search method of the extraction
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.018); //设置近邻搜索的搜索半径为2cm
ec.setMinClusterSize(6000); //设置一个聚类需要的最少点数目为100
ec.setMaxClusterSize(15000); //设置一个聚类需要的最大点数目为25000
ec.setSearchMethod(tree); //设置点云的搜索机制
ec.setInputCloud(cloud_filtered); //设置原始点云
ec.extract(cluster_indices); //从点云中提取聚类
// 可视化部分
pcl::visualization::PCLVisualizer viewer("segmention");
// 我们将要使用的颜色
float bckgr_gray_level = 0.0; // 黑色
float txt_gray_lvl = 1.0 - bckgr_gray_level;
int num = cluster_indices.size();
//迭代访问点云索引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>);
//创建新的点云数据集cloud_cluster,将所有当前聚类写入到点云数据集中
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); //*
//赋予显示点云的颜色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_in_color_h(cloud,
color_bar[j][0],
color_bar[j][1],
color_bar[j][2]);
viewer.addPointCloud(cloud_cluster, cloud_in_color_h, std::to_string(j));
pcl::io::savePCDFile("D:\\.....\\033.pcd", *cloud_cluster);
j++;
}
//等待直到可视化窗口关闭。
while (!viewer.wasStopped())
{
viewer.spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return (0);
}
三.结果展示
本实验用于将一个小车点云数据中的轮胎分离出来
原始点云
结果点云
边栏推荐
- 程序员的七夕浪漫时刻
- 基于时延估计的动力型下肢假肢分段控制策略研究
- ModuleNotFoundError No module named ‘xxx‘可能的解决方案大全
- (Repost) HashCode Summary (1)
- mysql8.0安装教程与配置(最详细)操作简单
- 二维数组实战项目--------《三子棋》
- 一种基于行为空间的回声状态网络参数优化方法
- I will give you a chance to interview in a big factory. Can you interview?Come in and see!
- rem适配
- Daily practice------There are n integers, so that the previous numbers are moved back m positions in order, and the last m numbers become the first m numbers
猜你喜欢
随机推荐
多个el-select下拉框无法选中相同内容
Small program (necessary common sense for development) 1
rem适配
深度学习:目标检测入门知识
Double Strings (don't always forget substr)
day11--shell脚本
嘉为蓝鲸携手东风集团、上汽零束再获信通院四项大奖
(转帖)HashCode总结(2)
mysql创建表
小程序组件总结
Daily practice------There are n integers, so that the previous numbers are moved back m positions in order, and the last m numbers become the first m numbers
Redis安装,基本命令,持久化方式,集群
代码随想录笔记_哈希_383赎金信
LeetCode:746. 使用最小花费爬楼梯【动态规划】
线性代数学习笔记3-3:逆矩阵的理解
mysql卸载详细教程
OD-Model [4]: SSD
DOM破坏及复现实验
Redis笔记基础篇:6分钟看完Redis的八种数据类型
【遥控器开发基础教程1】疯壳·开源编队无人机-GPIO(遥控器指示灯控制)