PCL学习二:PCL基础应用教程

参考引用

  • PCL Basic Usage
  • PCL 点云库官网教程

1. pcl_viewer 基本使用

1.1 pcl_viewer 安装测试

  • pcl_data 源码克隆
    $ git clone https://github.com/PointCloudLibrary/data.git
    
  • 进入 /pcl_data/tutorials(如下图)
    $ cd ~/pcl_data/tutorials  # 此处为重命名后的文件夹 pcl_data
    

在这里插入图片描述

  • 查看 .pcd 文件(以 ism_test_cat.pcd 为例)
    $ pcl_viewer ism_test_cat.pcd
    

在这里插入图片描述

1.2 pcl_viewer 常用操作

  • 基本使用

    • 进入:pcl_viewer xxxxx.pcd
    • 帮助:在界面中输入 h,可以在控制台看到帮助信息
    • 退出:界面中输入 q
    • 放大缩小:鼠标滚轮 或 Alt + [+/-]
    • 平移:Shift + 鼠标拖拽
    • 旋转:Ctrl + 鼠标拖拽
    • 修改点颜色:数字 1,2,3,4,5…9,重复按 1 可切换不同颜色方便观察
    • 修改点大小:放大 Ctrl + Shift + 加号,缩小 Ctrl + 减号
    • 保存截图:j
    • 显示颜色尺寸:u
    • 显示比例尺寸:g
    • 在控制列出所有几何和颜色信息:l
  • 常用指令

    # 1. 修改背景色或前景色
    $ pcl_viewer ism_test_cat.pcd -bc 255,255,255    # 修改背景色为白色
    $ pcl_viewer ism_test_cat.pcd -fc 0xff,0x0,0x0   # 修改前景色为红色
    
    # 2. 设置点大小和不透明度
    $ pcl_viewer ism_test_cat.pcd -ps 4    # 设置点大小为 4
    $ pcl_viewer ism_test_cat.pcd -opaque 0.1    # 设置点透明度为 0.1
    
    # 3. 设置坐标轴显示
    $ pcl_viewer ism_test_cat.pcd -ax 64    # 显示大小为 64 的坐标轴
    $ pcl_viewer ism_test_cat.pcd -ax 64 -ax_pos -64,-64,0    # 显示坐标轴并改变其位置(默认 0,0,0)
    
    # 4. 格式转换命令
    $ pcl_pcd2ply input.pcd output.ply    # 将 PCD 转为 ply 文件
    $ pcl_mesh2pcd input.{ply,obj} output.pcd   # 将 CAD 模型转为 PCD 文件
    $ pcl_mesh2pcd input.{ply,obj} output.pcd -leaf_size 10   # -leaf_size :修改体素网格的 XYZ 大小,用于增减点的密度
    
    # 5. Octrees 八叉树可视化(下图所示)
    $ pcl_octree_viewer ism_test_cat.pcd 0.2    # 0.2 代表分辨率
    

在这里插入图片描述

  • 鼠标选点打印坐标
    • 选点模式进入:pcl_viewer -use_point_picking bunny.pcd
    • 选择指定点:shift + 鼠标左键

2. 在项目中使用 PCL

  • 新建项目工作空间 pcl_demo_ws

    $ mkdir pcl_demo_ws
    
  • 在工作空间新建 pcd_write.cpp 文件

    // pcd_write.cpp
    // 随机生成了 5 个点,并将之以 ASCII 形式保存(序列化)在 test_pcd.pcd 文件中
    #include <iostream>
    #include <pcl/io/pcd_io.h>
    #include <pcl/point_types.h>
    
    int main(int argc, char **argv) {
        pcl::PointCloud<pcl::PointXYZ> cloud;
    
        // Fill in the cloud data
        cloud.width = 5;
        cloud.height = 1;
        cloud.is_dense = false; // 没有无穷值或 NaN 值
        cloud.points.resize(cloud.width * cloud.height);
    
        std::cout << rand() << std::endl;
        std::cout << rand() / (RAND_MAX + 1.0f) << std::endl;
        std::cout << 1024 * rand() / (RAND_MAX + 1.0f) << std::endl;
    
        // 随机生成5个点
        for (size_t i = 0; i < cloud.points.size(); ++i) {
            cloud.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
            cloud.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
            cloud.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
        }
    
        pcl::io::savePCDFileASCII("test_pcd.pcd", cloud);
        std::cerr << "Saved " << cloud.points.size() << " data points to test_pcd.pcd." << std::endl;
    
        for (size_t i = 0; i < cloud.points.size(); ++i)
            std::cerr << "    " << cloud.points[i].x << " " << cloud.points[i].y << " " << cloud.points[i].z << std::endl;
    
        return (0);
    }
    
  • 在工作空间新建 CMakeLists.txt 配置文件

    cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
    project(MY_GRAND_PROJECT)
    find_package(PCL 1.3 REQUIRED COMPONENTS common io)
    include_directories(${PCL_INCLUDE_DIRS})
    link_directories(${PCL_LIBRARY_DIRS})
    add_definitions(${PCL_DEFINITIONS})
    add_executable(pcd_write_test pcd_write.cpp)
    target_link_libraries(pcd_write_test ${PCL_LIBRARIES})
    
  • 编译与执行

    # 编译
    $ mkdir build
    $ cd build
    $ cmake ..
    $ make
    
    # 执行
    $ ./pcd_write_test
    
    // 终端输出结果
    1804289383
    0.394383
    -0.106395
    Saved 5 data points to test_pcd.pcd.
        -0.397406 -0.473106 0.292602
        -0.731898 0.667105 0.441304
        -0.734766 0.854581 -0.0361733
        -0.4607 -0.277468 -0.916762
        0.183749 0.968809 0.512055
    
  • 查看生成的 test_pcd.pcd 文件

    $ pcl_viewer test_pcd.pcd
    
    • 查看 pcd 内容
    $ cat test_pcd.pcd
    
    # .PCD v0.7 - Point Cloud Data file format
    VERSION 0.7
    FIELDS x y z
    SIZE 4 4 4
    TYPE F F F
    COUNT 1 1 1
    WIDTH 5
    HEIGHT 1
    VIEWPOINT 0 0 0 1 0 0 0
    POINTS 5
    DATA ascii
    -0.3974061 -0.47310591 0.29260206
    -0.73189831 0.66710472 0.44130373
    -0.73476553 0.85458088 -0.036173344
    -0.46070004 -0.2774682 -0.91676188
    0.1837492 0.96880913 0.5120554
    

3. 使用矩阵变换点云

  • 新建项目工作空间 pcl_demo_ws02

    $ mkdir pcl_demo_ws02
    
  • 在工作空间新建 matrix_transform.cpp 文件

    #include <iostream>
    
    #include <pcl/io/pcd_io.h>
    #include <pcl/io/ply_io.h>
    #include <pcl/point_cloud.h>
    #include <pcl/console/parse.h>
    #include <pcl/common/transforms.h>
    #include <pcl/visualization/pcl_visualizer.h>
    
    int main(int argc, char **argv) {
        // Load file | Works with PCD and PLY files
        pcl::PointCloud<pcl::PointXYZ>::Ptr source_cloud(new pcl::PointCloud<pcl::PointXYZ>());
    
        if (pcl::io::loadPCDFile(argv[1], *source_cloud) < 0) {
            std::cout << "Error loading point cloud " << argv[1] << std::endl << std::endl;
            return -1;
        }
    
        /* Reminder: how transformation matrices work :
                      |-------> This column is the translation
              | 1 0 0 x |  \
              | 0 1 0 y |   }-> The identity 3x3 matrix (no rotation) on the left
              | 0 0 1 z |  /
              | 0 0 0 1 |    -> We do not use this row (and it has to stay 0,0,0,1)
        
            方法一:使用 Matrix4f
            这个方法容易理解但也容易出错
        */
        Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();
        float theta = M_PI / 4; // 旋转角(弧度)
        // 旋转矩阵:沿 z 轴旋转 45°
        transform_1(0, 0) = cos(theta);  // transform_1(row, column)
        transform_1(0, 1) = -sin(theta);
        transform_1(1, 0) = sin(theta);
        transform_1(1, 1) = cos(theta);
        // 平移矩阵:沿 x 轴平移 2.5m
        transform_1(0, 3) = 2.5;    
        /*
                | cos(θ) -sin(θ)  0.0 |
            R = | sin(θ)  cos(θ)  0.0 |    // 旋转矩阵:沿 z 轴旋转 45°(逆时针)
                | 0.0     0.0     1.0 |
            t = < 2.5, 0.0, 0.0 >    // 平移矩阵:沿 x 轴平移 2.5m
        */
        // 打印变换结果
        printf("Method #1: using a Matrix4f\n");
        std::cout << transform_1 << std::endl;
    
        /*  
            方法二: 使用 Affine3f
            这个方法更容易且较少出错
        */
        // 创建仿射变换对象
        Eigen::Affine3f transform_2 = Eigen::Affine3f::Identity();
        // 在 z 轴平移 30m
        transform_2.translation() << 0.0, 0.0, 30.0;
        // 绕 Z 旋转 45 度(逆时针)
        transform_2.rotate(Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitZ()));
        // 打印仿射变换矩阵
        printf("\nMethod #2: using an Affine3f\n");
        std::cout << transform_2.matrix() << std::endl;
    
        // 创建变换后的点云
        pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud(new pcl::PointCloud<pcl::PointXYZ>());
        // 执行变换,source_cloud 为变换前的点云
        pcl::transformPointCloud(*source_cloud, *transformed_cloud, transform_2);
    
        // 可视化操作
        printf("\nPoint cloud colors : white = original point cloud\n" "red = transformed point cloud\n");
        pcl::visualization::PCLVisualizer viewer("Matrix transformation example");
    
        // 定义点云的 RGB 值,并将点云添加到查看器中,并通过颜色处理程序
        pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> source_cloud_color_handler(source_cloud, 255, 255, 255);
        viewer.addPointCloud(source_cloud, source_cloud_color_handler, "original_cloud");
    
        pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> transformed_cloud_color_handler(transformed_cloud, 230, 20, 20); // Red
        viewer.addPointCloud(transformed_cloud, transformed_cloud_color_handler, "transformed_cloud");
    
        // 设置坐标系系统
        viewer.addCoordinateSystem(0.5, "cloud", 0);
        // 设置背景色为黑灰色
        viewer.setBackgroundColor(0.05, 0.05, 0.05, 0);
        // 设置渲染属性(点大小)
        viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud");
        viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "transformed_cloud");
        //viewer.setPosition(800, 400); // Setting visualiser window position
    
        // 当按下 q 之前不断循环可视化操作
        while (!viewer.wasStopped()) { 
            viewer.spinOnce();
        }
        return 0;
    }
    
  • 在工作空间新建 CMakeLists.txt 配置文件

    cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
    
    project(pcl-matrix_transform)
    
    find_package(PCL 1.7 REQUIRED)
    
    include_directories(${PCL_INCLUDE_DIRS})
    link_directories(${PCL_LIBRARY_DIRS})
    add_definitions(${PCL_DEFINITIONS})
    
    add_executable (matrix_transform matrix_transform.cpp)
    target_link_libraries (matrix_transform ${PCL_LIBRARIES})
    
  • 编译与执行

    # 编译
    $ mkdir build
    $ cd build
    $ cmake ..
    $ make
    
    # 执行
    $ ./matrix_transform ism_test_cat.pcd  # 后面跟的 .pcd 或 .ply 文件为需要进行矩阵变换的文件
    
    // 终端输出结果
    Method #1: using a Matrix4f
     0.707107 -0.707107         0       2.5
     0.707107  0.707107         0         0
            0         0         1         0
            0         0         0         1
    
    Method #2: using an Affine3f
     0.707107 -0.707107         0         0
     0.707107  0.707107         0         0
            0         0         1        30
            0         0         0         1
    
    Point cloud colors : white  = original point cloud
                           red  = transformed point cloud
    

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Chapter 4 :Constraining I/O Delay(ug903)

4.1 About Constraining I/O Delay 要在设计中准确地建模外部时序上下文&#xff0c;必须为输入和输出端口提供时序信息。由于XilinxVivado集成设计环境&#xff08;IDE&#xff09;只能识别FPGA边界内的时序&#xff0c;因此必须使用以下命令来指定超出这些边界的延迟…

200人 500人 园区网设计

实验要求&#xff1a; ① 设置合理的STP优先级、边缘端口、Eth-trunk ② 企业内网划分多个vlan &#xff0c;减少广播域大小&#xff0c;提高网络稳定性 ③ 所有设备&#xff0c;在任何位置都可以telnet远程管理 ④ 出口配置NAT ⑤ 所有用户均为自动获取ip地址 ⑥ 在企业…

Matlab高光谱遥感、数据处理与混合像元分解及典型案例

站在学员的角度去理解“高光谱”&#xff0c;用大家能听的懂的语言去讲述高光谱的基本概念和理论&#xff0c;帮助学员深入理解这项技术的底层科学机理。方法篇&#xff0c;将高光谱技术与MATLAB工具结合起来&#xff0c;采用MATLAB丰富的工具箱&#xff0c;快速复现高光谱数据…

Java 重写(Override)与重载(Overload)

重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变&#xff0c;核心重写&#xff01; 重写的好处在于子类可以根据需要&#xff0c;定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。 重写方法不…

【MySQL自学之路】第4天——模式、表、视图、索引(数据定义详细版)

目录 前言 数据库 数据库的建立 数据库的使用 数据库的查看 数据库的删除 模式 查看所有的模式 模式和数据库之间的关系 ​编辑建立模式 删除模式 表 数据类型 查看一个数据库下面的所有表(必须进入要查看的数据库) 创建基本表 查看表结构&#xff08;查看表建…

Arduino学习笔记5

一.直流电机控制实验 1.源代码 int dianJiPin9;//定义数字9接口接电机驱动IN1的控制口void setup() {pinMode(dianJiPin,OUTPUT);//定义电机驱动IN1的控制口为输出接口 } void loop() {digitalWrite(dianJiPin,LOW);//关闭电机delay(1000);//延时digitalWrite(dianJiPin,HIGH…

【Vue 基础】vue-cli初始化项目及相关说明

目录 1. 创建项目 2. 项目文件介绍 3. 项目的其它配置 3.1 项目运行时&#xff0c;让浏览器自动打开 3.2 关闭eslint校验功能 3.3 src文件夹简写方法 1. 创建项目 vue create 项目名 2. 项目文件介绍 创建好的项目中包含如下文件&#xff1a; &#xff08;1&#xff09…

工具链和其他-超级好用的web调试工具whistle

目录 whistle介绍 整体结构 能力 规则 6个使用场景示例 1.修改Host 2.代理 3.替换文件&#xff08;线上报错时&#xff09; 4.替换UA 5.远程调试 6.JS注入 互动 whistle介绍 整体结构 安装&#xff1a; npm install whistle -g cli&#xff1a;whistle help 启动…

算法之时间复杂度---数据结构

目录 前言&#xff1a; 1.时间复杂度 1.1时间复杂度的理解 1.2规模与基本操作执行次数 1.3大O渐进表示法 1.4计算基本操作的次数 2.常见的时间复杂度及其优劣比较 ❤博主CSDN&#xff1a;啊苏要学习 ▶专栏分类&#xff1a;数据结构◀ 学习数据结构是一件有趣的事情&…

什么是Web1.0时代、Web2.0时代、Web3.0时代?

什么是Web1.0时代、Web2.0时代、Web3.0时代&#xff1f; 互联网的起源。1969年美国的阿帕网的出现标志着互联网的诞生&#xff0c;而1973年第一台个人电脑The Xerox Alto的出现就预示了互联网将蓬勃生长&#xff0c;随之而来的就是我们迈入了信息时代。短短几十年的发展&#x…

浏览器缓存策略:强缓存和协商缓存

浏览器缓存&#xff1a;其实就是在本地使用的计算机中开辟一个内存区&#xff0c;同时也开辟一个硬盘区&#xff0c;作为数据传输的缓冲区&#xff0c;然后利用这个缓冲区来暂时保护用户以前访问的信息通常浏览器的缓存策略分为两种&#xff1a;强缓存和协商缓存&#xff0c;强…

零基础学java——【基础语法】基本输入、输出语句,变量,运算符

目录 变量 数据类型 基本数据类型一览表 声明和初始化 基本的输出、输出语句 输出语句 补充“”的使用 输入语句Scanner 使用步骤 代码演示 运算符 有些内容可能会与c语言作比较 内容借鉴了韩顺平老师的java课堂笔记&#xff08;b站课&#xff09; 变量 数据类型 基本…

CKA证书题库-总结

CKA真题&#xff08;考题总结&#xff09; 文章目录 CKA真题&#xff08;考题总结&#xff09;证书个人考试总结申诉结果 CKA题目参考博主重点介绍 CKA模拟题库 注意事项考试概要考试注意事项&#xff1a; CKA题目答案设置自动补全方法一方法二 第⼀题&#xff1a;权限控制RBAC…

【4. ROS的主要通讯方式:Topic话题与Message消息】

【4. ROS的主要通讯方式&#xff1a;Topic话题与Message消息】 1. 前言1.1 王者解释结点通讯&#xff1a;1.2 通讯小结 2. 灵活的Topic话题图解2.1 话题注意细节2.2 外延补充 3. Message消息图解3.1 消息类型3.2 查看标准消息类型std_msgs 4. 使用C实现Publisher发布者4.1 发布…

Sametime 12.0.1 FP1发布以及Notes中的SwiftFile使用

大家好&#xff0c;才是真的好。 上周&#xff0c;HCL推出了Sametime 12.0.1FP1FP1更新包程序&#xff0c;包含不少新功能以及很多修复程序。虽然Sametime组件现在不需要运行在Domino服务器上&#xff0c;但毕竟Sametime通常会使用Domino目录或Domino中的LDAP目录服务&#xf…

Maven 如何下载依赖包的源码包

使用Maven下载依赖包的时候&#xff0c; 默认是不会下载源码包的&#xff0c;但是有时候&#xff0c; 需要Debug代码&#xff0c;或是看看依赖项的源码的写法&#xff0c; 就需要下载源码包了。 这里以 Apache 的 commons-text 为例&#xff0c; 在Maven中添加如下依赖配置&am…

HCIA-RS实验-ENSP设备的基础配置

本文主要简单地介绍ENSP设备的基础配置&#xff0c;帮助读者快速上手使用ENSP。可以掌握一些基础的配置方案&#xff0c;更改名称&#xff0c;系统时间&#xff0c;系统地区、密码登录等信息 以下是该文章的拓扑图&#xff1b;现将这2台设备启动&#xff1b;后续双击即可进入命…

Openswan安装和简单配置

Openswan安装和简单配置 安装环境&#xff1a; 操作系统&#xff1a;Ubuntu20.0.4TLS 用户权限&#xff1a;root下载Openswan: wget https://github.com/xelerance/Openswan/archive/refs/tags/v3.0.0.zip安装Openswan: 解压Openswan&#xff1a;&#xff08;PS&#xff1a…

Arduino学习笔记4

一.声控灯实验 1.源代码 int led2;//定义板子上数字2口控制小灯 int flag0;//定义一个变量记录小灯是亮起还是熄灭 int shengyin3;//定义声音传感器的控制口void setup() {pinMode(led,OUTPUT);//定义小灯为输出模式pinMode(shengyin,INPUT);//定义声音控制口为输入模式 } vo…

基于天牛须(BAS)与NSGA-Ⅱ混合算法的交直流混合微电网多场景多目标优化调度(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …