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

CGAL 点云上采样

目录

  • 一、算法原理
    • 1、主要函数
    • 2、参数解析
  • 二、代码实现
  • 三、结果展示

一、算法原理

  该方法对点集进行逐步上采样,同时根据法向量信息来检测边缘点,需要输入点云具有法线信息。在点云空洞填充和稀疏表面重建中具有较好的应用。

1、主要函数

头文件

#include <CGAL/edge_aware_upsample_point_set.h> // 上采样

函数

OutputIterator CGAL::edge_aware_upsample_point_set  ( const PointRange &  points,  
  OutputIterator  output,  
  const NamedParameters &  np = parameters::default_values()  
 ) 

  这种方法逐步向上采样点集,同时接近边缘奇点(通过法线变化检测),这从输入点集产生一个更密集的点集。这在基于点的渲染、孔填充和稀疏表面重建中有应用。点的法线需要作为输入。

  • sharpness_angle(s_angle):控制输出结果的平滑度,值越大越平滑,取值范围[0,90]。
  • edge_sensitivity(edge_s): 边缘的敏感性取值范围[0,1],边缘敏感度越大,在尖锐边缘处插入点的有限度越高
  • neighbor_radius(n_radius) :邻域点的个数,如果提供,查询点的邻域是用一个固定的球面计算的半径,而不是固定数量的邻居。在这种情况下,参数k用于限制每个球邻域返回点的数量(避免高密度区域的点过多)
  • number_of_output_points(n_out)) 上采样后的点数

2、参数解析

edge_sensitivity
   此参数控制新点插入的位置。边缘敏感值越大,沿尖锐特征插入点的优先级越高。如下图所示,想要在尖锐的特征上插入更多的点时,高值是可取的,这些地方的局部梯度很高,如尖点、折痕和角等。相反,当edge_sensitivity设置为0时,点是均匀插入的。取值范围为[0,1]。
在这里插入图片描述
sharpness_angle
   这个参数控制尖锐特征的平滑程度。
在这里插入图片描述
neighbor_radius
   通常,采样点的邻域至少应该包括一个相邻采样点环。使用小的邻域可能无法插入新的点。使用大的邻域可以填补小的洞,但插入边缘的点可能是不规则的。如果该参数值设置为默认值或小于零,函数将使用邻域点的密度进行估计。
在这里插入图片描述

二、代码实现

#include <vector>
#include <fstream>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/IO/read_points.h>
#include <CGAL/IO/write_points.h>
#include <CGAL/edge_aware_upsample_point_set.h> // 上采样
// types
typedef CGAL::Simple_cartesian<double> Kernel;
// 用于存储点坐标和法向量的pair容器
typedef std::pair<Kernel::Point_3, Kernel::Vector_3> PointVectorPair;

int main(int argc, char* argv[])
{
	const std::string input_filename = CGAL::data_file_path("cgal//before_upsample.xyz");
	const char* output_filename("cgal//after_upsample.xyz");

	// -----------------------读取包含点坐标和法向量的.xyz点云-------------------
	std::vector<PointVectorPair> points;
	if (!CGAL::IO::read_points(input_filename,std::back_inserter(points),
		CGAL::parameters::point_map(CGAL::First_of_pair_property_map<PointVectorPair>())
		.normal_map(CGAL::Second_of_pair_property_map<PointVectorPair>())))
	{
		std::cerr << "Error: cannot read file " << input_filename << std::endl;
		return -1;
	}

	// ---------------------------------参数设置---------------------------------
	const double s_angle = 25;                   // 平滑度,值越大越平滑,取值范围[0,90]
	const double edge_s = 0;                     // 边缘的敏感性取值范围[0,1]
	const double n_radius = 0.25;                // 邻域点搜索半径
	const std::size_t n_out = points.size() * 10; // 上采样后的点数
	// ----------------------------------上采样----------------------------------
	CGAL::edge_aware_upsample_point_set<CGAL::Parallel_if_available_tag>(points,std::back_inserter(points),
		CGAL::parameters::point_map(CGAL::First_of_pair_property_map<PointVectorPair>()).
		normal_map(CGAL::Second_of_pair_property_map<PointVectorPair>()).
		sharpness_angle(s_angle).        // 控制输出结果的平滑度,值越大越平滑,取值范围[0,90]。
		edge_sensitivity(edge_s).        // 边缘的敏感性取值范围[0,1],边缘敏感度越大,在尖锐边缘处插入点的有限度越高
		neighbor_radius(n_radius).       // 邻域点的个数,如果提供,查询点的邻域是用一个固定的球面计算的半径
		                                 // 而不是固定数量的邻居。在这种情况下,参数k用于限制每个球邻域返回点的数量(避免高密度区域的点过多)
		number_of_output_points(n_out)); // 上采样后的点数
	std::cout << "上采样完毕!!!" << std::endl;
	// ----------------------------------保存结果--------------------------------
	if (!CGAL::IO::write_points(output_filename, points,
		CGAL::parameters::point_map(CGAL::First_of_pair_property_map<PointVectorPair>())
		.normal_map(CGAL::Second_of_pair_property_map<PointVectorPair>())
		.stream_precision(6)))
	{
		std::cerr << "保存失败!!!" << std::endl;
		return -1;
	}	

	return 0;
}

三、结果展示

1、原始点云
在这里插入图片描述
2、上采样
在这里插入图片描述


http://www.kler.cn/a/1044.html

相关文章:

  • Spring——依赖注入之p命名空间和c命名空间
  • Kali系统(Debian 10.3) 遇到的问题
  • git提交
  • 【Notepad++】Notepad++如何删除包含某个字符串所在的行
  • 关于我拒绝了腾讯测试开发岗offer这件事
  • 【Java】你真的懂封装吗?一文读懂封装-----建议收藏
  • [网络原理] 网络中的基本概念
  • 数据结构与算法——栈和队列<也不过如此>
  • 考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联合配置方法(Matlab代码实现)
  • 为什么需要在差分或者重要信号换层时在它们旁边加上地孔呢?
  • 什么是计数排序?
  • IP地址的分类
  • ASEMI代理瑞萨TW8825-LA1-CR汽车芯片
  • C++ 98/03 应该学习哪些知识4
  • 2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛(同步赛)(H题)(线段树)
  • 国产航顺HK32F030M:定时器计数/PWM输出/输出翻转/输入捕获
  • 【操作系统复习】ch3 内存基础
  • 为什么VMware会给我多创建了两个网络呢?Windows和Linux为什么可以彼此ping的通呢
  • 【文心一言】什么是文心一言,如何获得内测和使用方法。
  • 基于python的奥运会历史数据分析【120年】
  • 「Python 基础」异步 I/O 编程
  • 数据分析之Matplotilb数据可视化
  • Integer和int的比较大小
  • HelloWorld