目录
- 一、算法原理
- 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、上采样