-
pcd文件在我的下载中 0 c币
-
流程为:
-
原始点云为:
-
直通滤波处理
-
分别分离出平面和圆柱体
-
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/ModelCoefficients.h> //模型的头文件
#include <pcl/filters/extract_indices.h> //按索引进行提取的滤波
#include <pcl/filters/passthrough.h> //直通滤波
#include <pcl/features/normal_3d.h>
#include <pcl/sample_consensus/model_types.h> //分割模型
#include <pcl/sample_consensus/method_types.h> //分割方法
#include <pcl/segmentation/sac_segmentation.h> //随机采样一致性的分割
int main() {
/*
* 读取点云
*/
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("table_scene_mug_stereo_textured.pcd", *cloud);
std::cout << "读取了点云 size = " << cloud->size() << std::endl;
/*
* 直通滤波处理点云
* 去除无效的部分
* 处理完成后还剩下一个杯子和一个平面
* 并把处理好的点云放到 cloud_filtered
*/
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
//直通滤波
pcl::PassThrough<pcl::PointXYZ> pass;
//输入的点云
pass.setInputCloud(cloud);
//设置处理字段是Z轴 范围是 z = (0 ,1.2)
pass.setFilterFieldName("z");
pass.setFilterLimits(0, 1.2);
pass.setFilterLimitsNegative(false); //true = 过滤区间内的点 false = 过滤区间外的点
pass.filter(*cloud_filtered);
std::cout << "直通滤波处理后的点云 size = " << cloud_filtered->size() << std::endl;
/*
* 采用基于法线估计的方法 先分割出平面
*/
//存放法线结构的点云
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);
//法线评估对象
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
//kd搜索树
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
ne.setInputCloud(cloud_filtered);
ne.setSearchMethod(tree);
ne.setKSearch(50); //搜索树的范围
ne.compute(*cloud_normals);
//基于法线的采样一致性分割 包括参数:索引,模型
pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> seg;
//基于法线估计的平面分割模型 这个模型是一个有条件限制的平面模型
//在规定的最大角度偏差限制下,每个局内的点的法线必须与所估计的平面的法线平行。
pcl::PointIndices::Ptr inliers_plane(new pcl::PointIndices);
pcl::ModelCoefficients::Ptr coefficients_plane(new pcl::ModelCoefficients);
//参数优化
seg.setOptimizeCoefficients(true);
//输入
seg.setInputCloud(cloud_filtered);
seg.setInputNormals(cloud_normals);
//设置分割的模型
seg.setModelType(pcl::SACMODEL_NORMAL_PLANE);
//设置分割的方法
seg.setMethodType(pcl::SAC_RANSAC);
//设置法线相对权重 权重与距离成正比 与角度成反比
seg.setNormalDistanceWeight(0.1);
//设置最大迭代次数
seg.setMaxIterations(100);
//设置阈值
seg.setDistanceThreshold(0.03);
//分割
seg.segment(*inliers_plane, *coefficients_plane);
std::cout << "得到平面内的点 size = " << inliers_plane->indices.size() << std::endl;
/*
* 分别将平面和剩余部分 分离开
*/
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered2(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptr normals_plane(new pcl::PointCloud<pcl::Normal>);
pcl::PointCloud<pcl::Normal>::Ptr normals_filtered2(new pcl::PointCloud<pcl::Normal>);
//点提取对象和法向量提取对象
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud(cloud_filtered);
extract.setIndices(inliers_plane);
pcl::ExtractIndices<pcl::Normal> extract_normal;
extract_normal.setInputCloud(cloud_normals);
extract_normal.setIndices(inliers_plane);
//处理平面
extract.setNegative(false);
extract.filter(*cloud_plane);
extract_normal.setNegative(false);
extract_normal.filter(*normals_plane);
//处理剩下的部分
extract.setNegative(true);
extract.filter(*cloud_filtered2);
extract_normal.setNegative(true);
extract_normal.filter(*normals_filtered2);
/*
* 从filtered2中 提取圆柱体
*/
pcl::ModelCoefficients::Ptr coefficient_cylinder(new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers_cylinder(new pcl::PointIndices);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cylinder(new pcl::PointCloud<pcl::PointXYZ>);
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_CYLINDER);
seg.setMethodType(pcl::SAC_RANSAC);
//设置表面法线权重系数
seg.setNormalDistanceWeight(0.1);
seg.setMaxIterations(10000);
seg.setDistanceThreshold(0.05);
//设置估计的圆柱体的半径范围
seg.setRadiusLimits(0, 0.1);
seg.setInputCloud(cloud_filtered2);
seg.setInputNormals(normals_filtered2);
seg.segment(*inliers_cylinder, *coefficient_cylinder);
//提取出点云cloud_cylinder
extract.setInputCloud(cloud_filtered2);
extract.setIndices(inliers_cylinder);
extract.setNegative(false);
extract.filter(*cloud_cylinder);
/*
* 可视化
*/
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("三个窗口"));
int v1(0);
int v2(1);
int v3(2);
//DDDD
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->createViewPort(0.5, 0.0, 1.0, 0.5, v2);
viewer->createViewPort(0.5, 0.5, 1.0, 1.0, v3);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_out_red(cloud, 255, 0, 0);
viewer->addPointCloud(cloud, cloud_out_red, "cloud_out1", v1);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_out_green(cloud, 0, 255, 0); // 显示绿色点云
viewer->addPointCloud(cloud_plane, cloud_out_green, "cloud_out2", v2); // 平面
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_out_blue(cloud, 0, 0, 255); // 显示蓝色点云
viewer->addPointCloud(cloud_cylinder, cloud_out_blue, "cloud_out3", v3); // 圆柱
viewer->spin();
return 0;
}