【CGAL】Region_Growing检测圆柱,保存结果并输出圆柱体参数

news2024/11/18 11:32:41

目录

  • 说明
  • 代码展示
  • 结果展示
    • 问题说明

说明

这篇博客以代码为主,使用CGAL中的region growing方法检测圆柱体。将不同的圆柱按不同颜色保存,并输出圆柱体的中心坐标、轴方向以及半径。
region growing的具体思想网上的文章已经有很多,可以参考这个。

代码展示

#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 "cylinder1_dense.ply"

// 检测结果分颜色保存
#define result_path "cylinder1_dense_result.ply"

// 参数保存
#define param_path "cylinder1_dense_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 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>;

void detect_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< Region_type::Primitive, std::vector<typename Point_set::Index> >& region) {
            // Assign a random color to each region.
            const unsigned char r = static_cast<unsigned char>(rand() % 255);
            const unsigned char g = static_cast<unsigned char>(rand() % 255);
            const unsigned char b = static_cast<unsigned char>(rand() % 255);
            for (auto id : region.second) {
                put(red, id, r);
                put(green, id, g);
                put(blue, id, b);
            }
            ++num_cylinders;
        }
    )
);

    std::cout << "* number of found cylinders: " << num_cylinders << std::endl;
    // Save regions to a file.
    std::ofstream out(src_file_path);
    CGAL::IO::set_ascii_mode(out);
    out << point_set;
}

void detect_and_print_param(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);

    std::vector<typename Region_growing::Primitive_and_region> regions;
    region_growing.detect(std::back_inserter(regions));

    // 打开输出文件
    std::ofstream outFile(param_path);

    for (size_t i = 0; i < regions.size(); i++)
    {
        const auto& primitive_and_region = regions[i];
        //const auto& region = primitive_and_region.second;
        const auto& cylinder_param = primitive_and_region.first;

        // 获取轴的方向
        const auto& dx = cylinder_param.axis.direction().dx();
        const auto& dy = cylinder_param.axis.direction().dy();
        const auto& dz = cylinder_param.axis.direction().dz();

        // 获取圆柱中心位置
        const auto& cx = cylinder_param.axis.point(0).x();
        const auto& cy = cylinder_param.axis.point(0).y();
        const auto& cz = cylinder_param.axis.point(0).z();

        // 获取圆柱半径
        const auto& r = cylinder_param.radius;

        outFile << r << " " << dx << " " << dy << " " << dz << " " << cx << " " << cy << " " << cz << "\n";

        std::cout << "圆柱半径:" << r << std::endl;
        std::cout << "圆柱轴方向:" << dx << ", " << dy << ", " << dz << std::endl;
        std::cout << "圆柱中心:" << cx << ", " << cy << ", " << cz << std::endl;
    }

    outFile.close();
}


int main(int argc, char** argv) {
    // Load ply data either from a local folder or a user-provided file.

    const std::string input_file = src_file_path;

    std::ifstream in(CGAL::data_file_path(input_file));
    CGAL::IO::set_ascii_mode(in);
    //CGAL::IO::set_binary_mode(in);
    if (!in) {
        std::cerr << "ERROR: cannot read the input file!" << std::endl;
        return EXIT_FAILURE;
    }
    Point_set point_set;
    in >> point_set;
    in.close();
    std::cout << "* number of input points: " << point_set.size() << std::endl;
    //assert(!is_default_input || point_set.size() == 1813);
    assert(point_set.has_normal_map()); // input should have normals
    // Default parameter values for the data file cuble.pwn.
    const std::size_t k = 10;
    const FT          max_distance = FT(1) / FT(500);
    const FT          max_angle = FT(60);
    const std::size_t min_region_size = 200;
    // Create instances of the classes Neighbor_query and Region_type.
    Neighbor_query neighbor_query = CGAL::Shape_detection::Point_set::make_k_neighbor_query(point_set, CGAL::parameters::k_neighbors(k));
    Region_type region_type = CGAL::Shape_detection::Point_set::make_least_squares_cylinder_fit_region(
        point_set,
        CGAL::parameters::
        maximum_distance(max_distance).
        maximum_angle(max_angle).
        minimum_region_size(min_region_size));
    
    // 检测圆柱,对属于不同圆柱的点赋予不同颜色
    //detect_and_save(point_set, neighbor_query, region_type);

    // 检测圆柱,输出每个圆柱的参数
    detect_and_print_param(point_set, neighbor_query, region_type);

    return EXIT_SUCCESS;
}

关于代码
写这个博客的一部分原因是,记录CGAL中保存region growing结果与检测到物体的参数的方式。可以从代码中看到,进行region_growing.detect(*)时,保存结果与输出参数所用的region类型并不一致。

另外还需注意,代码读取的ply文件必须是ASCII格式保存的,否则会出现读取的点不完整问题。

结果展示

原文件
在这里插入图片描述
检测结果
在这里插入图片描述

问题说明

当原点云中的圆柱体拥有上下底面时,检测结果很差。
源文件
在这里插入图片描述
检测结果
在这里插入图片描述

结论
进行圆柱体检测时,干扰点越少结果越精准。其中干扰点除了一些杂点之外,还包括圆柱体的上下两个底面点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1811982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

万界星空科技定制化MES系统,实现数字化生产

一、MES生产管理系统强调三个方面&#xff1a; 1、MES是对整个车间制造过程的优化&#xff0c;而不是单一的解决某个生产瓶颈。 2、MES必须提供实时收集生产过程中数据的功能&#xff0c;并作出相应的分析和处理。 3、MES需要与计划层和控制层进行信息交互&#xff0c;通过企业…

算法day25

第一题 394. 字符串解码 解法&#xff1a;模拟栈的完成上述的操作&#xff1b; 分析&#xff1a; 下面以如图的字符串来分析&#xff1b; 首先定义一个数字栈用来存放数字&#xff0c;同时定义一个容器stringbuffer栈&#xff0c;里面用来存放字符串&#xff1b; 1、遇到数字&…

若依RuoYi-Vue分离版—配置多数据源

若依RuoYi-Vue分离版—配置多数据源 一、修改application-druid.yml二、修改pom文件&#xff0c;引入依赖第一种&#xff1a;下载jar包到本地&#xff0c;然后引入&#xff08;我这边用的是这种&#xff09;本地引入的&#xff0c;打包时需要加上配置 第二种&#xff1a;从远程…

JAVA开发 使用Apache PDFBox库生成PDF文件,绘制表格

1. 表格位置定点 2.执行效果展示&#xff08;截取PDF文件图片&#xff09; 3.执行代码 当我们使用Apache PDFBox库在PDF文件中创建带有表格的内容&#xff0c;需要遵循几个步骤。PDFBox本身并没有直接的API来创建表格&#xff0c;但我们可以通过定位文本、绘制线条和单元格矩形…

如何在Visual Studio Code中禁用Less文件保存时自动编译为CSS的功能

第一步&#xff1a;点击扩展&#xff0c;搜索Easy Less&#xff0c;并找到对应的扩展设置 第二步&#xff1a;点击在setting.json中编辑 第三步&#xff1a;将此段代码复制粘贴 "compress": false, // 是否压缩"sourceMap": false, // 是否生成map文件&am…

揭秘ASA归因统计的奥秘,Xinstall带您轻松上手!

在移动互联网时代&#xff0c;App推广已成为企业获取用户、提升品牌知名度的重要手段。然而&#xff0c;如何准确衡量推广效果&#xff0c;如何精准定位目标用户&#xff0c;一直是困扰着众多App运营者的难题。今天&#xff0c;我们就来谈谈ASA&#xff08;Apple Search Ads&am…

怎么监控电脑屏幕上的画面?监控电脑屏幕的优秀软件有哪些

怎么监控电脑屏幕上的画面呢&#xff1f;当然是用监控软件啦&#xff0c;它的功能超乎你的想象&#xff0c;下面我将详细介绍如何使用监控软件来监控屏幕&#xff0c;内容将包含监控软件的选择、安装、配置以及具体监控功能的实现等方面。 一、选择监控软件 在选择监控软件时&…

SonarQube安全扫描常见问题

目录 一、SonarQube质量报告 二、SonarQube扫描常见问题和修复方法 三、SonarQube质量配置 最近小编在使用SonarQube工具进行代码扫描&#xff0c;检查代码异味&#xff0c;系统漏洞等&#xff0c;实际过程中也遇到了不少问题&#xff0c;这篇文章主要列举我遇到的常见问题和…

鸿蒙开发文件管理:【@ohos.document (文件交互)】

文件交互 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。本模块接口后续将废弃。不建议在OpenHarmony使用以下接口&#xff0c;调用以下接口将抛出异常。 导入模块 import document from ohos.d…

H1B签证/年薪近$6.5万|美国加州大学戴维斯分校博士后申请成功

N博士信息与通信工程专业毕业,希望到美国加州及周边地区从事博士后工作&#xff0c;且最好是H1B签证。我们为其申请到美国加州大学洛杉矶分校及戴维斯分校的职位&#xff0c;年薪为64,480美元&#xff0c;最终其选择可以办理H1B签证的加州大学戴维斯分校。 N博士背景&#xff1…

Django中配置日志

在Django中配置日志的方法非常简单&#xff0c;只需要在 setting 文件中添加配置项&#xff0c;系统会自动生成相应的日志文件&#xff0c;也可以配置调试时显示内容&#xff0c;报错发送邮件等操作。 在setting.py中添加以下配置。 # 日志配置 LOGS_DIRS os.path.join(BASE…

解决群晖NAS无法拉取docker镜像问题

一、问题描述 由于国内的docker已经被管控&#xff0c;直接在群晖NAS的docker面板上是无法直接查询到需要的docker镜像内容&#xff0c;我们需要通过SSH连接到群晖使用docker命令进行拉取镜像使用&#xff0c;如下图所示&#xff1a; 注意&#xff1a;若要通过SSH连接群晖NAS则…

【python中的转义字符】

在Python中&#xff0c;除了换行符&#xff08;\n&#xff09;和制表符&#xff08;\t&#xff09;&#xff0c;还有许多其他的转义字符和字符串格式化符号可以使用。以下是一些常见的例子&#xff1a; 1、常见的转义字符 ### 常见的转义字符 1. **换行符**: \n 2. **制表符*…

Odoo实现自动拉取gitee代码,自动升级模块

系统通过计划任务每天从指定的git仓库获取仓库tag,并存储在数据库中 系统管理员(base.group_system)每次刷新页面,在后台判断最新的tag是否已安装或已忽略来提醒是否有新的版本。 一、依赖 模块依赖python第三方包GitPython,安装方法: pip install GitPython GitP…

Camtasia Studio2024破解神器下载,轻松上手视频剪辑

嘿&#xff01;今天我要和大家分享一个神奇的软件——Camtasia Studio2024最新版的破解安装包&#xff01;&#x1f3ac; 作为一个视频制作爱好者&#xff0c;我一直在寻找一款功能强大、易于操作的视频编辑软件。而Camtasia Studio2024就是我心目中的完美选择&#xff01;它不…

二刷算法训练营Day28 | 回溯算法(4/6)

目录 详细布置&#xff1a; 1. 93. 复原 IP 地址 2. 78. 子集 3. 90. 子集 II 详细布置&#xff1a; 1. 93. 复原 IP 地址 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔…

网络协议四

一、云中网络 物理机的劣势&#xff1a; 1&#xff09;一旦需要扩容 CPU、内存、硬盘&#xff0c;都需要去机房手动弄&#xff0c;非常麻烦 2&#xff09;采购的机器往往动不动几百 G 的内存&#xff0c;而每个应用往往可能只需要 4 核 8G 3&#xff09;一台机器&#xff0c;…

pnpm : 无法加载文件 C:\Users\xxxxx\AppData\Roaming\npm\pnpm.ps1,因为在此系统上禁止运行脚本。

vscode中执行pnpm install的时候&#xff0c;直接报了上面的错误。 解决&#xff1a; 然后输入&#xff1a;set-ExecutionPolicy RemoteSigned&#xff0c;按回车&#xff0c;然后根据提示&#xff0c;我们选A。 然后回车。 这样我们再次回到vscode中的我们就会发现可以了。 …

数字化浪潮下的制造业:WMS仓储系统功能与优势深度解析-亿发

近年来&#xff0c;国内经济增速放缓&#xff0c;中美贸易摩擦加剧&#xff0c;以及制造业产业迁移等因素&#xff0c;使得制造业面临着产能过剩和激烈竞争的局面。制造企业的仓库中常常堆积着大量原材料和积压的成品、半成品&#xff0c;这些库存占用了企业的大量流动资金&…

重点关注!2024年影响因子即将发布!

本周投稿推荐 SSCI • 中科院2区&#xff0c;6.0-7.0&#xff08;录用友好&#xff09; EI • 各领域沾边均可&#xff08;2天录用&#xff09; CNKI • 7天录用-检索&#xff08;急录友好&#xff09; SCI&EI • 4区生物医学类&#xff0c;0.5-1.0&#xff08;录用…