CGAL 点云离群点剔除

本文介绍了如何使用CGAL库进行3D点云去噪,主要关注CGAL::remove_outliers函数,该函数通过计算平均间距并设置阈值或百分比来去除离群点。示例代码展示了如何加载点云数据,设定邻域点个数和阈值参数,然后应用去噪算法。最后,将处理后的点云保存到文件中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、主要函数

头文件

#include <CGAL/remove_outliers.h>

函数

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

  计算到最近邻居的平均平方距离,并使用平均距离的阈值或选择具有最高平均距离的点的固定百分比来划分点。该方法修改输入点的顺序,以便首先打包所有剩余的点,并在第一个点上返回要删除的迭代器。由于这个原因,它不应该在已排序的容器上调用。
  可以使用两个阈值:threshold_percentthreshold_distance。这个函数返回最小数量的异常值,以便至少满足这些阈值中的一个。这意味着如果threshold_percent=100,则只考虑threshold_distance;如果threshold_distance=0,则只考虑threshold_percent

二、代码实现

#include <vector>
#include <iostream>
#include <CGAL/property_map.h>
#include <CGAL/compute_average_spacing.h>
#include <CGAL/IO/read_points.h>
#include <CGAL/IO/write_points.h>
#include <CGAL/remove_outliers.h> // 点云去噪

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;

int main(int argc, char* argv[])
{
	const std::string fname = CGAL::data_file_path("cgal//oni.pwn");
	// ------------------------------加载点云----------------------------------
	std::vector<Kernel::Point_3> points;
	if (!CGAL::IO::read_points(fname, std::back_inserter(points),
		CGAL::parameters::point_map(CGAL::Identity_property_map<Kernel::Point_3>())))
	{
		std::cerr << "点云读取失败" << fname << std::endl;
		return -1;
	}

	// Removes outliers using erase-remove idiom.
	// The Identity_property_map property map can be omitted here as it is the default value.
	const int nb_neighbors = 24; // 邻域点个数
	// 计算平均密度
	const double average_spacing = CGAL::compute_average_spacing<CGAL::Sequential_tag>(points, nb_neighbors);
	std::vector<Kernel::Point_3>outLier;
	bool outPercent = true; // 离群点百分比是否已知

	if (outPercent == false)
	{
		// -------------------------离群点所占百分比未知---------------------------
		std::vector<Kernel::Point_3>::iterator first_to_remove = CGAL::remove_outliers<CGAL::Parallel_if_available_tag>
			(points, nb_neighbors,
				CGAL::parameters::threshold_percent(100.). // 百分比为100,则只考虑距离
				threshold_distance(2. * average_spacing)); // 距离设置为平均密度的2倍

		std::cerr << (100. * std::distance(first_to_remove, points.end()) / static_cast<double>(points.size()))
			<< "% of the points are considered outliers when using a distance threshold of "
			<< 2. * average_spacing << std::endl;
		outLier.swap(points);
	}
	else
	{
		// --------------------------知道离群点所占百分比----------------------------
		const double removed_percentage = 5.0; // 百分之五的离群点需要移除

		points.erase(CGAL::remove_outliers<CGAL::Parallel_if_available_tag>
			(points,
				nb_neighbors,
				CGAL::parameters::threshold_percent(removed_percentage). // 按最小百分比剔除异常值
				threshold_distance(0.)), // 距离阈值设置为0
			points.end());
		// Optional: after erase(), use Scott Meyer's "swap trick" to trim excess capacity
		outLier.swap(points);
	}
	
	// -------------------------------------保存结果----------------------------------
	if (!CGAL::IO::write_points("cgal//oni_outlier.xyz", outLier,
		CGAL::parameters::point_map(CGAL::Identity_property_map<Kernel::Point_3>())
		.stream_precision(10)))
	{
		std::cerr << "保存失败!!!" << std::endl;
		return -1;
	}
	
	return 0;
}

三、结果展示

1、滤波前
在这里插入图片描述
2、滤波后
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值