PCL中GreedyProjection三角化算法简介与示例


文章目录

  • 前言
  • 一、PCL点云三角化
    • 1.1 Delaunay三角剖分
    • 1.2 贪婪三角化
  • 二、程序示例
  • 总结


前言

Delaunay三角剖分最初应用于2维领域,而与Greedy三角化算法的结合,使之成为目前在三维重建领域最为基础的算法原理之一,很多学者针对其原理进行改进用以三维点云模型的构建。


一、PCL点云三角化

1.1 Delaunay三角剖分

定义:假设点集中的一条边e(两个端点为a,b),e若满足下列条件,则称之为Delaunay边:存在一个圆经过a,b两点,圆内(圆上最多三点共圆)不含点集中任何其他的点。而Delaunay三角化就是指三角网格均是由Delaunay边组成,并满足最小角最大原则(在点集可能形成的三角剖分中,Delaunay三角剖分所形成的三角形的最小角最大)。

针对以上定义,目前已提出了很多经典的剖分算法,如Lawson算法、Bowyer-Watson算法。以上算法都很有意思,通过点插法实现,具体原理可以查看以下链接。
技术分享:Delaunay三角剖分算法介绍
在这里插入图片描述

1.2 贪婪三角化

PCL中采用将三维点云投影到二维平面的方法来实现三角剖分, 具体采用贪婪三角化算法。
其过程为:
1:计算点云中点的法线,再将点云通过法线投影到二维坐标平面。
2:使用基于Delaunay三角剖分的空间区域增长算法完成平面点集的三角化。
3:根据投影点云的连接关系确定原始三维点云间的拓扑关系,最终得到曲面模型。

PCL中的NormalEstimation和GreedyProjectionTriangulation类实现该计算过程。
源代码:

FFN和SFN是指两个不同方向的边缘邻域集,在connectPoint方法里完成计算。

/** \brief Index of the current query point **/
int R_;std::vector<int> ffn_;
std::vector<int> sfn_;
// Locating FFN and SFN to adapt distance thresholddouble sqr_source_dist = (coords_[R_] - coords_[source_[R_]]).squaredNorm ();double sqr_ffn_dist = (coords_[R_] - coords_[ffn_[R_]]).squaredNorm ();double sqr_sfn_dist = (coords_[R_] - coords_[sfn_[R_]]).squaredNorm ();double max_sqr_fn_dist = (std::max)(sqr_ffn_dist, sqr_sfn_dist);double sqr_dist_threshold = (std::min)(sqr_max_edge, sqr_mu * sqrDists[1]); //sqr_mu * sqr_avg_conn_dist);if (max_sqr_fn_dist > sqrDists[nnn_-1]){if (0 == increase_nnn4fn)PCL_WARN("Not enough neighbors are considered: ffn or sfn out of range! Consider increasing nnn_... Setting R=%d to be BOUNDARY!\n", R_);increase_nnn4fn++;state_[R_] = BOUNDARY;continue;}double max_sqr_fns_dist = (std::max)(sqr_source_dist, max_sqr_fn_dist);if (max_sqr_fns_dist > sqrDists[nnn_-1]){if (0 == increase_nnn4s)PCL_WARN("Not enough neighbors are considered: source of R=%d is out of range! Consider increasing nnn_...\n", R_);increase_nnn4s++;}

计算法线:

// Get the normal estimate at the current point 
const Eigen::Vector3f nc = (*input_)[(*indices_)[R_]].getNormalVector3fMap ();

三角化:

// Triangulatingif (angles_[2].visible == false){if ( !( (angles_[0].index == ffn_[R_] && angles_[1].index == sfn_[R_]) || (angles_[0].index == sfn_[R_] && angles_[1].index == ffn_[R_]) ) ){state_[R_] = BOUNDARY;}else{if ((source_[R_] == angles_[0].index) || (source_[R_] == angles_[1].index))state_[R_] = BOUNDARY;else{if (sqr_max_edge < (coords_[ffn_[R_]] - coords_[sfn_[R_]]).squaredNorm ()){state_[R_] = BOUNDARY;}else{tmp_ = coords_[source_[R_]] - proj_qp_;uvn_s[0] = tmp_.dot(u_);uvn_s[1] = tmp_.dot(v_);double angleS = std::atan2(uvn_s[1], uvn_s[0]);double dif = angles_[1].angle - angles_[0].angle;if ((angles_[0].angle < angleS) && (angleS < angles_[1].angle)){if (dif < 2*M_PI - maximum_angle_)state_[R_] = BOUNDARY;elsecloseTriangle (polygons);}else{if (dif >= maximum_angle_)state_[R_] = BOUNDARY;elsecloseTriangle (polygons);}}}}continue;}

源码中大量代码关注于三角形的连接问题。
最后调用MeshConstruction类的reconstruct方法进行表面重建。

template <typename PointInT> void
MeshConstruction<PointInT>::reconstruct (std::vector<pcl::Vertices> &polygons)
{if (!initCompute ()){polygons.clear ();return;}// Check if a space search locator was givenif (check_tree_){if (!tree_){if (input_->isOrganized ())tree_.reset (new pcl::search::OrganizedNeighbor<PointInT> ());elsetree_.reset (new pcl::search::KdTree<PointInT> (false));}// Send the surface dataset to the spatial locatortree_->setInputCloud (input_, indices_);}// Set up the output dataset//polygons.clear ();//polygons.reserve (2 * indices_->size ()); /// NOTE: usually the number of triangles is around twice the number of vertices// Perform the actual surface reconstructionperformReconstruction (polygons);deinitCompute ();
}

二、程序示例

//----------------------------------法线计算-----------------------------------pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);pcl::search::KdTree<pcl::PointXYZ>::Ptr tree1(new pcl::search::KdTree<pcl::PointXYZ>);tree->setInputCloud(cloud);n.setInputCloud(cloud);n.setSearchMethod(tree1);n.setKSearch(20);n.compute(*normals);pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);//连接点云和法线pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);tree2->setInputCloud(cloud_with_normals);pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp;pcl::PolygonMesh triangles;gp.setSearchRadius(0.025);//设置搜索半径,即连接点的最大距离gp.setMu(2.5); //加权因子,对于每个样本点,其映射所选球的半径由mu与离样本点最近点的距离乘积决定,用以解决点云密度不均匀的问题,mu一般取值2.5-3gp.setMaximumNearestNeighbors(600); //最大领域点个数gp.setMaximumSurfaceAngle(M_PI / 4);//临近点的法线和样本点法线的最大偏离角度gp.setMinimumAngle(M_PI / 18); //三角形最小角gp.setMaximumAngle(2 * M_PI / 3);//三角形最大角gp.setNormalConsistency(false); //保证法线朝向一致gp.setInputCloud(cloud_with_normals);gp.setSearchMethod(tree2);   gp.reconstruct(triangles);

在这里插入图片描述

总结

彻底理解三角化的源代码比较困难,缺少相关学习资料,欢迎共同研究,提出意见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/256058.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【pyqt5】 读取numpy arrray 显示图片

目录 1、GUI界面&#xff08;QT designer设计&#xff09; 2、逻辑函数&#xff08;回调等&#xff09; 3、显示图片在label上 0&#xff09;直接利用QPixmap显示图像 1&#xff09;显示彩色图 彩色图显示色调不正常——opencv&#xff08;BGR&#xff09;QT(RGB)需要进行…

【pyqt5】——入门级模板(ui文件+ui转py文件+逻辑py文件)(消息提示框)

目录 1、ui文件 2、ui转py文件 3、逻辑py文件 4、实例 1&#xff09;ui文件——demo.ui 2&#xff09;ui转py文件——demo.py 3)逻辑py文件——demoLogic.py 4)运行结果 1、ui文件 这个文件是直接通过pyqt5 designer进行设计的&#xff0c;相关配置可见《配置Qt Design…

PCL中点特征描述子PFH、FPFH和VFH简述和示例

文章目录前言一、点特征直方图1.1 PFH1.1.1 法线估计1.1.2 特征计算1.2 FPFH1.3 VFH二、示例2.1 PFH计算2.2 FPFH2.3 VFH前言 点特征直方图是PCL中非常重要的特征描述子&#xff0c;在点云匹配、分割、重建等任务中起到关键作用&#xff0c;可以对刚体变换、点云密度和噪声均有…

来一个炫酷的导航条

本文分享一个带动画效果的中英文切换导航条。 鼠标放上去试一下&#xff1a; INDEX 首页 BBS 社区 HOME 我 1.用CSS3实现 效果看上去复杂&#xff0c;其实我们先来做出一个样式&#xff0c;就很简单了。如下&#xff1a; 代码&#xff1a; <nav><ul class"list…

EXCEL小技巧:如何统计非空单元格

http://club.excelhome.net/thread-1187271-1-1.html 下面教大家如果用函数统计非空单元格的数量 首先我们来介绍几个统计函数&#xff1a; 1.COUNT(value1,value2,...) 统计包含数字的单元格个数 2.COUNTA(value1,value2,...) 统计非空单元格的个数 3.COUNTBLANK(range&…

未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序。

报错信息&#xff1a; 解决方案&#xff1a; 1、“设置应用程序池默认属性”/“常规”/”启用32位应用程序”&#xff0c;设置为 true。 如下图所示&#xff1a;&#xff08;已测试&#xff0c;好使&#xff09; 方法二&#xff1a;生成->配置管理器->平台->点击Any C…

008. 限制上传文件的大小

第一种方法: 利用web.config的配置文件项, 进行设置; 前端aspx示例: <% Page Language"C#" AutoEventWireup"true" CodeFile"sendOutEmail.aspx.cs" Inherits"sendOutEmail" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHT…

浙江中医药大学第十一届程序设计竞赛题解

官方题解&#xff1a;http://www.jnxxhzz.com/Article/article/9.html 2019: 特产 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 548 Solved: 154[Submit][Status][Web Board]Description Input Output 输出一个整数表示dd带回来的特产重量 Sample Input 2 3 6 1 3Sample …

【项目实战】——USB双路继电器电脑控制灯的开关(Python)

环境&#xff1a;window10、Python3.7.9 依赖库&#xff1a;pyserial 硬件&#xff1a;220V灯带、220V吊灯、USB双路继电器、电笔 1、安装Python第三方库pyserial 2、清楚插座的零火线&#xff08;用电笔去测试&#xff0c;灯亮为火线&#xff09; 3、清楚灯的零火线&#…

字符串去掉空格

2019独角兽企业重金招聘Python工程师标准>>> String s1s.trim().replaceAll("\\s*", ""); 转载于:https://my.oschina.net/u/2842177/blog/1587850

基于CMake构建MSVC_CUDA及MinGW编译环境下的的OpenCV项目

前言 第一次搭建OpenCV开发环境的时候各种报错&#xff0c;内心那个烦啊&#xff0c;简直了。当时只能针对某个特定的错误去寻找特定的解决方法&#xff0c;在OpenCV构建过程中出现最多的问题就是各个模块文件的下载问题&#xff0c;本质上这类问题的解决思路都是一样的&#…

【opencv】——钢管计数(霍夫圆变换 + 阈值 + canny)

目录 方法一:霍夫圆变换 + canny 方法二 阈值 + 寻边 对图中的钢管进行计数 方法一:霍夫圆变换 + canny

DNS域传送漏洞

0x00 相关背景介绍 Dns是整个互联网公司业务的基础&#xff0c;目前越来越多的互联网公司开始自己搭建DNS服务器做解析服务&#xff0c;同时由于DNS服务是基础性服务非常重要&#xff0c;因此很多公司会对DNS服务器进行主备配置而DNS主备之间的数据同步就会用到dns域传送&#…

封装之--通过类中公有方法访问私有成员变量

如何在ClassB中访问ClassA的私有成员变量&#xff1f;&#xff08;典型的封装案例&#xff09; 通过在ClassA中定义公有的成员方法&#xff0c;然后&#xff0c;在ClassB中通过ClassA的对象调用ClassA中的公有方法&#xff0c;来访问ClassA中的私有成员变量。 转载于:https://w…

匹配物镜放大倍数与相机像元尺寸

通常来说&#xff0c;相机内部的CCD或者CMOS传感器上都有感光阵列&#xff0c;由一个一个的感光元件构成&#xff0c;每一个感光元件负责完成光电转换的过程。简单理解&#xff0c;一个感光元件可以认为就是一个像素(pixel)或像元(pel)。像元具有一定尺寸&#xff0c;如果像的尺…

【深度学习】——非极大值抑制(nms/soft-nms)

目录 一、相关概念 1、iou 1&#xff09;理论计算 2&#xff09;Python代码&#xff08;代码参考yolov3模型util.py文件&#xff09; 2、nms 1)基本思路 2&#xff09;标准nms和soft-nms 3&#xff09;Python代码实现&#xff08;yolov3中util.py文件&#xff0c;增加了…

移动服务安全现状分析!

2019独角兽企业重金招聘Python工程师标准>>> 由于Android开源的环境&#xff0c;导致Android的整体环境都存在很多不安全的因素&#xff0c;同时用户在移动APP客户端的便捷应用&#xff0c;也给用户带来了巨大的安全隐患。未经过移动服务安全加固的APP存在被静态反编…

MyEclipse连接MySQL

在官网http://www.mysql.com/downloads/下载数据库连接驱动 本文中使用驱动版本为mysql-connector-java-5.1.40 一、创建一个java测试项目MySQLConnectorsTest 在项目下穿件一个lib文件夹用来存放MySQL驱动包。 右键驱动包build path进行add添加操作&#xff0c;打开Referenced…

在Windows系统中配置Google AddressSanitizer

Google AddressSanitizer简介 AddressSanitizer (ASan) 是 C 和 C 的内存错误检测软件&#xff0c;它可以检测&#xff1a; 释放指针后继续使用堆缓冲区溢出栈缓冲区溢出全局缓冲区溢出返回后继续使用在范围之外继续使用初始化顺序的bug内存泄漏 在 Windows 系统中&#xff…

【剑指offer】——求出一个正整数的质数因子(Python)

目录 一、题目描述 二、思路 1、短除法 2、平方根法 一、题目描述 功能:输入一个正整数&#xff0c;按照从小到大的顺序输出它的所有质因子&#xff08;重复的也要列举&#xff09;&#xff08;如180的质因子为2 2 3 3 5 &#xff09; 最后一个数后面也要有空格 输入描述…