CGAL 根据扫描线方向和角度对法向量进行重定向

文章介绍了在机载点云数据中,最小生成树方法对法向量定向的不足,提出了使用CGAL库中的scanline_orient_normals()函数进行扫描线特性点云的法向量重定向。该函数考虑了扫描线ID和扫描角度,优化了点云在2.5D城市场景的处理。代码示例展示了如何读取LAS点云数据,计算法向量并使用不同信息定向法向量,最后将结果写入PLY文件。
摘要由CSDN通过智能技术生成

一、算法原理

在这里插入图片描述

  最小生成树对法向量定向的结果在具有许多尖锐特征和遮挡的机载点云数据中结果并不理想。scanline_orient_normals()是专门用于具有扫描线特性的点云法向量重定向的替代方法。它充分利用了某些激光雷达扫描器的LAS特性,是处理2.5D城市场景中车载或机载点云法向量方向重定向的最佳选择。

1、主要函数

头文件

#include <CGAL/scanline_orient_normals.h>

scanline_orient_normals()

void CGAL::scanline_orient_normals  ( PointRange &  points,  
  const NamedParameters &  np = parameters::default_values()  
 ) 

  通过检查扫描视线方向与当前法线方向的一致性,对点云的法向量进行定向。这个函数要求输入的点是沿着xy平面上对齐的扫描线排序。这种数据通常是通过机载或车载激光雷达设备获得。当提供scanline_id_mapscan_angle时,该方法会给出最优结果。只要点集在2.5D扫描线中有序排列,在缺少其中一个或两个属性的情况下,仍然可以生成正确的结果。

  1. 首先,通过对点进行迭代,获取位于同一扫描线上的点:
  • 如果提供了命名参数scanline_id_map,则每次id更改时范围都会被切断。
  • 如果没有提供扫描线ID映射,回退方法只是简单地在投影xy平面上每次有3个连续点形成锐角时削减范围。这种回退方法给出了次优结果。
  1. 然后,估计每个点与扫描器位置之间的视线(采集时的估计矢量):
  • 如果提供了scan_angle,视线可以直接计算为估计扫描线和扫描角度的组合。
  • 如果没有提供扫scan_angle,扫描仪的位置估计为在xy平面上投影扫描线各点的重心之上。这种回退方法给出了次优结果。
      一旦对每个点的视线进行了估计,就可以通过视点来调整法向量的方向,如果视线和法线向量乘积为正则法向量方向为正的,否则法向量是反的。

二、代码实现

#include <CGAL/Simple_cartesian.h>
#include <CGAL/IO/read_las_points.h>
#include <CGAL/IO/write_ply_points.h>
#include <CGAL/jet_estimate_normals.h>
#include <CGAL/scanline_orient_normals.h>

using Kernel = CGAL::Simple_cartesian<double>;

using Point_with_info = std::tuple<Kernel::Point_3, Kernel::Vector_3, float, unsigned char>;
using Point_map = CGAL::Nth_of_tuple_property_map<0, Point_with_info>;
using Normal_map = CGAL::Nth_of_tuple_property_map<1, Point_with_info>;
using Scan_angle_map = CGAL::Nth_of_tuple_property_map<2, Point_with_info>;
using Scanline_id_map = CGAL::Nth_of_tuple_property_map<3, Point_with_info>;

void dump(const char* filename, const std::vector<Point_with_info>& points)
{
	std::ofstream ofile(filename, std::ios::binary);
	CGAL::IO::set_binary_mode(ofile);
	CGAL::IO::write_PLY(ofile, points, CGAL::parameters::point_map(Point_map()).
		normal_map(Normal_map()));

}

int main(int argc, char** argv)
{
	std::string fname( "cgal//urban.las");

	std::vector<Point_with_info> points;
	// ----------------------------------读取las点云--------------------------------------
	std::cerr << "Reading input file " << fname << std::endl;
	std::ifstream ifile(fname, std::ios::binary);
	if (!ifile ||
		!CGAL::IO::read_LAS_with_properties(ifile, std::back_inserter(points),
			CGAL::IO::make_las_point_reader(Point_map()),
			std::make_pair(Scan_angle_map(),CGAL::IO::LAS_property::Scan_angle()),
			std::make_pair(Scanline_id_map(),CGAL::IO::LAS_property::Scan_direction_flag())))
	{
		std::cerr << "Can't read " << fname << std::endl;
		return -1;
	}
	// --------------------------------计算法向量----------------------------------------
	std::cerr << "Estimating normals" << std::endl;
	CGAL::jet_estimate_normals<CGAL::Parallel_if_available_tag>(points, 12,
			CGAL::parameters::point_map(Point_map()).normal_map(Normal_map()));
	// ---------------------使用扫描角度和扫描方向重定向法线-----------------------------
	std::cerr << "Orienting normals using scan angle and direction flag" << std::endl;
	CGAL::scanline_orient_normals(points,CGAL::parameters::point_map(Point_map()).
		normal_map(Normal_map()).scan_angle_map(Scan_angle_map()).scanline_id_map(Scanline_id_map()));

	dump("out_angle_and_flag.ply", points);
	// ---------------------使用扫描方向对点云进行法线定向-------------------------------
	std::cerr << "Orienting normals using scan direction flag only" << std::endl;
	CGAL::scanline_orient_normals(points,CGAL::parameters::point_map(Point_map()).
		normal_map(Normal_map()).
		scanline_id_map(Scanline_id_map()));
	dump("out_flag.ply", points);
	// ---------------------使用扫描角度对点云进行法线定向-------------------------------
	std::cerr << "Orienting normals using scan angle only" << std::endl;
	CGAL::scanline_orient_normals(points,CGAL::parameters::point_map(Point_map()).
		normal_map(Normal_map()).
		scan_angle_map(Scan_angle_map()));

	dump("out_angle.ply", points);
	// -----------------------不使用额外信息的法线定向-----------------------------------
	std::cerr << "Orienting normals using no additional info" << std::endl;
	CGAL::scanline_orient_normals(points,CGAL::parameters::point_map(Point_map()).
		normal_map(Normal_map()));
	dump("out_nothing.ply", points);

	return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

点云侠

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

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

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

打赏作者

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

抵扣说明:

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

余额充值