pcl基础知识

什么是点云?

点云Point Cloud是三维空间中,表达目标空间分布和目标表面特性的点的集合,点云通常可以从深度相机中直接获取,也可以从CAD等软件中生成。点云是用于表示多维点集合的数据结构,通常用于表示三维数据。在3D点云中,这些点通常代表采样表面的X,Y和Z几何坐标。当存在颜色信息时(请参见下图),点云变为4D。

三维图像有以下几种表现形式:深度图(描述物体与相机的距离信息),几何模型(由CAD等软件生成),点云模型(逆向工程设备采集生成)

一些常见的点云图如下:

人的侧脸3D
man

一只兔子3D
pcl_bunny.png

PCL(Point Cloud Library)是用于2D / 3D图像和点云处理的大型开源跨平台的C++编程库。 PCL框架实现了大量点云相关的通用算法和高效的数据结构。内容涉及了点云的获取、滤波、分割、配准、检索、特征提取、特征估计,表面重建、识别、模型拟合、追踪、曲面重建、可视化等等,这些算法可用于从嘈杂的数据中过滤出异常值,将3D点云缝合在一起,分割场景的部分区域,提取关键点并计算描述符,根据物体的几何外观识别实际物体,创建表面点云并将其可视化。支持多种操作系统,可以在Windows、Linux、MacOS X、Android、部分嵌入式实时系统上运行。

如果说OpenCV是2D信息获取与处理的结晶,那么PCL就在3D信息获取与处理上也具有相同的地位。相比图像数据,点云数据多了一个维度,因此能够更全面的刻画三维场景中的对象。随着智能机器人,包括机械臂,无人汽车,无人机,服务机器人等快速普及和应用,点云处理及其背后的3D视觉,正在成为一个越来越重要且越来越活跃的领域。

什么是pcl

PCL(Point Cloud Library)是在吸收了前人点云相关研究基础上建立起来的大型跨平台开源C++编程库,它实现了大量点云相关的通用算法和高效数据结构,涉及到点云获取、滤波、分割、配准、检索、特征提取、识别、追踪、曲面重建、可视化等。支持多种操作系统平台,可在Windows、Linux、Android、Mac OS X、部分嵌入式实时系统上运行。如果说OpenCV是2D信息获取与处理的结晶,那么PCL就在3D信息获取与处理上具有同等地位,PCL是BSD授权方式,可以免费进行商业和学术应用。

应用领域

1、机器人领域
深度信息结合2D信息的应用研究。,深度信息的引人能够使机器人
更好地时环境进行认知、辨识,与图像信息在机器人领域的应用一样, 需要强大智能算法支撑,PCL就为此而生
2、CAD/CAM
目前在CAD/CAM 领域利用激光点云进行商精度测量与重建成为趋势
逆向工程技术能够对产品实物进行测绘,重构产品表面三维几何模型, 生成产品制造所需的数字化文档
3、激光遥感测量
激光遥感测量系统是目前最先进的实时获取地形表面三维空间信息和影像的遥感系统,但现在算法结果和实际结果差别较大,PCL中的模块有助于解决此问题。
4、虚拟现实,人机交互
PCL是基于RGBD设备的虚拟现实和人机交互应用生态链中最重要的一个环节

Pcl的结构和内容

pcl架构图如图所示:
![pcl架构图](https://img-blog.csdnimg.cn/de2d9a4454404216982c5b7a042417a9.png)

● PCL 架构图如图,,对于3D 点云处理来说, PCL 完全是一个模块化的现代C+ + 模板库。其基于以下第三方库:Boost 、Eigen 、FLANN 、VTK 、CUDA 、OpenNI 、QHull , 实现点云相关的获取、滤波、分割、配准、检索、特征提取、识别、追踪、曲面重建、可视化等。

● PCL 中的所有模块和. 算法都是通过Boost 共享指针来传送数据,因而避免了多次复制系统中已存在的数据的需要。
● 从0.6 版本开始, PCL 就已经被移入到 Windows 、Mac OS 和Linux 系统,并且在Android 系统也已经开始投入使用,这使得PCL 的应用容易移植与多方发布。
● 从算法的角度, PCL 是指纳入了多种操作点云数据的三维处理算法,其中包括过滤、特征估计、表面重建、模型拟合和分割、定位搜索等。
● 在PCL中一个处理管道的基本接口程序如下:
a. 创建处理对象〈例如过滤、特征估计、分割等) .
b. 使用set l npu t C l o ud 通过输入点云数据,处理模块.
c. 设置算法相关参数
d. 调用计算(或过滤、分割等〉得到输出

PCD文件格式

# .PCD v.7 - Point Cloud Data file format
VERSION .7								# 版本号
FIELDS x y z rgb				#  指定一个点可以有的每一个维度和字段的名字
SIZE 4 4 4 4								# 用字节数指定每一个维度的大小。例如:
TYPE F FFF									# 用一个字符指定每一个维度的类型 int uint folat
COUNT 1 1 1 1						# 指定每一个维度包含的元素数目
WIDTH 640    						   # 像图像一样的有序结构,有640行和480列,
HEIGHT 480    					  # 这样该数据集中共有640*480=307200个点
VIEWPOINT 0 0 0 1 0 0 0			# 指定数据集中点云的获取视点 视点信息被指定为平移(txtytz)+四元数(qwqxqyqz)
POINTS 307200						# 指定点云中点的总数。从0.7版本开始,该字段就有点多余了
DATA ascii										# 指定存储点云数据的数据类型。支持两种数据类型:ascii和二进制
0.93773 0.33763 0 4.2108e+06
0.90805 0.35641 0 4.2108e+06

文件头格式

每一个PCD文件包含一个文件头,它确定和声明文件中存储的点云数据的某种特性。PCD文件头必须用ASCII码来编码。PCD文件中指定的每一个文件头字段以及ascii点数据都用一个新行(\n)分开了,从0.7版本开始,PCD文件头包含下面的字段:

  1. VERSION –指定PCD文件版本

    FIELDS –指定一个点可以有的每一个维度和字段的名字。例如: FIELDS x y z                     
    # XYZ data FIELDS x y z rgb                          # XYZ + colors FIELDS x y z normal_xnormal_y normal_z         # XYZ +
    

    surface
    normals FIELDS j1 j2 j3 # moment
    invariants …

    ● SIZE –用字节数指定每一个维度的大小。例如: unsigned char/char has 1 byte unsigned
    short/short has 2 bytes unsignedint/int/float has 4 bytes double has
    8 bytes
    
    1. List item

    TYPE –用一个字符指定每一个维度的类型。现在被接受的类型有: I
    –表示有符号类型int8(char)、int16(short)和int32(int); U –
    表示无符号类型uint8(unsigned char)、uint16(unsigned short)和uint32(unsigned
    int); F –表示浮点类型。

    ·COUNT
    –指定每一个维度包含的元素数目。例如,x这个数据通常有一个元素,但是像VFH这样的特征描述子就有308个。实际上这是在给每一点引入n维直方图描述符的方法,把它们当做单个的连续存储块。默认情况下,如果没有COUNT,所有维度的数目被设置成1。
    
    ·WIDTH –用点的数量表示点云数据集的宽度。根据是有序点云还是无序点云,WIDTH有两层解释:
    1)它能确定无序数据集的点云中点的个数(和下面的POINTS一样); 2)它能确定有序点云数据集的宽度(一行中点的数目)。
    注意:有序点云数据集,意味着点云是类似于图像(或者矩阵)的结构,数据分为行和列。这种点云的实例包括立体摄像机和时间飞行摄像机生成的数据。有序数据集的优势在于,预先了解相邻点(和像素点类似)的关系,邻域操作更加高效,这样就加速了计算并降低了PCL中某些算法的成本。
    例如: WIDTH 640       # 每行有640个点
    

    ·HEIGHT –用点的数目表示点云数据集的高度。类似于WIDTH ,HEIGHT也有两层解释:
    1)它表示有序点云数据集的高度(行的总数); 2)对于无序数据集它被设置成1(被用来检查一个数据集是有序还是无序)。 有序点云例子:
    WIDTH 640 # 像图像一样的有序结构,有640行和480列, HEIGHT 480 #
    这样该数据集中共有640*480=307200个点 无序点云例子: WIDTH 307200 HEIGHT 1 #
    有307200个点的无序点云数据集

    ·VIEWPOINT–指定数据集中点云的获取视点。VIEWPOINT有可能在不同坐标系之间转换的时候应用,在辅助获取其他特征时也比较有用,例如曲面法线,在判断方向一致性时,需要知道视点的方位,
    视点信息被指定为平移(txtytz)+四元数(qwqxqyqz)。默认值是: VIEWPOINT 0 0 0 1 0 0 0

    ·POINTS–指定点云中点的总数。从0.7版本开始,该字段就有点多余了,因此有可能在将来的版本中将它移除。 例子: POINTS
    307200 #点云中点的总数为307200

    ·DATA –指定存储点云数据的数据类型。从0.7版本开始,支持两种数据类型:ascii和二进制。查看下一节可以获得更多细节。
    注意:文件头最后一行(DATA)的下一个字节就被看成是点云的数据部分了,它会被解释为点云数据。

警告:PCD文件的文件头部分必须以上面的顺序精确指定,也就是如下顺序:
VERSION、FIELDS、SIZE、TYPE、COUNT、WIDTH、HEIGHT、VIEWPOINT、POINTS、DATA
之间用换行隔开。

点云基础格式转换

1、 将xyzrgb转换为xyz格式的点云
#include <pcl/io/pcd_io.h>
#include <ctime>
#include <Eigen/Core>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
 
using namespace std;
typedef pcl::PointXYZ point;
typedef pcl::PointXYZRGBA pointcolor;
 
int main(int argc,char **argv)
{
        pcl::PointCloud<pointcolor>::Ptr input (new pcl::PointCloud<pointcolor>);
        pcl::io::loadPCDFile(argv[1],*input);
        
 
        pcl::PointCloud<point>::Ptr output (new pcl::PointCloud<point>);
        int M = input->points.size();
        cout<<"input size is:"<<M<<endl;
 
        for (int i = 0;i <M;i++)
        {
                point p;
                p.x = input->points[i].x;
                p.y = input->points[i].y;
                p.z = input->points[i].z; 
                output->points.push_back(p);
        }
        output->width = 1;
        output->height = M;
        
        cout<< "size is"<<output->size()<<endl;
        pcl::io::savePCDFile("output.pcd",*output);
 


2、pcd转txt
#include <iostream>
#include <fstream>
#include <pcl/io/pcd_io.h>   

int main(int argc, char *argv[])
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::io::loadPCDFile("rabbit.pcd", *cloud);

	std::ofstream outfile;
	outfile.open("rabbit.txt");

	for (size_t i = 0; i < cloud->points.size(); ++i)
	{
		outfile << cloud->points[i].x << "\t" << cloud->points[i].y << "\t" << cloud->points[i].z << "\n";
	}

	return 0;
}

3、txt转换pcd
#include <iostream>
#include <fstream>
#include <pcl/io/pcd_io.h>   

int main(int argc, char *argv[])
{
	std::ifstream infile;
	infile.open("rabbit.txt");
	
	float x, y, z;
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	while (infile >> x >> y >> z)
	{
		cloud->push_back(pcl::PointXYZ(x, y, z));
	}
	pcl::io::savePCDFileBinary("rabbit.pcd", *cloud);

	return 0;
}

4 pcd转换ply
#include <iostream>          
#include <pcl/io/pcd_io.h>  
#include <pcl/point_types.h> 
#include <pcl/io/ply_io.h>  

int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::io::loadPCDFile("rabbit.pcd", *cloud);
	pcl::io::savePLYFileBinary("rabbit.ply", *cloud);

	return 0;
}

其余格式转换
pcd转ply(三角网格化)
ply转pcd
obj/ply转pcd(均匀采样)
pcd转obj
stl转ply
ply转stl
可参考添加链接描述

可用point类型

在pcl中定义了大量的point类型,全部都在point_type.hpp(common/include/pcl/impl/point_types.hpp)中,在定义自己需要的类型之前可以了解已有的类型,避免重复定义。

点云的数据结构如下:

$ rosmsg info sensor_msgs/PointCloud2
std_msgs/Header header
  uint32 seq
  time stamp
  string frame_id
uint32 height
uint32 width
sensor_msgs/PointField[] fields
  uint8 INT8=1
  uint8 UINT8=2
  uint8 INT16=3
  uint8 UINT16=4
  uint8 INT32=5
  uint8 UINT32=6
  uint8 FLOAT32=7
  uint8 FLOAT64=8
  string name
  uint32 offset
  uint8 datatype
  uint32 count
bool is_bigendian
uint32 point_step
uint32 row_step
uint8[] data
bool is_dense

变量解释:

header --头文件,包含消息的时间戳和坐标系

height --点云的高度,如果是无序点云,则为1
width --每行点云的宽度
fields --每个点的成员变量,其中name为对应成员变量的名字,datatype为变量的数据类型,具体对应关系如下
// uint8 INT8 = 1
// uint8 UINT8 = 2
// uint8 INT16 = 3
// uint8 UINT16 = 4
// uint8 INT32 = 5
// uint8 UINT32 = 6
// uint8 FLOAT32 = 7
// uint8 FLOAT64 = 8
is_bigendian –
point_step --每个点占用的比特数,1个字节对应8个比特数
row_step --每一行占用的比特数
data --为序列化后的数据,直接获得不了信息,序列化是为了方便信息传输和交换,使用时需要反序列化
is_dense --是否有非法数据点,true表示没有

点云的数据结构主要有以下格式:PointXYZ、PointXYZI、PointXYZRGBA、PointXYZRGB、PointXY、InterestPoint、Normal、PointNormal、PointXYZRGBNormal、PointXYZINormal、PointXYZLNormal、PointXYZL、PointXYZRGBL、PointXYZHSV、PointWithRange、PointWithViewpoint、MomentInvariants、PrincipalRadiiRSD、Boundary、PrincipalCurvatures、PFHSignature125、FPFHSignature33、VFHSignature308、Narf36、BorderDescription、IntensityGradient、Histogram、PointWithScale、PointSurfel。
参见头文件:pcl/point_types.h

1、PointXYZ

PointXYZ是使用最常见的一个点数据类型,因为它只包含三维xyz坐标信息,这三个浮点数附加一个浮点数来满足存储对齐

union
{
    float data[4];
    struct
    {
        float x;
        float y;
        float z;
    };
};
2.PointXYZI

成员变量: float x, y, z, intensity;

PointXYZI是一个简单的XYZ坐标加intensity的point类型,理想情况下,这四个变量将新建单独一个结构体,并且满足存储对齐,然而,由于point的大部分操作会把data[4]元素设置成0或1(用于变换),不能让intensity与xyz在同一个结构体中,如果这样的话其内容将会被覆盖。例如,两个点的点积会把他们的第四个元素设置成0,否则该点积没有意义,等等。因此,对于兼容存储对齐,用三个额外的浮点数来填补intensity,这样在存储方面效率较低,但是符合存储对齐要求,运行效率较高。

union
{ 
    float data[4];
    struct
    {
       float x;
       float y;
       float z;
    };
};
union
{
    struct
    {
       float intensity;
     };
    float data_c[4];
};
3.PointXYZRGBA

成员变量: float x, y, z; uint32_t rgba;

除了rgba信息被包含在一个整型变量中,其它的和PointXYZI类似

union
{
    float data[4];
    struct
    {
       float x;
       float y;
       float z;
    };
};
union
{
   struct
   {
      uint32_t rgba;
   };
   float data_c[4];
};
4.PointXYZRGB

成员变量:float x, y, z, rgb;

除了rgb信息被包含在一个浮点型变量中,其它和PointXYZRGB类似。rgb数据被压缩到一个浮点数里的原因在于早期PCL是作为ROS项目的一部分来开发的,那里RGB数据是用浮点数来传送的,PCL设计者希望所有遗留代码会重新更改(在PCL 2.x中很可能这样做),可能取消此数据类型。

union
{
    float data[4];
    struct
    {
       float x;
       float y;
       float z;
    };
};
union
{
    struct
    {
       float rgb;
    };
    float data_c[4];
};

5.PointXY

成员变量:float x, y

简单的二维x-y point结构

struct
{
   float x;
   float y;
};

剩余point格式可以查看参考的博主介绍。pointcloud格式转载于
原文链接:https://blog.csdn.net/u013925378/article/details/83537844

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值