PCL

http://www.pointclouds.org/documentation/tutorials/#filtering-tutorial 每个模块点击进去后,有demo可以查看

源码编译打开option开关with_docs true,生成html文档

PCD

width、height绘制的网格中,height>1有序点云,height==1无序点云
sensor_origin_ 中心点
sensor_orientation_ 模型矩阵
point类型(体素类型),不同类型的点数据,加载出来的图像不同

  • PointXYZ 常用无色点云数据
  • PointXYZI i表示强度(intensity),距离越近强度越高
  • PointXYZRGB RGB颜色使用float存储,彩色点云

filed:concatenateFields拼接点云的数据坐标和法线数据等 PointCloud–>PointCloudNormal
点云数据合并 a+b=c点云

ply

pcl支持pcd和ply文件,meshlab支持ply

Segment

  • 欧几里德
std::vector<pcl::PointIndices> cluster_indices;
//欧式分割器
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
ec.setClusterTolerance (0.02); // 2cm
ec.setMinClusterSize (100);
ec.setMaxClusterSize (25000);
//搜索策略树
ec.setSearchMethod (tree);
ec.setInputCloud (cloud_filtered);
ec.extract (cluster_indices);
  • 区域生长
//一个点云团队列,用于存放聚类结果
std::vector <pcl::PointIndices> clusters;
//区域生长分割器
pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
//输入分割目标
reg.setSearchMethod (tree);
reg.setNumberOfNeighbours (30);
reg.setInputCloud (cloud);
//reg.setIndices (indices);
reg.setInputNormals (normals);
//设置限制条件及先验知识
reg.setMinClusterSize (50);
reg.setMaxClusterSize (1000000);
reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
reg.setCurvatureThreshold (1.0);
reg.extract (clusters);
  • ransac随机抽样一致算法(类似最小而乘法的拟合算法,抗燥能力较强),存在不确定性(不一定拟合),为了提高准确度需要提高迭代次数
pcl::SACSegmentation<pcl::PointXYZ> seg; 
seg.setOptimizeCoefficients (true);
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
sac.setMaxIterations(100);                //默认50
seg.setDistanceThreshold (0.01);
seg.setInputCloud (cloud);
seg.segment (*inliers, *coefficients);
  • 分割后遍历各个子集
for (std::vector<pcl::PointIndices>::const_iterator it = clusters.begin(); it != clusters.end(); it++)
    {    
        pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZRGB>);
        for (std::vector<int>::const_iterator itor = it->indices.begin(); itor != it->indices.end(); itor++)
        {
            cloud_cluster->points.push_back(colored_cloud->points[*itor]); //*
            cloud_cluster->width = cloud_cluster->points.size();
            cloud_cluster->height = 1;
            cloud_cluster->is_dense = true;
...上面方法较笨或者

pcl::ExtractIndices<pcl::PointXYZRGB> extra;
extra.setInputCloud(cloud);
extra.setIndices(clusters[i]);
extra.filter(*out);

ModelCoefficients平面参数

  • 点云提取(保留或者删除点云,通过SACSegmentation后循环去掉平面,然后欧几里得聚类算法分类识别物体)
pcl::ExtractIndices<pcl::PointXYZRGB>ext;
ext.setInputCloud(sor_cloud);
ext.setIndices(inliner);
ext.setNegative(true);    //删除目标点云或保留
ext.filter(*ext_cloud_rest);

Common

PosesFromMatches姿态估计
getMinMax包围和估计

Filter

过滤点云(下采样),保持形状不变减少点云数量
VoxelGrid体素网格,可以做下采样
setLeafSize设置体素的过滤大小m为单位,0.01(1cm^3)

pcl::VoxelGrid<pcl::PCLPointCloud2> sor;  //创建滤波对象
sor.setInputCloud (cloud);            //设置需要过滤的点云给滤波对象
sor.setLeafSize (0.01f, 0.01f, 0.01f);  //设置滤波时创建的体素体积为1cm的立方体
sor.filter (*cloud_filtered);           //执行滤波处理,存储输出

PassThrough过滤或保留不再给定范围内的值

pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud (cloud);            //设置输入点云
pass.setFilterFieldName ("z");          //设置过滤时所需要点云类型的Z字段
pass.setFilterLimits (0.0, 1.0);          //设置在过滤字段的范围
//pass.setFilterLimitsNegative (true);     //设置保留范围内还是过滤掉范围内
pass.filter (*cloud_filtered);             //执行滤波,保存过滤结果在cloud_filtered

UniformSampling 均匀采样

pcl::UniformSampling<pcl::PointXYZ> filter;
filter.setInputCloud(cloud);
filter.setRadiusSearch(0.01f);
pcl::PointCloud<int> keypointIndices;
filter.compute(keypointIndices);
pcl::copyPointCloud(*cloud, keypointIndices.points, *filteredCloud);

StatisticalOutlierRemoval区域范围内的点是否离群(标准差方式判断离群点)

pcl::PointCloud<pcl::PointXYZRGB>::Ptr sor_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB>sor;
sor.setMeanK(10);     //计算标准差的区域点个数
sor.setInputCloud(vox_cloud);
sor.setStddevMulThresh(0.02);
sor.filter(*sor_cloud);

RadiusOutlierRemoval半径范围内必须要有足够点,否则删除
ConditionalRemoval,条件过滤,去掉部相关的条件(颜色筛选)

//上面的就是创建点云数据
pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());   //创建条件定义对象
range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 0.0)));
range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT,800)));
//创建滤波器并用条件定义对象初始化
pcl::ConditionalRemoval<pcl::PointXYZ> condrem(range_cond);
condrem.setInputCloud(cloud);
condrem.setKeepOrganized(true);
condrem.filter(*cloud_filtered);

Feature

  • 模型边界 BoundaryEstimation,模型
Eigen::Vector4f pcaCentroid;
	Eigen::Matrix3f covariance;
    pcl::compute3DCentroid(*scene, pcaCentroid);
    pcl::computeCovarianceMatrixNormalized(*scene, pcaCentroid, covariance);  //协方差矩阵
    Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(covariance, Eigen::ComputeEigenvectors);
    Eigen::Matrix3f eigenVectorsPCA = eigen_solver.eigenvectors();
    //viewer.addCoordinateSystem(1,pcaCentroid.x(),pcaCentroid.y(),pcaCentroid.z());
    viewer.addCube(Eigen::Vector3f(tmpCenter.x,tmpCenter.y,tmpCenter.z),Eigen::Quaternionf(eigenVectorsPCA),width,height,depth,"bbox");
  • 法线估计
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
//创建法线估计估计向量
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
ne.setInputCloud (cloud);
//创建一个空的KdTree对象,并把它传递给法线估计向量
//基于给出的输入数据集,KdTree将被建立
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
ne.setSearchMethod (tree);
//使用半径在查询点周围3厘米范围内的所有临近元素
ne.setRadiusSearch (0.03);
//计算特征值
ne.compute (*cloud_normals);
  • 点特征直方图PFH描述

查找特征点云P,得到P点最临近元素,对领域内的每对点,计算三个角度特征参数,输出直方图,点区域特征和权重

python pcre模式 pythonpcl_python

//其他相关操作
pcl::PointCloud<pcl::PointXYZ>::Ptrcloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptrnormals(new pcl::PointCloud<pcl::Normal>());
//打开点云文件估计法线等
//创建PFH估计对象pfh,并将输入点云数据集cloud和法线normals传递给它
pcl::PFHEstimation<pcl::PointXYZ,pcl::Normal,pcl::PFHSignature125> pfh;
pfh.setInputCloud(cloud);
pfh.setInputNormals(normals);
//如果点云是类型为PointNormal,则执行pfh.setInputNormals (cloud);
//创建一个空的kd树表示法,并把它传递给PFH估计对象。
//基于已给的输入数据集,建立kdtree
pcl::KdTreeFLANN<pcl::PointXYZ>::Ptrtree(new pcl::KdTreeFLANN<pcl::PointXYZ>());
pfh.setSearchMethod(tree);
//输出数据集
pcl::PointCloud<pcl::PFHSignature125>::Ptrpfhs(new pcl::PointCloud<pcl::PFHSignature125>());
//使用半径在5厘米范围内的所有邻元素。
//注意:此处使用的半径必须要大于估计表面法线时使用的半径!!!
pfh.setRadiusSearch(0.05);
//计算pfh特征值
pfh.compute(*pfhs);

Surface

三维重建
霍夫曼变换(Hough)、哈里斯角点(Harris)

Sample Consensus

单个模型拟合去噪,RANSAC算法(带阈值的最小二乘法)

KdTree

查找特征点附近的K个临近点。由一个有其他约束条件的二叉树组成。

OCTree

查找临近点。描述三维坐标系中的8个象限。

# register(姿态估计)

  • ICP算法

注册模型,匹配模型姿态估计(最小二乘法计算变换矩阵)
Icp算法,点集对点集配准方法,通过算法不断迭代,找到模型的匹配姿态。

IterativeClosestPoint<PointXYZ, PointXYZ> icp;
icp.setInputCloud (cloud_source);
icp.setInputTarget (cloud_target);
icp.setMaxCorrespondenceDistance (0.05);
icp.setMaximumIterations (50);
icp.setTransformationEpsilon (1e-8);
icp.setEuclideanFitnessEpsilon (1);
icp.align (cloud_source_registered);
Eigen::Matrix4f transformation = icp.getFinalTransformation ();

recongnise

Linemod,目标检测算法

LineRGBD<PointXYZRGBA> line_rgbd;
std::vector<LineRGBD<PointXYZRGBA>::Detection> detections;
line_rgbd.setGradientMagnitudeThreshold (10.0);
line_rgbd.setDetectionThreshold (0.75);
line_rgbd.loadTemplates ("*.lmt");   //输入训练好的lmt文件
line_rgbd.setInputCloud (cloud);
line_rgbd.setInputColors (cloud);
line_rgbd.detect (detections);

ORK(github上面object recognise kitchen)

visualization

pcl::visualization对VT(OPenGL的封装)K做封装,包含pcd点云显示等功能

pcl::visualization::CloudViewer cloudView("test");
cloudView.showCloud    //可以直接更新显示

pcl::visualization::PCLVisualizer cloudView2("test");
cloudView2.addPointCloud(cloud);   //添加点云
cloudView2.spinOnce()   //更新显示   spin阻塞

Eigen编译错误

EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE eigen类型不匹配会,通过编译宏断言设置错误
Eigen::Vector3f(pcl::PointRGB.getVector3fMap())

点做旋转变换,注意旋转矩阵的左乘和右乘

python-pcl

git clone https://github.com/strawlab/python-pcl.git
执行./build.sh即可,执行过程中出现错误,需要修改setup.py文件的pcl版本,vtk6.3版本,提示libtk*.so找不到,在setup.py中删除即可(和我安装的apt install libvtk6-dev不同)
最后:

拷贝pcl文件夹下的所有文件到python的site-packges/pcl下(setup.py不拷贝这些文件,否则python import pcl智能在python-pcl源码目录下可用)