CGAL 点云双边滤波

一、算法原理

  基于点云法线的双边滤波,实现对点云的平滑处理。

1、主要函数

头文件

#include <CGAL/bilateral_smooth_point_set.h>

函数

double CGAL::bilateral_smooth_point_set  ( PointRange &  points,  
  unsigned int  k,  
  const NamedParameters &  np = parameters::default_values()  
 ) 

  该函数通过迭代地将每个点投影到最近邻拟合的隐式曲面上,来平滑输入点集。双侧投影根据法线(梯度)信息保留尖锐特征。点位和法线都会被修改。函数返回值为平均点移动误差。这是算法的收敛准则。这个值可以帮助用户决定多少次迭代是足够的。

  • points:包含法向量信息的点云
  • k: 隐式曲面拟合的邻域点数。值越大,结果越平滑。
  • np:下面列出的命名参数中的一个可选序列。

在这里插入图片描述

2、参考文献

H. Huang, S. Wu, M. Gong, D. Cohen-Or, U. Ascher, and H. Zhang. Edge-aware point set resampling. ACM Transactions on Graphics, 32:9:1–9:12, 2013.

二、代码实现

#include <utility> // std::pair
#include <fstream>
#include <CGAL/tags.h>
#include <CGAL/property_map.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/IO/read_points.h>             // 读取点云
#include <CGAL/IO/write_points.h>            // 保存点云
#include <CGAL/bilateral_smooth_point_set.h> // 双边滤波

// Types
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
// 定义一个pair容器用来存储点坐标和法向量
typedef std::pair<Point, Vector> PointVectorPair;

int main(int argc, char* argv[])
{
    
    
	// 设置文件读取路径和保存路径
	const std::string input_filename = CGAL::data_file_path("cgal//fin90_with_PCA_normals.xyz");
	const char* output_filename = "cgal//fin90_with_PCA_normals_bilateral_smoothed.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 << "点云读取失败" << input_filename << std::endl;
		return -1;
	}
	// -----------------------------------参数设置----------------------------------------
	int k = 120;                 // 邻域点的个数,点数越多越平滑
	double sharpness_angle = 25; // 控制结果的平滑度,值越大越平滑
	int iter_number = 3;         // 应用投影的次数
	// ------------------------------基于法线的双边滤波----------------------------------
	for (int i = 0; i < iter_number; ++i)
	{
    
    
		CGAL::bilateral_smooth_point_set <CGAL::Parallel_if_available_tag>(
			points,
			k,
			CGAL::parameters::point_map(CGAL::First_of_pair_property_map<PointVectorPair>())
			.normal_map(CGAL::Second_of_pair_property_map<PointVectorPair>())
			.sharpness_angle(sharpness_angle));
	}
	// ------------------------------------结果保存--------------------------------------
	if (!CGAL::IO::write_XYZ(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(17)))
		return -1;

	return 0;

}

三、结果展示

白色为原始点云,红色为平滑之后的点云。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_36686437/article/details/127466623