PCL是一个模块化的C++模板库, 实现点云相关的获取、滤波、分割、配准、检索、特征提取、识别、追踪、曲面重建、可视化等。
要学习的正是PCL中的16个模块
- 01common 通用模块
- 02kdtree k维tree
- 03octree 八叉树
- 04search
- 05sample consensus 抽样一致性模块
- 06range-images深度图像
- 07tracking (此模块,没有官方示例代码)
- 08 io 输入输出
- 09 filters 滤波
- 10 features 特征
- 11 surface表面
- 12 segmentation分割
- 13 recognition识别
- 14 registration配准
- 15 visualization可视化
- 16 keypoints关键点
各模块之间的依赖关系如图所示。
PCL可用于机器人领域、逆向工程、激光遥感测量、虚拟现实和人际交互等。
在PCL中一个处理管道的基本接口程序如下:
1. 创建处理对象
2. 使用setInputCloud通过输入点云数据,处理模块
3. 设置算法相关参数
4. 调用计算(过滤、分割)得到输出
(管道本质上就是一个文件,前面的进程以写方式打开文件,后面的进程以读方式打开)
学习各个模块可以参考其他大佬的中文博客,结合代码体会学习。
# .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文件头必须用ASCII码来编码
·TYPE –用一个字符指定每一个维度的类型。现在被接受的类型有:
I –表示有符号类型int8(char)、int16(short)和int32(int);
U – 表示无符号类型uint8(unsigned char)、uint16(unsigned short)和uint32(unsigned int);
F –表示浮点类型。
WIDTH –用点的数量表示点云数据集的宽度
1)确定无序数据集的点云中点的个数;
2)确定有序点云数据集的宽度(一行中点的数目)。
·HEIGHT –用点的数目表示点云数据集的高度。
1)有序点云数据集的高度(行的总数);
2)无序数据集它被设置成1。
·DATA –指定存储点云数据的数据类型。从0.7版本开始,支持两种数据类型:ascii和二进制。
点云文件常用格式转换(pcd,txt,ply,obj,stl)_给算法爸爸上香的博客-CSDN博客_pcd转obj
在PCL中定义了大量的point类型,在以下文件中
common/include/pcl/impl/point_types.hpp
sensor_msgs::PointCloud2(ROS点云数据) 转成PointXYZI(PointT)
void elevatedCloudCallback(const sensor_msgs::PointCloud2::ConstPtr & input_cloud) // PointCloud2
{
// 将接收到的消息打印出来
// ROS_INFO( input_cloud->header);
pcl::PointCloud<PointT>::Ptr output_cloud(new pcl::PointCloud<PointT>()); // input_cloud转换成pcl数据类型laser_cloud
pcl::fromROSMsg(*input_cloud, *output_cloud);//转换成pcl数据类型
std::cout <<output_cloud->header<< std::endl;
std::cout << output_cloud->points[1].x<< std::endl;
}
将点云类型pcl::PointXYZI转换成pcl::PointXYZ
pcl::PointCloud<pcl::PointXYZI>::Ptr keypoints (new pcl::PointCloud<pcl::PointXYZI>);
keypoints_Harris( cloud_xyz, keypoints);
pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints_ptr(new pcl::PointCloud<pcl::PointXYZ>);
copyPointCloud (*keypoints , *keypoints_ptr);
实现类似pcl::PointCloud::Ptr和pcl::PointCloud的两个类相互转换
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudPtr(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ> cloud;
cloud = *cloudPtr;//由Ptr转变为另一种类型
cloudPtr = cloud.makeShared();//转变为Ptr类型
cloudPtr原本是一个指针,取值后就是PointCloud类型
将xyzrgb格式转换为xyz格式的点云
typedef是给某类取新名字
#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);
}
Point已经定义好了很多类型,根据需要再去查阅即可。