版本: >PCL1.3
平面分割可用于地面检测,ransac是一种非常有效的平面分割方法,根据设定的平面模型不断迭代找出属于平面的点。同时通过设定模型距离阈值(setDistanceThreshold)可以检测不同起伏程度的地面。
本例中使用的点云数据(test.pcd)请见百度网盘分享。
链接:https://pan.baidu.com/s/1CN3sb1lRylfvT67PnRdKiw
提取码:kz7q
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/visualization/cloud_viewer.h>
int main(int argc, char** argv)
{
pcl::PCDReader reader;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>);
reader.read("test.pcd", *cloud); //读取点云
pcl::PointIndices::Ptr inliers(new pcl::PointIndices); //创建平面分割后存储平面点云的索引
pcl::SACSegmentation<pcl::PointXYZ> seg; //创建sac分割对象
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE); //设置模型为平面
seg.setMethodType(pcl::SAC_RANSAC); //设置分割方法为ransac
seg.setMaxIterations(100); //设置最大迭代次数
seg.setDistanceThreshold(0.15); //设置偏离模型距离阈值
seg.setInputCloud(cloud);
seg.segment(*inliers, *coefficients);
if (inliers->indices.size() == 0) //检查一下是否有平面分割出来
{
std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
}
pcl::ExtractIndices<pcl::PointXYZ> extract; //抽取分割得到的平面点云
extract.setInputCloud(cloud);
extract.setIndices(inliers);
extract.setNegative(false);
extract.filter(*cloud_plane);
std::cout << "PointCloud representing the planar component: " << cloud_plane->size() << " data points." << std::endl;
pcl::visualization::PCLVisualizer viewer("Cloud Viewer");
int v1(0); //创建左窗口显示原始点云
viewer.createViewPort(0, 0, 0.5, 1.0, v1); //左右窗口大小划分,1:1
viewer.setBackgroundColor(0, 0, 0, v1);
viewer.addText("Cloud Original", 2, 2, "Cloud Original", v1); //窗口下的标题
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> rgb1(cloud, "z");
viewer.addPointCloud<pcl::PointXYZ>(cloud, rgb1, "original cloud", v1);
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "original cloud", v1);
viewer.addCoordinateSystem(1.0, "original cloud", v1);
int v2(1); //创建右窗口显示分割后的平面
viewer.createViewPort(0.5, 0, 1.0, 1.0, v2); //左右窗口大小划分,1:1
viewer.setBackgroundColor(0, 0, 0, v2);
viewer.addText("Cloud Segmentation", 2, 2, "Cloud Segmentation", v2); //窗口下的标题
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> rgb2(cloud_plane, "z");
viewer.addPointCloud<pcl::PointXYZ>(cloud_plane, rgb2, "plane cloud", v2);
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "plane cloud", v2);
viewer.addCoordinateSystem(1.0, "plane cloud", v2);
viewer.spin();
return (0);
}