CGAL学习记录——区域增长实现多平面分割

CGAL——区域增长聚类实现多平面分割

效果展示

在这里插入图片描述

在这里插入图片描述

代码

代码可直接运行

#include <string>
#include <vector>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <iterator>
#include <boost/iterator/function_output_iterator.hpp>
#include <CGAL/Timer.h>
#include <CGAL/Random.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Point_set_3/IO.h>
#include <CGAL/Shape_detection/Region_growing/Region_growing.h>
#include <CGAL/Shape_detection/Region_growing/Region_growing_on_point_set.h>


using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using FT = typename Kernel::FT;
using Point_3 = typename Kernel::Point_3;
using Vector_3 = typename Kernel::Vector_3;
using Input_range = CGAL::Point_set_3<Point_3>;
using Point_map = typename Input_range::Point_map;
using Normal_map = typename Input_range::Vector_map;
using Neighbor_query = CGAL::Shape_detection::Point_set::K_neighbor_query<Kernel, Input_range, Point_map>;
using Region_type = CGAL::Shape_detection::Point_set::Least_squares_plane_fit_region<Kernel, Input_range, Point_map, Normal_map>;
using Region_growing = CGAL::Shape_detection::Region_growing<Input_range, Neighbor_query, Region_type>;
using Indices = std::vector<std::size_t>;
using Output_range = CGAL::Point_set_3<Point_3>;
using Points_3 = std::vector<Point_3>;

// 定义一个迭代器
struct Insert_point_colored_by_region_index {
    using argument_type = Indices;
    using result_type = void;
    using Color_map = typename Output_range:: template Property_map<unsigned char>;


    const Input_range& m_input_range;//输入
    const   Point_map  m_point_map;//point.map
    Output_range& m_output_range;//输出
    std::size_t& m_number_of_regions;//输出种类

    Color_map m_red, m_green, m_blue;
    Insert_point_colored_by_region_index(const Input_range& input_range,const   Point_map  point_map, 
        Output_range& output_range,std::size_t& number_of_regions) :
        m_input_range(input_range),
        m_point_map(point_map),
        m_output_range(output_range),
        m_number_of_regions(number_of_regions) 
    {
        m_red =m_output_range.template add_property_map<unsigned char>("red", 0).first;
        m_green =m_output_range.template add_property_map<unsigned char>("green", 0).first;
        m_blue = m_output_range.template add_property_map<unsigned char>("blue", 0).first;
    }
    result_type operator()(const argument_type& region)
    {
        CGAL::Random rand(static_cast<unsigned int>(m_number_of_regions));
        const unsigned char r =static_cast<unsigned char>(64 + rand.get_int(0, 192));
        const unsigned char g =static_cast<unsigned char>(64 + rand.get_int(0, 192));
        const unsigned char b = static_cast<unsigned char>(64 + rand.get_int(0, 192));

        for (const std::size_t index : region)
        {
            const auto& key = *(m_input_range.begin() + index);
            const Point_3& point = get(m_point_map, key);
            const auto it = m_output_range.insert(point);
            m_red[*it] = r;
            m_green[*it] = g;
            m_blue[*it] = b;
        }
        ++m_number_of_regions;
    }
}; // Insert_point_colored_by_region_index

int main(int argc, char* argv[]) {

    //读取点云
    std::ifstream in(argc > 1 ? argv[1] : CGAL::data_file_path("data/cube.xyz"));
    CGAL::IO::set_ascii_mode(in);
    if (!in) {
        std::cout <<
            "Error: cannot read the file point_set_3.xyz!" << std::endl;
        std::cout <<
            "You can either create a symlink to the data folder or provide this file by hand."
            << std::endl << std::endl;
        return EXIT_FAILURE;
    }
    //插入法线
    const bool with_normal_map = true;
    Input_range input_range(with_normal_map);
    in >> input_range;
    in.close();
    std::cout <<"* loaded "<< input_range.size() <<" points with normals" << std::endl;


    //默认参数设置
    const std::size_t k = 12;
    const FT          max_distance_to_plane = FT(1);
    const FT          max_accepted_angle = FT(20);
    const std::size_t min_region_size = 200;
    

    //区域增长
    Neighbor_query neighbor_query(input_range,k, input_range.point_map());
    Region_type region_type(input_range,max_distance_to_plane, max_accepted_angle, min_region_size, input_range.point_map(), input_range.normal_map());
    Region_growing region_growing(input_range, neighbor_query, region_type);
    Output_range output_range;

    std::size_t number_of_regions = 0;
    Insert_point_colored_by_region_index inserter(input_range, input_range.point_map(), output_range, number_of_regions);

    CGAL::Timer timer;
    timer.start();
    region_growing.detect( boost::make_function_output_iterator(inserter));
    timer.stop();
    std::cout << "* " << number_of_regions <<" regions have been found in " << timer.time() << " seconds"<< std::endl;
    


    if (argc > 2) {
        const std::string path = argv[2];
        const std::string fullpath = path + "regions_point_set_3.ply";
        std::ofstream out(fullpath);
        out << output_range;
        std::cout << "* found regions are saved in " << fullpath << std::endl;
        out.close();
    }

    return EXIT_SUCCESS;
}

结论

检测出20个区域平面 ,时间消耗0.764s。
在这里插入图片描述

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片