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

PCL分割——法向量差分分割

Difference of Normals Based Segmentation

该算法基于一个点在不同大小邻域所得到的两个法向量的插值为依据对点进行分割。该方法计算效率高,并且对于大规模的无组织点云数据具有很好的效果。

算法流程

1️⃣ 使用较大的支持半径 (r_l),为点云中的每一个点估计法向量
2️⃣ 使用较小的支持半径 (r_s),再次为点云中的每一个点估计法向量
3️⃣ 对每一个点计算法向量的归一化差值
4️⃣ 对得到的向量场进行滤波,从而提取出属于目标尺度 / 感兴趣区域的点


  1. 算法要求要求必须使用半径搜索去计算点的法向量
  2. 滤波算法(可以使用条件滤波)需要基于我们得到的DON来进行选择,可以从以下数据中进行滤波条件的设定。
  3. 基于DON进行滤波后,还需要对滤波后的点云数据进行分割,才算完整整个流程。
过滤量(Quantity) PointNormal 字段 数值范围 含义说明 典型使用场景
DoN 向量 \(\Delta \hat{n}(p, r_s, r_l)\) normal[3] ([-1, 1]) 小尺度与大尺度法向量的差向量 DoN 方向 / 角度 过滤(方向敏感任务)
DoN 模长(L2 范数) (\(|\Delta \hat{n}|\)) curvature ((0, 1)) DoN 响应强度,衡量该点在给定尺度下的几何变化程度 尺度分割首选(与方向无关)
DoN x 分量 (\(\Delta \hat{n}_x\)) normal[0] ((-1, 1)) DoN 在 x 方向的分量 定向尺度过滤(如建筑立面)
DoN y 分量 (\(\Delta \hat{n}_y\)) normal[1] ((-1, 1)) DoN 在 y 方向的分量 定向尺度过滤
DoN z 分量 (\(\Delta \hat{n}_z\)) normal[2] ((-1, 1)) DoN 在 z 方向的分量 地面 / 屋顶 / 垂直结构区分
使用示例
int main()
{// Compute normals using both small and large scales at each pointpcl::NormalEstimationOMP<PointXYZRGB, PointNormal> ne;ne.setInputCloud (cloud);ne.setSearchMethod (tree);/*** NOTE: setting viewpoint is very important, so that we can ensure* normals are all pointed in the same direction!*/ne.setViewPoint (std::numeric_limits<float>::max (), std::numeric_limits<float>::max (), std::numeric_limits<float>::max ());// calculate normals with the small scalestd::cout << "Calculating normals for scale..." << scale1 << std::endl;pcl::PointCloud<PointNormal>::Ptr normals_small_scale (new pcl::PointCloud<PointNormal>);ne.setRadiusSearch (scale1);ne.compute (*normals_small_scale);// calculate normals with the large scalestd::cout << "Calculating normals for scale..." << scale2 << std::endl;pcl::PointCloud<PointNormal>::Ptr normals_large_scale (new pcl::PointCloud<PointNormal>);ne.setRadiusSearch (scale2);ne.compute (*normals_large_scale);// Create output cloud for DoN resultsPointCloud<PointNormal>::Ptr doncloud (new pcl::PointCloud<PointNormal>);copyPointCloud (*cloud, *doncloud);std::cout << "Calculating DoN... " << std::endl;// Create DoN operatorpcl::DifferenceOfNormalsEstimation<PointXYZRGB, PointNormal, PointNormal> don;don.setInputCloud (cloud);don.setNormalScaleLarge (normals_large_scale);don.setNormalScaleSmall (normals_small_scale);if (!don.initCompute ()){std::cerr << "Error: Could not initialize DoN feature operator" << std::endl;exit (EXIT_FAILURE);}// Compute DoNdon.computeFeature (*doncloud);// Save DoN featurespcl::PCDWriter writer;writer.write<pcl::PointNormal> ("don.pcd", *doncloud, false); // Filter by magnitudestd::cout << "Filtering out DoN mag <= " << threshold << "..." << std::endl;// Build the condition for filteringpcl::ConditionOr<PointNormal>::Ptr range_cond (new pcl::ConditionOr<PointNormal> ());range_cond->addComparison (pcl::FieldComparison<PointNormal>::ConstPtr (new pcl::FieldComparison<PointNormal> ("curvature", pcl::ComparisonOps::GT, threshold)));// Build the filterpcl::ConditionalRemoval<PointNormal> condrem;condrem.setCondition (range_cond);condrem.setInputCloud (doncloud);pcl::PointCloud<PointNormal>::Ptr doncloud_filtered (new pcl::PointCloud<PointNormal>);// Apply filtercondrem.filter (*doncloud_filtered);doncloud = doncloud_filtered;// Save filtered outputstd::cout << "Filtered Pointcloud: " << doncloud->size () << " data points." << std::endl;writer.write<pcl::PointNormal> ("don_filtered.pcd", *doncloud, false); // Filter by magnitudestd::cout << "Clustering using EuclideanClusterExtraction with tolerance <= " << segradius << "..." << std::endl;pcl::search::KdTree<PointNormal>::Ptr segtree (new pcl::search::KdTree<PointNormal>);segtree->setInputCloud (doncloud);std::vector<pcl::PointIndices> cluster_indices;pcl::EuclideanClusterExtraction<PointNormal> ec;ec.setClusterTolerance (segradius);ec.setMinClusterSize (50);ec.setMaxClusterSize (100000);ec.setSearchMethod (segtree);ec.setInputCloud (doncloud);ec.extract (cluster_indices);}

该算法在PCL没有直接封装,需要按照上面的流程进行处理。
PCL中的copyPointCloud是按照字段的名称实现拷贝,只会拷贝两个类型中的交集字段的数据。
此外,由于我们需要计算两组法向量并计算差分。因此在估计法向量是千万要记住设置视点的方向,让法向量朝向我们的视点方向。,保证前后两次计算的一致性。具体设置在哪里应该是随意的,但一定要选一个视点

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

相关文章:

  • LobeChat是否支持HTTP/2?网络协议性能优化实测
  • 收藏备用!企业级RAG落地全攻略:从避坑到选型的大模型实践手册
  • 北京市继承律师权威指南:2025-2026口碑评价与全场景解决方案推荐 - 老周说教育
  • Anaconda配置PyTorch环境的最佳实践:结合CUDA加速库
  • 2025年稳定性好、技术强、价格合理的激光平直度测量仪品牌推 - 工业推荐榜
  • 自动化测试平台Parasoft v2025.2更新:AI深度集成,支持嵌入式GPU
  • uos 使用nginx配置vue2站点
  • 2025年紫外线消毒器品牌排名:紫外线消毒器哪家品牌的易用性 - mypinpai
  • 提升用户体验:LobeChat中实现打字机效果的技巧
  • 如何找代码bug
  • TFA(双因素认证,Two-Factor Authentication)验证
  • 2025年最新资讯:定制环境监测系统推荐厂家及品牌(含功能、参数与系统组成详解) - 品牌推荐大师1
  • 49、技术领域综合知识解析
  • git下载速度慢?vLLM镜像内置CDN加速支持
  • 网站打不开、响应慢,可能是DNS解析出现了问题!
  • 西安口碑好的红木家具厂家推荐:陕西木灵生实力赢得市场 - 朴素的承诺
  • 应用层|低空应用安全的 “精工锻造者”,中科数测以多工具矩阵赋能应用从开发到运维的全周期安全
  • 26、Docker 应用场景实战:负载均衡、对象存储与数据库集群搭建
  • 基于单片机的智能家居燃气检测系统设计与技术实现
  • PLC连续可变S速度曲线算法仿真
  • AutoGPT能否接入网易邮箱?邮件协议调用示例
  • ComfyUI工作流中嵌入vLLM节点,动态批处理提速
  • 27、Docker 应用场景:Galera 集群负载均衡与 Spark 集群搭建
  • AutoGPT如何避免生成违法内容?合规过滤层说明
  • 固态断路器技术现状、应用场景与核心挑战
  • 17、Docker不同操作系统及工具使用指南
  • 打造专属AI助手:LobeChat角色预设配置完全手册
  • CAGRA:面向GPU优化的高精度图索引技术核心解析
  • 横观水力压裂模型:从 PDE 建模到 Comsol 模拟
  • AutoGPT能否自动生成UML图?系统设计辅助尝试