PCL 基于样本一致性的圆柱体分割

📅 2026/7/13 2:36:27
PCL 基于样本一致性的圆柱体分割
这个程序可以分割出PCL点云里的平面和圆柱体。先看一下输入点云桌子上有一个圆柱体形状的杯子程序运行后会分别分割出平面(桌子)和圆柱体杯子这是分割出来的平面桌子的深度图中间的黑色是杯子留下的影子下面是分割出来的圆柱体杯子。左边是杯子的横截面右边是竖起来放置的圆柱体现在把输入点云和输出点云放置在同一坐标系里这个就比较明显了红色的是分割出来的平面桌子绿色的是分割出来的圆柱体杯子蓝色的是输入点云。换一个角度下面这个角度可以解释输出的圆柱体为什么是是残缺的前面的点云把后面的点云挡住了。输入table_scene_mug_stereo_textured.pcd 带有圆柱体的PCL点云输出table_scene_mug_stereo_textured_cylinder.pcd 分割出来的圆柱体table_scene_mug_stereo_textured_plane.pcd 分割出来的平面代码#include pcl/ModelCoefficients.h #include pcl/io/pcd_io.h #include pcl/point_types.h #include pcl/filters/extract_indices.h #include pcl/filters/passthrough.h #include pcl/features/normal_3d.h #include pcl/sample_consensus/method_types.h #include pcl/sample_consensus/model_types.h #include pcl/segmentation/sac_segmentation.h typedef pcl::PointXYZ PointT; int main () { // All the objects needed pcl::PCDReader reader; pcl::PassThroughPointT pass; pcl::NormalEstimationPointT, pcl::Normal ne; pcl::SACSegmentationFromNormalsPointT, pcl::Normal seg; pcl::PCDWriter writer; pcl::ExtractIndicesPointT extract; pcl::ExtractIndicespcl::Normal extract_normals; pcl::search::KdTreePointT::Ptr tree (new pcl::search::KdTreePointT ()); // Datasets pcl::PointCloudPointT::Ptr cloud (new pcl::PointCloudPointT); pcl::PointCloudPointT::Ptr cloud_filtered (new pcl::PointCloudPointT); pcl::PointCloudpcl::Normal::Ptr cloud_normals (new pcl::PointCloudpcl::Normal); pcl::PointCloudPointT::Ptr cloud_filtered2 (new pcl::PointCloudPointT); pcl::PointCloudpcl::Normal::Ptr cloud_normals2 (new pcl::PointCloudpcl::Normal); pcl::ModelCoefficients::Ptr coefficients_plane (new pcl::ModelCoefficients), coefficients_cylinder (new pcl::ModelCoefficients); pcl::PointIndices::Ptr inliers_plane (new pcl::PointIndices), inliers_cylinder (new pcl::PointIndices); // Read in the cloud data reader.read (table_scene_mug_stereo_textured.pcd, *cloud); std::cerr PointCloud has: cloud-size () data points. std::endl; // Build a passthrough filter to remove spurious NaNs and scene background pass.setInputCloud (cloud); pass.setFilterFieldName (z); pass.setFilterLimits (0, 1.5); pass.filter (*cloud_filtered); std::cerr PointCloud after filtering has: cloud_filtered-size () data points. std::endl; // Estimate point normals ne.setSearchMethod (tree); ne.setInputCloud (cloud_filtered); ne.setKSearch (50); ne.compute (*cloud_normals); // Create the segmentation object for the planar model and set all the parameters seg.setOptimizeCoefficients (true); seg.setModelType (pcl::SACMODEL_NORMAL_PLANE); seg.setNormalDistanceWeight (0.1); seg.setMethodType (pcl::SAC_RANSAC); seg.setMaxIterations (100); seg.setDistanceThreshold (0.03); seg.setInputCloud (cloud_filtered); seg.setInputNormals (cloud_normals); // Obtain the plane inliers and coefficients seg.segment (*inliers_plane, *coefficients_plane); std::cerr Plane coefficients: *coefficients_plane std::endl; // Extract the planar inliers from the input cloud extract.setInputCloud (cloud_filtered); extract.setIndices (inliers_plane); extract.setNegative (false); // Write the planar inliers to disk pcl::PointCloudPointT::Ptr cloud_plane (new pcl::PointCloudPointT ()); extract.filter (*cloud_plane); std::cerr PointCloud representing the planar component: cloud_plane-size () data points. std::endl; writer.write (table_scene_mug_stereo_textured_plane.pcd, *cloud_plane, false); // Remove the planar inliers, extract the rest extract.setNegative (true); extract.filter (*cloud_filtered2); extract_normals.setNegative (true); extract_normals.setInputCloud (cloud_normals); extract_normals.setIndices (inliers_plane); extract_normals.filter (*cloud_normals2); // Create the segmentation object for cylinder segmentation and set all the parameters 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 (cloud_normals2); // Obtain the cylinder inliers and coefficients seg.segment (*inliers_cylinder, *coefficients_cylinder); std::cerr Cylinder coefficients: *coefficients_cylinder std::endl; // Write the cylinder inliers to disk extract.setInputCloud (cloud_filtered2); extract.setIndices (inliers_cylinder); extract.setNegative (false); pcl::PointCloudPointT::Ptr cloud_cylinder (new pcl::PointCloudPointT ()); extract.filter (*cloud_cylinder); if (cloud_cylinder-points.empty ()) std::cerr Cant find the cylindrical component. std::endl; else { std::cerr PointCloud representing the cylindrical component: cloud_cylinder-size () data points. std::endl; writer.write (table_scene_mug_stereo_textured_cylinder.pcd, *cloud_cylinder, false); } return (0); }参考Cylinder model segmentation — Point Cloud Library 0.0 documentation