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

PCL 垂距法实现点云精简

目录

  • 一、垂距法
  • 二、代码实现
  • 三、结果展示

一、垂距法

垂距法是道格拉斯普客算法的一种非递归、单遍扫描变体。它维护一个“当前有效基线”(从上一个保留点指向当前候选点),逐个检查中间点到该基线的垂距,若超过阈值则保留该中间点并更新基线起点。

二、代码实现

#include<iostream>#include<vector>#include<cmath>#include<pcl/io/pcd_io.h>#include<pcl/point_types.h>#include<pcl/visualization/pcl_visualizer.h>doubleperpendicularDistance(constpcl::PointXYZ&A,constpcl::PointXYZ&B,constpcl::PointXYZ&P){doubledx=B.x-A.x,dy=B.y-A.y,dz=B.z-A.z;doublelen=std::sqrt(dx*dx+dy*dy+dz*dz);if(len<1e-12)return0.0;doublecross_x=dy*(P.z-A.z)-dz*(P.y-A.y);doublecross_y=dz*(P.x-A.x)-dx*(P.z-A.z);doublecross_z=dx*(P.y-A.y)-dy*(P.x-A.x);returnstd::sqrt(cross_x*cross_x+cross_y*cross_y+cross_z*cross_z)/len;}pcl::PointCloud<pcl::PointXYZ>perpendicularSimplify(constpcl::PointCloud<pcl::PointXYZ>&cloud,doubledistance_threshold){if(cloud.empty())returnpcl::PointCloud<pcl::PointXYZ>();std::vector<pcl::PointXYZ>pts(cloud.begin(),cloud.end());intn=pts.size();std::vector<bool>kept(n,false);kept[0]=kept[n-1]=true;intanchor=0;// 当前基线的起点索引intfloater=2;// 当前基线的终点索引(候选点)while(floater<n){// 检查 anchor 到 floater 之间所有点boolfoundExceed=false;for(inti=anchor+1;i<floater;++i){doubled=perpendicularDistance(pts[anchor],pts[floater],pts[i]);if(d>distance_threshold){// 保留前一个点(floater-1)作为新锚点kept[floater-1]=true;anchor=floater-1;floater=anchor+2;foundExceed=true;break;}}if(!foundExceed){// 所有中间点都在阈值内,继续向前移动floaterfloater++;}}pcl::PointCloud<pcl::PointXYZ>out;out.reserve(std::count(kept.begin(),kept.end(),true));for(inti=0;i<n;++i){if(kept[i])out.push_back(pts[i]);}returnout;}intmain(){pcl::PointCloud<pcl::PointXYZ>::Ptrcloud(newpcl::PointCloud<pcl::PointXYZ>);if(pcl::io::loadPCDFile<pcl::PointXYZ>("sorted_cloud.pcd",*cloud)==-1){std::cerr<<"错误:无法读取点云文件!"<<std::endl;return-1;}std::cout<<"原始点数: "<<cloud->size()<<std::endl;doubledist_thresh=0.03;// 垂距阈值(米)pcl::PointCloud<pcl::PointXYZ>simplified=perpendicularSimplify(*cloud,dist_thresh);std::cout<<"简化后点数: "<<simplified.size()<<std::endl;std::cout<<"简化比例: "<<(double)simplified.size()/cloud->size()*100<<"%"<<std::endl;pcl::io::savePCDFileBinary("simplified_perp.pcd",simplified);std::cout<<"结果已保存至 simplified_perp.pcd"<<std::endl;// 可视化pcl::visualization::PCLVisualizerviewer(u8"垂距法简化");viewer.addPointCloud<pcl::PointXYZ>(cloud,"original");viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,1.0,0.0,0.0,"original");viewer.addPointCloud<pcl::PointXYZ>(simplified.makeShared(),"simplified");viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,0.0,1.0,0.0,"simplified");viewer.spin();return0;}

参数调优threshold_(弦高阈值)是核心参数。阈值越大,简化程度越高,丢失的细节越多;阈值越小,保留的点越多,计算量越大。建议根据点云的平均点间距(mean_distance)来设定,通常为0.1 ~ 0.5倍的平均间距。

三、结果展示

http://www.jsqmd.com/news/1098769/

相关文章:

  • 深入解析Hermes Agent:从Skill驱动架构到实战部署的AI Agent框架指南
  • 东莞翻译机构 韩语审计报告重点
  • Kimi LeetCode 3425. 最长特殊路径 Java实现
  • 从入门到精通:Python OpenPyXL完整教程
  • 3个突破性技巧:如何用SRWE实现Windows窗口的实时魔法编辑
  • 6个月小白逆袭AI初级工程师:收藏这份保姆级学习路线,从零基础到实战大模型!
  • 嵌入式音频开发实战:AU-60 全功能 DSP 语音模组一站式开发指南
  • 揭秘AI写教材黑科技!低查重的AI教材生成,为教学助力
  • MCP 协议传输层进化:从 stdio 到 Streamable HTTP,我的踩坑实录
  • 5分钟免费解锁英雄联盟所有皮肤:R3nzSkin国服特供版完整指南
  • How To: Create A Word Document In Powershell – Part 1 – Opening The Document, Writing Some Text, Usi
  • Kimi LeetCode 3425. 最长特殊路径 Python3实现
  • 低查重AI写教材攻略:精选5款AI工具,轻松搞定教材写作难题!
  • GNSS数据处理新手必看:手把手教你读懂RINEX 3.04钟差文件(CLK)里的关键信息
  • django文件对象是什么?
  • Highcharts有版权吗?
  • 对称加密算法的混淆层(S盒)密码学指标详细介绍
  • TVA在具身智能全栈能力体系中的关键作用(6)
  • 限峰功率最大熵定理的理论推导和MATLAB仿真实现(P124302075刘家隆)
  • php里直接塞CSS代码?别傻了,这招让加载快如闪电
  • VMware虚拟机安装Ubuntu Linux:从零搭建开发环境的完整指南
  • TVA:连接数字与物理世界的智能底座(3)
  • 北方高寒矿区专网通信搭建要点,适配低温、粉尘、防爆严苛工况
  • 基于YOLOv8的船舶检测分类系统:从模型训练到部署的完整实践
  • 第十六篇:商业模式重塑——告别数据垄断,拥抱能力订阅
  • YOLOv9的RepNCSPELAN4模块拆解:从代码到结构图,手把手理解这个新‘C3’
  • 新能源车逆市涨价,燃油车持续降价,车市怎么突然分化了?
  • 30N06-ASEMI通用 60V 中低压 Trench MOS管
  • Dify零基础七日实战:从部署到API发布,手把手掌握LLM应用开发
  • 如何用Taskt实现零代码办公自动化:免费RPA工具完整指南