当前位置: 首页 > news >正文

PCL 将点云投影到圆柱(Ransac拟合)

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1 法线估计

2.1.2 圆柱拟合

2.1.3 投影滤波

2.1.4 可视化

2.2完整代码

三、实现效果


PCL点云算法汇总及实战案例汇总的目录地址链接:

PCL点云算法与项目实战案例汇总(长期更新)


一、概述

        点云投影到圆柱模型 是通过拟合点云数据中的圆柱形特征,将原始点云投影到圆柱体表面。通过拟合圆柱体的模型,可以将点云数据与该圆柱体匹配,并将其投影到圆柱表面。该过程常用于几何建模、特征提取和3D重建中。

1.1原理

  1. 法线估计:通过计算点云的法向量,帮助拟合几何模型。
  2. 圆柱拟合:使用RANSAC算法对点云进行圆柱模型拟合,获得圆柱模型系数(包括轴线方向、圆柱半径等)。
  3. 投影滤波:将原始点云投影到拟合得到的圆柱模型上,使点云数据与圆柱模型相匹配。

1.2实现步骤

  1. 读取点云数据并计算其法向量。
  2. 使用RANSAC算法拟合圆柱模型,获取模型系数。
  3. 将原始点云投影到圆柱体表面。
  4. 可视化原始点云和投影后的点云

1.3应用场景

  1. 管道检测:在工业或建筑领域,圆柱形的物体如管道、柱子等,常见于各种检测任务,通过将点云投影到圆柱模型,可以检测和分析这些物体的几何特征。
  2. 3D重建:在3D重建过程中,圆柱形物体(如杆、柱等)需要精确拟合,以确保重建模型的准确性。
  3. 医学成像:圆柱模型在骨骼、血管等医学影像处理中也有应用,点云投影可以辅助分析器官或骨骼的形态。
  4. 机器人导航:在复杂环境中,圆柱形障碍物的检测有助于机器人避障和路径规划。

二、代码实现

2.1关键函数

2.1.1 法线估计

#include <pcl/features/normal_3d.h>  // 引入法线估计相关的头文件// 计算点云法线
void computeNormals(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals)
{pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());ne.setSearchMethod(tree);  // 设置搜索方式ne.setInputCloud(cloud);   // 输入点云ne.setKSearch(20);         // 设置K近邻搜索点的个数ne.compute(*normals);      // 计算法线
}

2.1.2 圆柱拟合

#include <pcl/segmentation/sac_segmentation.h>  // 引入分割模块// 圆柱拟合
void segmentCylinder(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,pcl::PointCloud<pcl::Normal>::Ptr normals,pcl::PointIndices::Ptr inliers_cylinder,pcl::ModelCoefficients::Ptr coefficients_cylinder)
{pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> seg;seg.setInputCloud(cloud);   // 输入点云seg.setInputNormals(normals);  // 输入法向量seg.setOptimizeCoefficients(true);  // 对估计的模型系数进行优化seg.setModelType(pcl::SACMODEL_CYLINDER);  // 设置模型类型为圆柱seg.setMethodType(pcl::SAC_RANSAC);  // 使用RANSAC算法seg.setNormalDistanceWeight(0.3);  // 设置表面法线的权重seg.setMaxIterations(10000);  // 最大迭代次数seg.setDistanceThreshold(0.1);  // 内点到模型的最大距离seg.setRadiusLimits(2.0, 3.0);  // 圆柱半径范围seg.segment(*inliers_cylinder, *coefficients_cylinder);  // 执行分割,获取模型系数
}

2.1.3 投影滤波

#include <pcl/filters/project_inliers.h>  // 引入投影滤波器头文件// 将点云投影到圆柱
void projectPointCloudToCylinder(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,pcl::ModelCoefficients::Ptr coefficients_cylinder,pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected)
{pcl::ProjectInliers<pcl::PointXYZ> proj;proj.setModelType(pcl::SACMODEL_CYLINDER);  // 设置模型类型为圆柱proj.setInputCloud(cloud);  // 输入点云proj.setModelCoefficients(coefficients_cylinder);  // 输入圆柱模型系数proj.filter(*cloud_projected);  // 执行投影滤波
}

2.1.4 可视化

#include <pcl/visualization/pcl_visualizer.h>  // 引入可视化库// 可视化原始点云和投影后的点云
void visualizePointClouds(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,pcl::PointCloud<pcl::PointXYZ>::Ptr projected_cloud)
{pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Cylinder Projection Visualization"));// 设置视口1,显示原始点云int vp_1;viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1);  // 白色背景viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(cloud, 0, 255, 0);  // 绿色显示原始点云viewer->addPointCloud(cloud, cloud_color, "original_cloud", vp_1);// 设置视口2,显示投影后的点云int vp_2;viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2);  // 浅灰色背景viewer->addText("Projected PointCloud", 10, 10, "vp2_text", vp_2);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> projected_color(projected_cloud, 0, 0, 255);  // 蓝色显示投影后的点云viewer->addPointCloud(projected_cloud, projected_color, "projected_cloud", vp_2);while (!viewer->wasStopped()){viewer->spinOnce(100);}
}

2.2完整代码

#include <iostream>
#include <pcl/io/pcd_io.h>  // PCD文件读取
#include <pcl/point_types.h>  // 点云类型
#include <pcl/ModelCoefficients.h>  // 模型系数
#include <pcl/features/normal_3d.h>  // 法线估计
#include <pcl/segmentation/sac_segmentation.h>  // 分割
#include <pcl/filters/project_inliers.h>  // 投影滤波
#include <pcl/visualization/pcl_visualizer.h>  // 可视化库
#include <boost/thread/thread.hpp>  // 线程库// 计算点云法线
void computeNormals(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, pcl::PointCloud<pcl::Normal>::Ptr normals)
{pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());ne.setSearchMethod(tree);  // 设置搜索方式ne.setInputCloud(cloud);   // 输入点云ne.setKSearch(20);         // 设置K近邻搜索点的个数ne.compute(*normals);      // 计算法线
}// 圆柱拟合
void segmentCylinder(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,pcl::PointCloud<pcl::Normal>::Ptr normals,pcl::PointIndices::Ptr inliers_cylinder,pcl::ModelCoefficients::Ptr coefficients_cylinder)
{pcl::SACSegmentationFromNormals<pcl::PointXYZ, pcl::Normal> seg;seg.setInputCloud(cloud);   // 输入点云seg.setInputNormals(normals);  // 输入法向量seg.setOptimizeCoefficients(true);  // 对估计的模型系数进行优化seg.setModelType(pcl::SACMODEL_CYLINDER);  // 设置模型类型为圆柱seg.setMethodType(pcl::SAC_RANSAC);  // 使用RANSAC算法seg.setNormalDistanceWeight(0.3);  // 设置表面法线的权重seg.setMaxIterations(10000);  // 最大迭代次数seg.setDistanceThreshold(0.1);  // 内点到模型的最大距离seg.setRadiusLimits(2.0, 3.0);  // 圆柱半径范围seg.segment(*inliers_cylinder, *coefficients_cylinder);  // 执行分割,获取模型系数
}// 将点云投影到圆柱
void projectPointCloudToCylinder(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,pcl::ModelCoefficients::Ptr coefficients_cylinder,pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected)
{pcl::ProjectInliers<pcl::PointXYZ> proj;proj.setModelType(pcl::SACMODEL_CYLINDER);  // 设置模型类型为圆柱proj.setInputCloud(cloud);  // 输入点云proj.setModelCoefficients(coefficients_cylinder);  // 输入圆柱模型系数proj.filter(*cloud_projected);  // 执行投影滤波
}// 可视化函数
void visualizePointClouds(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,pcl::PointCloud<pcl::PointXYZ>::Ptr projected_cloud)
{pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Cylinder Projection Visualization"));// 设置视口1,显示原始点云int vp_1;viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1);  // 白色背景viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(cloud, 0, 255, 0);  // 绿色显示原始点云viewer->addPointCloud(cloud, cloud_color, "original_cloud", vp_1);// 设置视口2,显示投影后的点云int vp_2;viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);viewer->setBackgroundColor(0.98, 0.98, 0.98, vp_2);  // 浅灰色背景viewer->addText("Projected PointCloud", 10, 10, "vp2_text", vp_2);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> projected_color(projected_cloud, 0, 0, 255);  // 蓝色显示投影后的点云viewer->addPointCloud(projected_cloud, projected_color, "projected_cloud", vp_2);while (!viewer->wasStopped()){viewer->spinOnce(100);}
}// main函数
int main(int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::io::loadPCDFile<pcl::PointXYZ>("侍女.pcd", *cloud);pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);computeNormals(cloud, normals);  // 计算法向量pcl::PointIndices::Ptr inliers_cylinder(new pcl::PointIndices);pcl::ModelCoefficients::Ptr coefficients_cylinder(new pcl::ModelCoefficients);segmentCylinder(cloud, normals, inliers_cylinder, coefficients_cylinder);  // 圆柱拟合pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>);projectPointCloudToCylinder(cloud, coefficients_cylinder, cloud_projected);  // 点云投影visualizePointClouds(cloud, cloud_projected);  // 可视化结果return 0;
}

三、实现效果


http://www.mrgr.cn/news/40459.html

相关文章:

  • 基于NFSR和S盒的国产流密码算法Bagua
  • 快速了解:MySQL InnoDB和MyISAM的区别
  • MATLAB数字水印系统
  • 计算机网络自顶向下(2)----socket编程
  • 【YOLO系列】YOLOv11正式发布!
  • 足球青训俱乐部后台:Spring Boot开发策略
  • SOMEIP_ETS_144: SD_Reserved_Field_Endpoint_Option_set
  • stm32单片机学习 - MDK仿真调试
  • u盘格式化后数据能恢复吗?2024年Top4恢复神器来帮忙
  • 基于JAVA+SpringBoot+Vue的电商平台的设计与实现
  • 第十讲-显示控件QLabel
  • 论文笔记:LAFF 文本到视频检索的新基准
  • 滚雪球学MySQL[2.3讲]:MySQL数据过滤与排序详解:WHERE条件、ORDER BY排序与LIMIT分页查询
  • 「漏洞复现」EDU 某智慧平台 PersonalDayInOutSchoolData SQL注入漏洞
  • TypeScript 算法手册【选择排序】
  • 【Linux学习】基本指令其二
  • Leetcode45. 跳跃游戏 II
  • 关于计算机算法设计方法的思考
  • 监控易监测对象及指标之:Exchange邮件服务器监测
  • 死锁相关概念