如何求取叶片点云前后缘与叶盆叶背的分界点(c++)

时间: 2024-01-27 14:04:51 浏览: 29
求取叶片点云前后缘与叶盆叶背的分界点需要进行以下步骤: 1. 对点云进行预处理,包括去除离群点、降采样等操作。 2. 确定叶片的主轴方向,可以采用PCA等方法求解。 3. 将点云沿主轴方向进行投影,得到一维的点云分布。 4. 对点云分布进行平滑滤波,得到分布的拐点。 5. 将点云沿法向方向进行投影,得到叶片截面的点云。 6. 对叶片截面的点云进行聚类,得到叶片前后两侧点云。 7. 对前后两侧点云进行分别拟合,得到拟合曲线。 8. 拟合曲线的交点即为前后缘的分界点,拟合曲线与点云的交点即为叶盆叶背的分界点。 以下是C++代码的示例: ```c++ #include <iostream> #include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/filters/voxel_grid.h> #include <pcl/features/normal_3d.h> #include <pcl/filters/statistical_outlier_removal.h> #include <pcl/segmentation/sac_segmentation.h> #include <pcl/filters/extract_indices.h> #include <pcl/visualization/cloud_viewer.h> typedef pcl::PointXYZ PointT; typedef pcl::PointCloud<PointT> PointCloudT; int main(int argc, char** argv) { // Load point cloud PointCloudT::Ptr cloud(new PointCloudT); pcl::io::loadPCDFile<PointT>("leaf.pcd", *cloud); // Voxel grid filtering pcl::VoxelGrid<PointT> vg; vg.setInputCloud(cloud); vg.setLeafSize(0.01f, 0.01f, 0.01f); PointCloudT::Ptr cloud_filtered(new PointCloudT); vg.filter(*cloud_filtered); // Statistical outlier removal pcl::StatisticalOutlierRemoval<PointT> sor; sor.setInputCloud(cloud_filtered); sor.setMeanK(50); sor.setStddevMulThresh(1.0); PointCloudT::Ptr cloud_sor(new PointCloudT); sor.filter(*cloud_sor); // Estimate normals pcl::NormalEstimation<PointT, pcl::Normal> ne; ne.setInputCloud(cloud_sor); pcl::search::KdTree<PointT>::Ptr tree(new pcl::search::KdTree<PointT>()); ne.setSearchMethod(tree); pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); ne.setRadiusSearch(0.03); ne.compute(*normals); // Segment plane pcl::SACSegmentationFromNormals<PointT, pcl::Normal> seg; seg.setOptimizeCoefficients(true); seg.setModelType(pcl::SACMODEL_NORMAL_PLANE); seg.setNormalDistanceWeight(0.1); seg.setMethodType(pcl::SAC_RANSAC); seg.setMaxIterations(100); seg.setDistanceThreshold(0.02); seg.setInputCloud(cloud_sor); seg.setInputNormals(normals); pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients); pcl::PointIndices::Ptr inliers(new pcl::PointIndices); seg.segment(*inliers, *coefficients); // Extract inliers pcl::ExtractIndices<PointT> extract; extract.setInputCloud(cloud_sor); extract.setIndices(inliers); extract.setNegative(false); PointCloudT::Ptr cloud_plane(new PointCloudT); extract.filter(*cloud_plane); // Project to axis Eigen::Vector4f centroid; pcl::compute3DCentroid(*cloud_plane, centroid); Eigen::Matrix3f covariance_matrix; pcl::computeCovarianceMatrixNormalized(*cloud_plane, centroid, covariance_matrix); Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(covariance_matrix, Eigen::ComputeEigenvectors); Eigen::Matrix3f eigD = eigen_solver.eigenvalues().asDiagonal(); Eigen::Matrix3f eigV = eigen_solver.eigenvectors(); int idx = 0; if (eigD(1, 1) > eigD(0, 0)) idx = 1; if (eigD(2, 2) > eigD(idx, idx)) idx = 2; Eigen::Vector3f axis = eigV.col(idx); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected(new pcl::PointCloud<pcl::PointXYZ>); pcl::ProjectInliers<PointT> proj; proj.setModelType(pcl::SACMODEL_PLANE); proj.setInputCloud(cloud_plane); proj.setModelCoefficients(coefficients); proj.setInputCloud(cloud_plane); proj.filter(*cloud_projected); // Smooth filtering std::vector<float> data(cloud_projected->points.size()); for (int i = 0; i < cloud_projected->points.size(); i++) data[i] = cloud_projected->points[i].x; std::vector<float> kernel = { 1, 5, 8, 5, 1 }; std::vector<float> data_smooth(cloud_projected->points.size()); for (int i = 2; i < cloud_projected->points.size() - 2; i++) { for (int j = -2; j <= 2; j++) data_smooth[i] += data[i + j] * kernel[j + 2]; data_smooth[i] /= 20; } // Find inflection points std::vector<int> inflections; for (int i = 2; i < cloud_projected->points.size() - 2; i++) { if (data_smooth[i] > data_smooth[i - 1] && data_smooth[i] > data_smooth[i + 1]) inflections.push_back(i); if (data_smooth[i] < data_smooth[i - 1] && data_smooth[i] < data_smooth[i + 1]) inflections.push_back(i); } // Extract cross section pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_section(new pcl::PointCloud<pcl::PointXYZ>); pcl::ExtractIndices<PointT> extract_indices; extract_indices.setInputCloud(cloud); pcl::PointIndices::Ptr section_indices(new pcl::PointIndices); for (int i = 0; i < cloud_projected->points.size(); i++) { if (abs(cloud_projected->points[i].x - data_smooth[inflections[0]]) < 0.002) section_indices->indices.push_back(i); } extract_indices.setIndices(section_indices); extract_indices.setNegative(false); extract_indices.filter(*cloud_section); // Cluster front and back sides pcl::search::KdTree<pcl::PointXYZ>::Ptr tree_section(new pcl::search::KdTree<pcl::PointXYZ>); tree_section->setInputCloud(cloud_section); std::vector<pcl::PointIndices> cluster_indices; pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec; ec.setClusterTolerance(0.02); ec.setMinClusterSize(100); ec.setMaxClusterSize(10000); ec.setSearchMethod(tree_section); ec.setInputCloud(cloud_section); ec.extract(cluster_indices); // Fit curves pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_front(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_back(new pcl::PointCloud<pcl::PointXYZ>); for (int i = 0; i < cluster_indices.size(); i++) { pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>); pcl::PointIndices::Ptr cluster_indices_ptr(new pcl::PointIndices(cluster_indices[i])); extract_indices.setInputCloud(cloud_section); extract_indices.setIndices(cluster_indices_ptr); extract_indices.setNegative(false); extract_indices.filter(*cloud_cluster); 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_LINE); seg.setMethodType(pcl::SAC_RANSAC); seg.setMaxIterations(1000); seg.setDistanceThreshold(0.02); seg.setInputCloud(cloud_cluster); seg.segment(*inliers, *coefficients); if (coefficients->values[3] > 0) *cloud_front += *cloud_cluster; else *cloud_back += *cloud_cluster; } // Show results pcl::visualization::PCLVisualizer viewer("Leaf"); viewer.setBackgroundColor(0.0, 0.0, 0.0); viewer.addPointCloud(cloud, "cloud"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloud"); viewer.addPointCloud(cloud_projected, "projected"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 0.0, 0.0, "projected"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "projected"); viewer.addPointCloud(cloud_section, "section"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 1.0, 0.0, "section"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "section"); viewer.addPointCloud(cloud_front, "front"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 0.0, 1.0, "front"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "front"); viewer.addPointCloud(cloud_back, "back"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 1.0, 0.0, "back"); viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "back"); viewer.spin(); return 0; } ```

相关推荐

最新推荐

recommend-type

压气机叶片排序的数学模型

模型一:只考虑按重量约束,每个扇形区域的工件总重量与相邻区域的工件总重量之差不超过一定值,我们以相邻扇形区域工件总重量之差最小为目标函数建立规划模型,并用LINGO软件求出结果如下: 扇形区域 1 2 3 4 5 6 ...
recommend-type

Java 员工管理系统项目源代码(可做毕设项目参考)

Java 员工管理系统项目是一个基于 Java 编程语言开发的桌面应用程序,旨在管理员工的信息、津贴、扣除和薪资等功能。该系统通过提供结构和工具集,使公司能够有效地管理其员工数据和薪资流程。 系统特点 员工管理:管理员可以添加、查看和更新员工信息。 津贴管理:管理员可以添加和管理员工的津贴信息。 扣除管理:管理员可以添加和管理员工的扣除信息。 搜索功能:可以通过员工 ID 搜索员工详细信息。 更新薪资:管理员可以更新员工的薪资信息。 支付管理:处理员工的支付和生成支付记录。 模块介绍 员工管理模块:管理员可以添加、查看和更新员工信息,包括员工 ID、名字、姓氏、年龄、职位和薪资等。 津贴管理模块:管理员可以添加和管理员工的津贴信息,如医疗津贴、奖金和其他津贴。 扣除管理模块:管理员可以添加和管理员工的扣除信息,如税收和其他扣除。 搜索功能模块:可以通过员工 ID 搜索员工详细信息。 更新薪资模块:管理员可以更新员工的薪资信息。 支付管理模块:处理员工的支付和生成支付记录 可以作为毕业设计项目参考
recommend-type

CAD实验报告:制药车间动力控制系统图、烘烤车间电气控制图、JSJ型晶体管式时间继电器原理图、液位控制器电路图

CAD实验报告:制药车间动力控制系统图、烘烤车间电气控制图、JSJ型晶体管式时间继电器原理图、液位控制器电路图
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

优化MATLAB分段函数绘制:提升效率,绘制更快速

![优化MATLAB分段函数绘制:提升效率,绘制更快速](https://ucc.alicdn.com/pic/developer-ecology/666d2a4198c6409c9694db36397539c1.png?x-oss-process=image/resize,s_500,m_lfit) # 1. MATLAB分段函数绘制概述** 分段函数绘制是一种常用的技术,用于可视化不同区间内具有不同数学表达式的函数。在MATLAB中,分段函数可以通过使用if-else语句或switch-case语句来实现。 **绘制过程** MATLAB分段函数绘制的过程通常包括以下步骤: 1.
recommend-type

SDN如何实现简易防火墙

SDN可以通过控制器来实现简易防火墙。具体步骤如下: 1. 定义防火墙规则:在控制器上定义防火墙规则,例如禁止某些IP地址或端口访问,或者只允许来自特定IP地址或端口的流量通过。 2. 获取流量信息:SDN交换机会将流量信息发送给控制器。控制器可以根据防火墙规则对流量进行过滤。 3. 过滤流量:控制器根据防火墙规则对流量进行过滤,满足规则的流量可以通过,不满足规则的流量则被阻止。 4. 配置交换机:控制器根据防火墙规则配置交换机,只允许通过满足规则的流量,不满足规则的流量则被阻止。 需要注意的是,这种简易防火墙并不能完全保护网络安全,只能起到一定的防护作用,对于更严格的安全要求,需要
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。
recommend-type

"互动学习:行动中的多样性与论文攻读经历"

多样性她- 事实上SCI NCES你的时间表ECOLEDO C Tora SC和NCESPOUR l’Ingén学习互动,互动学习以行动为中心的强化学习学会互动,互动学习,以行动为中心的强化学习计算机科学博士论文于2021年9月28日在Villeneuve d'Asq公开支持马修·瑟林评审团主席法布里斯·勒菲弗尔阿维尼翁大学教授论文指导奥利维尔·皮耶昆谷歌研究教授:智囊团论文联合主任菲利普·普雷教授,大学。里尔/CRISTAL/因里亚报告员奥利维耶·西格德索邦大学报告员卢多维奇·德诺耶教授,Facebook /索邦大学审查员越南圣迈IMT Atlantic高级讲师邀请弗洛里安·斯特鲁布博士,Deepmind对于那些及时看到自己错误的人...3谢谢你首先,我要感谢我的两位博士生导师Olivier和Philippe。奥利维尔,"站在巨人的肩膀上"这句话对你来说完全有意义了。从科学上讲,你知道在这篇论文的(许多)错误中,你是我可以依
recommend-type

揭秘MATLAB分段函数绘制技巧:掌握绘制分段函数图的精髓

![揭秘MATLAB分段函数绘制技巧:掌握绘制分段函数图的精髓](https://img-blog.csdnimg.cn/direct/3821ea2a63d44e65925d8251196d5ca9.png) # 1. MATLAB分段函数的概念和基本语法** 分段函数是一种将函数域划分为多个子域,并在每个子域上定义不同函数表达式的函数。在MATLAB中,可以使用`piecewise`函数来定义分段函数。其语法为: ``` y = piecewise(x, x1, y1, ..., xn, yn) ``` 其中: * `x`:自变量。 * `x1`, `y1`, ..., `xn`,