1 处理过程可视化
原始数据
直通滤波过滤后
pcl::ProjectInliers结果
pcl::ExtractIndices结果
凹包结果
凸包结果
2 处理过程分析:
原始点云 ---> 直通滤波 --> pcl::SACSegmentation分割出平面 -->pcl::ProjectInliers投影 --> pcl::ConcaveHull凹包重构
2.1 有一个步骤可以被替换
pcl::ProjectInliers这步骤是将直通滤波过滤得到的结果,全部投影到pcl::SACSegmentation分割到的平面上。这一步可以用pcl::ExtractIndices代替,其直接提取属于平面的点云。替换后不影响后面的凹包重构结果
2.2 凹包与凸包的区别
凹包是最小外接,凸包是最大外接,详情可以看下面这篇博客
PCL计算ConvexHull凸包、ConcaveHull凹包_pcl::concavehull_com1098247427的博客-CSDN博客
3 凹包参数探究
该算法中有许多参数可设置:
setAlpha(double alpha)
:设置凹凸包计算的精细程度。alpha
参数控制了计算凹凸包时使用的半径大小。较小的alpha
值会产生更精细的凹凸包,而较大的alpha
值会产生更粗糙的凹凸包。
setDimension(int dim)
:设置凹凸包计算的维度。dim
参数指定了计算凹凸包的维度。默认值为3,表示计算三维凹凸包。如果输入点云是二维的,则可以将dim
设置为2。
setKeepInformation(bool keep)
:设置是否保留输入点云的信息。如果将keep
参数设置为true
,则计算的凹凸包点云将保留输入点云的法线和曲率信息。如果设置为false
,则不保留这些信息。
setAlphaMultiplier(double multiplier)
:设置alpha
参数的乘数因子。multiplier
参数用于调整alpha
参数的值。默认值为1.0,表示使用alpha
参数的原始值。
通常只需手动设置alpha参数,其控制了计算凹凸包时使用的半径大小。较小的alpha值会产生更精细的凹凸包,而较大的alpha值会产生更粗糙的凹凸包。
将alpha参数设置为0.01,得到:
4 代码
cpp
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/project_inliers.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/surface/concave_hull.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/surface/convex_hull.h>
#include <pcl/filters/extract_indices.h>
int main()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>),
cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>),
cloud_projected(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCDReader reader;
reader.read("/home/lrj/work/pointCloudData/table_scene_mug_stereo_textured.pcd",*cloud);
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName("z");
pass.setFilterLimits(0, 1.1);
pass.filter(*cloud_filtered);
std::cerr << "PointCloud after filtering has: "
<< cloud_filtered->size() << " data points.\n";
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
pcl::SACSegmentation<pcl::PointXYZ> seg;
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setDistanceThreshold(0.01);
seg.setInputCloud(cloud_filtered);
seg.segment(*inliers, *coefficients);
std::cerr << "PointCloud after segmentation has: "
<< inliers->indices.size() << " inliers.\n";
// 将点云投影到拟合的平面上
// pcl::ProjectInliers<pcl::PointXYZ> proj;
// proj.setModelType(pcl::SACMODEL_PLANE);
// proj.setInputCloud(cloud_filtered);
// proj.setModelCoefficients(coefficients);
// proj.filter(*cloud_projected);
// std::cerr << "PointCloud after projection has: "
// << cloud_projected->size() << " data points.\n" << std::endl;
// 直接提取属于平面点云
pcl::ExtractIndices<pcl::PointXYZ> extract;
extract.setInputCloud(cloud_filtered);
extract.setIndices(inliers);
extract.setNegative(false);
extract.filter(*cloud_projected);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);
pcl::ConcaveHull<pcl::PointXYZ> chull;
chull.setInputCloud(cloud_projected);
chull.setAlpha(0.1);
chull.reconstruct(*cloud_hull);
std::cerr << "Concave hull has: " << cloud_hull->size()
<< " data points.\n" << std::endl;
pcl::visualization::CloudViewer vis("cloud visualization");
vis.showCloud(cloud_hull);
while(!vis.wasStopped())
{
}
}