【CGAL】圆柱体检测结果后处理

文章说明

这篇文章主要介绍,对使用CGAL中的 Region Growing 算法爬取圆柱体的结果进行后处理,以获取位置、轴向量、半径都较为合理的单个圆柱体。

在之前的一篇文章中,使用了open3D生成的标准圆柱体测试了爬取圆柱的代码,结果并不好。结果中标准圆柱体被分了好几部分,也就是说,算法检测到了多个圆柱体,但实际上只有一个。其原因是,CGAL中圆柱体检测只是检测圆柱体的侧面,并不包含上下两个底面。而生成的标准圆柱体是带底面的,这对算法造成了干扰,导致结果不准确。

所以,我基于算法得到的结果,自己写了筛选并合并圆柱体的代码,以得到与真实圆柱体相近的圆柱体及其参数。

用途
这个可以用到物体参数化方面,当我们得到了真实世界类似圆柱体的三维模型,想要将它进行参数化,就可以使用检测圆柱+后处理的方法,来得到模型的参数。

算法思路

1、读取圆柱体结果,包括每个圆柱包含的点个数,半径、中心、轴方向,存储在自定义结构体中。

struct Cylinder_Param {
   
   
    uint32_t m_points_num;
    double m_radius;
    Point_3 m_center;
    DT m_direction;
    Cylinder_Param() = default;
    Cylinder_Param(uint32_t points_num, double radius, Point_3& center, DT& direction) :m_points_num(points_num), m_radius(radius), m_center(center), m_direction(direction){
   
   }
};

2、计算每个圆柱体的轴向量与其它各个圆柱体轴向量的角度差异,将角度差较小的圆柱体归为一组。在计算角度之前需要调整两个圆柱体的轴向,使其方向保持一致

3、找到包含点数最多的一组圆柱体,合并这一组圆柱体,得到新的单个圆柱体的各个参数。

合并规则
轴向量:各个圆柱体轴向量求平均后归一化
包含点个数:组中的每个圆柱体包含点个数之和
中心:这是可选的,既可以求所有圆柱中心的平均,也可以使用点数最多的圆柱的中心
半径:组中各个圆柱体的平均,或者直接使用包含点数最多的圆柱中心。

规则可以根据自己的实际情况调整。

代码展示

#include <CGAL/Point_set_3.h>
#include <CGAL/Point_set_3/IO.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Shape_detection/Region_growing/Region_growing.h>
#include <CGAL/IO/read_points.h>
#include <CGAL/property_map.h>
#include <CGAL/Shape_detection/Region_growing/Point_set.h>
#include <boost/iterator/function_output_iterator.hpp>
#include <CGAL/utils.h>
#include <fstream>

#define src_file_path "cylinder2_dense_normals.ply"

#define result_path "cylinder2_dense_all_result.ply"

#define param_path "cylinder2_dense_param.txt"

#define merge_param_path "cylinder2_dense_merge_param.txt"


// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using FT = Kernel::FT;
using Point_3 = Kernel::Point_3;
using Vector_3 = Kernel::Vector_3;
using Line_3 = Kernel::Line_3;
using Point_set = CGAL::Point_set_3<Point_3>;
using Point_map = typename Point_set::Point_map;
//using Normal_map = typename Point_set::Vector_map;
typedef std::pair<Point_3, Vector_3> Point_with_normal;
typedef std::vector<Point_with_normal> Pwn_vector;
using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query_for_point_set<Point_set>;
using Region_type = CGAL::Shape_detection::Point_set::Least_squares_cylinder_fit_region_for_point_set<Point_set>;
using Region_growing = CGAL::Shape_detection::Region_growing<Neighbor_query, Region_type>;

// My
typedef CGAL::Direction_3<Kernel> DT;
typedef std::pair<std::vector<uint32_t>, std::vector<uint32_t>> Cylinders_Group; // first保存该组的圆柱索引,second保存总点数

void detec_and_save(Point_set& point_set, Neighbor_query& neighbor_query, Region_type& region_type)
{
   
   
    // Create an instance of the region growing class.
    Region_growing region_growing(
        point_set, neighbor_query, region_type);

    // Add maps to get a colored output.
    Point_set::Property_map<unsigned char>
        red = point_set.add_property_map<unsigned char>("red", 0).first,
        green = point_set.add_property_map<unsigned char>("green", 0).first,
        blue = point_set.add_property_map<unsigned char>("blue", 0).first;
    // Run the algorithm.
    //CGAL::Random random;
    std::size_t num_cylinders = 0;

    region_growing.detect(
        boost::make_function_output_iterator(
            [&](const std::pair< R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值