PCL1. 点云的读入和显示

文章介绍了如何使用PCL库读取OBJ、PLY和PCD等格式的点云文件,重点是加载OBJ文件并显示PointXYZRGB类型的点云数据。通过PCL的IO模块和可视化模块,实现了点云的读取和三维可视化。虽然OBJ文件可以包含颜色信息,但示例代码中可能丢失了原始的色彩信息,导致点云显示为黑色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 相关头文件

        点云文件是众多点组成的一个集合,点作为组成点云的最小元素,包含了空间位置XYZ和颜色信息RGB。当然,对颜色的描述可以是灰度值(Intensity)、HSV(HSV颜色空间描述)和Alpha(透明度等)。因此常见的点的类型有: PointXYZ、PointXYZRGB、PointXYZI和PointXYZHSV、POINTXYZRGBA等。从代码上来看,需要导入文件读入的IO模块,点的类型模块。

/*
 * 本例以读取OBJ文件为例
 */

#include<iostream>
using namespace std;

#include<pcl/point_types.h> // 点的类型
// 三种不同的文件io
#include<pcl/io/pcd_io.h>  // 本例中多余
#inlcude<pcl/io/obj_io.h>  
#include<pcl/io/ply_io.h>  // 本例中多余
#include<pcl/visualization/pcl_visualizer.h> // 显示模块


//- 定义点的类型: 使用Typedef进行定义,简化代码
typedef pcl::PointXYZRGB PointT;    
typedef pcl::PointCloud<PointT> PointCloud;

        同时,在CMakeLists中需要添加对PCL库的依赖:

# 与PCL无关的内容
cmake_minimum_required(Version 2.8)
project(pcl_io_display)
add_executable(io_display main.cpp)

# PCL相关
find_package(PCL 1.8 REQUIRED) # 指定了PCL版本
if(PCL_FOUND)
  #根据安装方法可能不同
  ## /usr/include下面是pcl-1.8: ${PCL_INCLUDE_DIRS}/pcl-1.8/pcl/
  ## /usr/include下面是pcl: ${PCL_INCLUDE_DIRS}即可
  include_directories(${PCL_INCLUDE_DIRS}/pcl-1.8/pcl/) 
  add_definitions(${PCL_DEFINITIONS}) 
  link_directories(${PCL_LIBRARY_DIRS})
  target_link_libraries(io_display ${PCL_LIBRARIES})
endif()

    

 

2. 读取点云数据

        点云文件通常以ply、pcd和obj结尾,通常ply文件仅包含点的XYZ信息,OBJ文件包含了XYZRGB信息。PCD文件是pcl原生支持文件类型,其点的信息定义可以是多样的(XYZI, XYZRGB, XYZA等), 其具体定义是通过文件头FIELDS后的信息来确定的。点云的读取方法:

//- 输入为文件路径和点云的引用
void LoadOBJ(string fName, PointCloud& cloud){
    int ret = pcl::io::loadOBJFile(fName, cloud);   //- 二次引用,读入点云存入cloud中
    if(ret<0){
        cout << "点云没有成功读入" << endl; //- 返回小于0,读入失败
    } else {
        cout << "点云成功读入" << endl;   //- 返回大于等于0,读入成功  
    }
}

3. 点云的显示

        在完成点云之后,可以使用pcl显示点云,实现点云的可视化。

    //- 显示点云
    pcl::visualization::PCLVisualizer::Ptr visualizer(
            new pcl::visualization::PCLVisualizer("点云显示窗口"));
    // 背景RGB(此处为黑色), viewport缺省
    visualizer->setBackgroundColor(255,255,255);
    // 添加显示的点云及对应标签,可以添加多个点云,通过标签对应,后续通过标签可以进行单独的设置
    visualizer->addPointCloud<PointT>(cloud, "PointCloud");
    // 设置显示单个点的属性: 如每个点显示的像素大小,可以多次设置多个属性
    // PointCloud是刚刚添加的标签
    visualizer->setPointCloudRenderingProperties(
            pcl::visualization::PCL_VISUALIZER_FONT_SIZE, 5, "PointCloud"
            );
    //- 坐标系设置
    visualizer->addCoordinateSystem(0.5);
    //- 循环显示,每次显示之间可以添加函数处理点云
    while(!visualizer->wasStopped()){
        visualizer->spinOnce(100);
        sleep(0.01); //休眠100ms
    }

4. 代码整理

        整理之后的可运行代码如下, 存在问题。正常的OBJ文件,应该附带一个MLT文件来记录各种材质信息,包括彩色信息。PCL提供两个函数pcl::io::loadPolygonFileOBJ() 和 pcl::io::loadOBJFile() 从这种OBJ文件中读取信息到数据类型pcl::TextureMesh,然后在viewer中使用addTextureMesh进行可视化。

        本例中使用XYZRGB尽管可以显示处三维点云,但是点云失去了原来的色彩信息,即全为黑色。

#include <iostream>

#include <pcl/visualization/cloud_viewer.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>   // 本例中多余
#include <pcl/io/ply_io.h>  // 本例中多余
#include <pcl/io/obj_io.h>
#include <thread>

using namespace std;


typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloud;

//- 输入为文件路径和点云的引用
void LoadOBJ(string fName, PointCloud& cloud){
    int ret = pcl::io::loadOBJFile(fName, cloud);   //- 二次引用,读入点云存入cloud中
    if(ret<0){
        cout << "点云没有成功读入" << endl; //- 返回小于0,读入失败
    } else {
        cout << "点云成功读入" << endl;   //- 返回大于等于0,读入成功
    }
}



int main() {
    string fName = "/home/kylin/CLionProjects/教育小车视觉SLAM/obj/t1.obj";
    PointCloud::Ptr cloud(new PointCloud);
    LoadOBJ(fName, *cloud);
    cout << "总点数: " << cloud->points.size() << endl;

    //- 显示点云
    pcl::visualization::PCLVisualizer::Ptr visualizer(
            new pcl::visualization::PCLVisualizer("点云显示窗口"));
    // 背景RGB(此处为黑色), viewport缺省
    visualizer->setBackgroundColor(255,255,255);
    // 添加显示的点云及对应标签,可以添加多个点云,通过标签对应,后续通过标签可以进行单独的设置
    visualizer->addPointCloud<PointT>(cloud, "PointCloud");
    // 设置显示单个点的属性: 如每个点显示的像素大小,可以多次设置多个属性
    // PointCloud是刚刚添加的标签
    visualizer->setPointCloudRenderingProperties(
            pcl::visualization::PCL_VISUALIZER_FONT_SIZE, 5, "PointCloud"
            );
    //- 坐标系设置
    visualizer->addCoordinateSystem(0.5);
    //- 循环显示,每次显示之间可以添加函数处理点云
    while(!visualizer->wasStopped()){
        visualizer->spinOnce(100);
        sleep(0.01); //休眠100ms
    }




    return 0;
}



### 不使用Shift操作的PCL点云取点方法 在PCL库中,可以采用多种方式来选取特定点而无需依赖于shift操作。对于密集点云可以直接指定索引来获取单个点的信息[^1]。 当面对较为稀疏的点云数据时,推荐的方式是定义一个小范围区域并计算该区域内所有点坐标的平均值即质心位置作为代表点的位置坐标。这种方法能够有效减少噪声影响并且提高所选点的代表性。 为了避免因背景或其他物体干扰而导致错误地选择了不该被选中的点,在选择感兴趣区域之前应该先对该区域内的点进行预处理分析,比如利用法线估计判断表面朝向或者通过距离阈值筛选符合条件的目标点群组。 下面是一个简单的代码示例展示了如何基于上述原则实现在PCL中不使用shift操作完成点云取点: ```cpp #include <pcl/point_cloud.h> #include <pcl/io/pcd_io.h> #include <pcl/filters/passthrough.h> // 假设已经加载了一个名为cloud_in的输入点云pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile ("test_pcd.pcd", *cloud); // 创建一个直通滤波器对象用于去除不需要的部分 pcl::PassThrough<pcl::PointXYZ> pass; pass.setInputCloud (cloud); pass.setFilterFieldName ("z"); pass.setFilterLimits (-0.5, 1.0); // 设置Z轴方向上的过滤区间 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>); pass.filter (*cloud_filtered); // 计算选定区域内所有点的质心 Eigen::Vector4f centroid; pcl::compute3DCentroid(*cloud_filtered, centroid); std::cout << "Selected point at position: [" << centroid[0] << ", " << centroid[1] << ", " << centroid[2] << "]" << std::endl; ``` 此段程序首先读入一个PCD文件格式存储的点云数据集`cloud`,接着应用了直通滤波(Pass Through Filter),只保留满足条件(这里是以Z坐标为例)的数据点形成新的集合`cloud_filtered`。最后调用了`pcl::compute3DCentroid()`函数求得这些剩余点构成的空间几何体中心位置,并将其打印出来表示最终选出的一个典型点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值