PCL(Point Cloud Library) (一)

一·基础使用:

PCL被分割成若干个模块库。最重要的一组已发布的PCL模块如下所示:

1.1 了解PCL中点云的定义:

  在PCL 1.X中基础的数据类型是点云,它是一个c++类:

  width(int):指定点云数据集的宽度,以点的数量为单位,宽度有两种含义:相对于有序点云数据和无序点云数据而言:

    1>对于无序点云数据集,宽度表示点云的总的点数量;

    2>对于有序点云数据集,宽度表示一行点云的点数量(列数);

  height(int):指定点云数据集的高度,以点的数量为单位,高度也有两种含义:

    1>对于无序点云数据集,高度将被设置为1;

    2>对于无序点云数据集,高度表示一列点云的点数量(行数);

  可以参照图像的矩阵存储方式。

example:

//有序点云
cloud.width = 64;
cloud.height = 64;
//无序点云
cloud.width = 4096;
cloud.height = 1;

  此外,is_dense(bool)字段也很重要:

    true:表示所有点的所有数据都是有限的;

    false:表示某些点的数据是Inf、NaN值;

1.2 如何自定义一个点云数据类型:

  在pcl_types.h头文件中你可以用到大多数你想要的点云数据类型;

  自定义一个PointXYZI点云类型:

struct EIGEN_ALIGN16 PointXYZI  // 强制执行SSE填充以实现正确的内存对齐
{
    PCL_ADD_POINT4D; // 添加xyz+另外一个变量 的首选方式
    float intensity;
    PCL_MAKE_ALIGNED_OPERATOR_NEW // 确保新的分配器是一致的
};
POINT_CLOUD_REGISTER_POINT_STRUCT(PointXYZI, // 这里设置 xyz + intensity 组合(as fields)
                                  (float,x,x)
                                  (float,y,y)
                                  (float,z,z)
                                  (float,intensity,intensity)
                                 )

 1.3 在CAMKE工程中使用:

##本机环境 设置方式
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(customPC)

set(CMAKE_CXX_STANDARD 14)
set(PCL_DIR "/home/h/ku/pcl-1.12.0/share/pcl-1.12/")

find_package(PCL 1.12.0 REQUIRED)

message(STATUS "--------PCL_VERSIONS: ${PCL_VERSION} ------")

include_directories(
    ${PCL_INCLUDE_DIRS}
)

link_directories(
    ${PCL_LIBRARY_DIRS}
    )

add_definitions(
    ${PCL_DEFINITIONS}
)

add_executable(PC customPC.cpp)
target_link_libraries(
    PC ${PCL_LIBRARIES}
)

参考链接:https://pcl.readthedocs.io/en/master/using_pcl_pcl_config.html#using-pcl-pcl-config

1.4 如何使用变换矩阵T[R|t] 转换点云

#

二.pcl::features类

  2.1 PCL特征使用近似的方法来计算查询点的最近邻居,使用快速的kd-tree查询。我们感兴趣的查询有两种类型:

    1>确定一个查询点的K邻域,用户指定参数,通常为8-20;

    2>确定一个查询点在半径为r的范围内的所有邻居点;

  2.2.pcl::features类 有两种输入数据的方法,对应四种应用模式:

     1>一个完整的点云数据集,通过setInputCloud (PointCloudConstPtr &)来传入。任何特征估计的子类都会尝试估计这个输入点云中每个点的特征。

        2>一个点云数据集的子集,通过setInputCloud (PointCloudConstPtr &)和setIndices (IndicesConstPtr &)来传入。任何特征估计的子类都会尝试估计给定索引列表中的每个索引对应的点的特征,如果没有给定索引列表,则会默认估计点云数据集中所有点的特征。
      附加可以调佣setSearchSurface(PointCloudConstPtr &) 指定要使用的相邻点集,通常适合使用在下采样后的点云。例如:

 n.setInputCloud(cloud_out); // cloud_out 表示已经经过下采样的点云
 n.setSearchSurface(cloud_info);// cloud_info 表示原始点云

   2.3.四种对应模式:

    setInputCloud()总是必须的。由setIndices()和setSearchSurface()组合成四种情况:

    1>!setIndices()& !setSearchSurface();

    2>setIndices()&  !setSearchSurface();

    3>!setIndices()& setSearchSurface ();

    4>setIndices()& setSearchSurface();

   2.4.法线估计

    在点云中估计平面法向量有两种方式:

    1>使用表面网格化技术,从获得的点云数据集中获得底层表面,然后从网格中计算出表面法线;

    2>使用近似值直接从点云数据集推断出表面法线;

    通常使用后者直接在点云中估计每个点的法向量。

    确定曲面上一个点的法线问题近似于估计与曲面相切的平面的法线问题,这又成为一个最小平方平面拟合估计问题。解决办法:估计表面法线的解决方案被简化为分析从查询点的最近邻居创建的协方差矩阵的特征向量和特征值(或PCA - 主成分分析)。

    第i个点Pi的协方差矩阵C:

    

    从一系列邻域点中估计协方差矩阵:

Eigen::Matrix3f cov_matrix;
Eigen::Vector4f xyz_centroid;

compute3DCentroid(cloud_info,xyz_centroid);
computeCovarianceMatrix(cloud_info,xyz_centroid,cov_matrix);

    此外,由于平面上法线方向的二义性,需要确定一个视点方向:有以下关系

    视点设置:

object.setViewPoint(x,y,z); // object是NormalEstimmation类的对象

    

    也可以给法线定向:

flipNormalTowardsViewpoint (const PointT &point, float vp_x, float vp_y, float vp_z, Eigen::Vector4f &normal);

    

posted @ 2023-06-06 10:39  scauhong  阅读(265)  评论(0)    收藏  举报