目录
一、概述
官网链接:Point Cloud Library (PCL): Module common
pcl_common中主要是包含了PCL库常用的公共数据结构和方法,比如PointCloud的类和许多用于表示点,曲面,法向量,特征描述等点的类型,用于计算距离,均值以及协方差,角度转换以及几何变化的函数。
pcl_common库包含大多数PCL库使用的公共数据结构和方法。核心数据结构包括PointCloud类和许多用于表示点、表面法线、RGB颜色值、特征描述符等的点类型。它还包含许多用于计算距离/范数、均值和协方差、角度转换、几何变换,等等。这个模块是不依赖其他模块的,所以是可以单独编译成功,单独编译出来可利用其中的数据结构自行开发,当然想单独提取出来编译时需要自行修改cmakeLists的。
1.1 common模块中的头文件
- angles.h 定义了标准的C接口的角度计算函数
- centriod.h 定义了中心点的估算以及协方差矩阵的计算
- commo.h 标准的C以及C++类,是其他common 函数的父类
- distance.h 定义标准的C接口用于计算距离
- file_io.h 定义了一些文件帮助写或者读方面的功能。
- random.h 定义一些随机点云生成的函数
- geometry.h 定义一些基本的几何功能的函数
- intersection.h 定义线与线相交的函数
- norm.h 定义了标准的C方法计算矩阵的正则化
- time.h 定义了时间计算的函数
- Point_types.h 定义了所有PCL实现的点云的数据结构的类型
二、 common模块中的基本函数
1、从弧度到角度
pcl::rad2deg(fllat alpha)
2、从角度到弧度
pcl::deg2rad(float aipha)
3、正则化角度在(-PI,PI)之间
pcl::normAngle(float alpha)
4、pcl::compute3DCentroid
函数的作用是计算输入点云的质心,并将结果存储在提供的 Eigen 矩阵中。具体来说,它计算点云中所有点的坐标平均值,并返回一个包含 x, y, z 坐标和齐次坐标(通常为 1.0)的四维向量。
pcl::compute3DCentroid (const pcl::PointCloud< PointT > &cloud, Eigen::Matrix< Scalar, 4, 1 > ¢roid)
5、计算给定的三维点云的协方差矩阵。
pcl::computeCovarianceMatrix (const pcl::PointCloud< PointT >
&cloud, const Eigen::Matrix< Scalar, 4, 1 > ¢roid,
Eigen::Matrix< Scalar, 3, 3 > &covariance_matrix)
6、计算正则化的3*3的协方差矩阵以及给定点云数据的中心点
pcl::computeMeanAndCovarianceMatrix (const pcl::PointCloud< PointT > &cloud, Eigen::Matrix< Scalar, 3, 3 > &covariance_matrix, Eigen::Matrix< Scalar, 4, 1 > ¢roid
7、利用一组点的指数对其进行一般的、通用的nD中心估计。
pcl::demeanPointCloud (const pcl::PointCloud< PointT > &cloud_in, const Eigen::Matrix< Scalar, 4, 1 > ¢roid, pcl::PointCloud< PointT > &cloud_out)
pcl::computeNDCentroid (const pcl::PointCloud< PointT > &cloud, Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > ¢roid)
8、计算两个向量之间的角度
pcl::getAngle3D (const Eigen::Vector4f &v1, const Eigen::Vector4f &v2, const bool in_degree=false)
9、同时计算给定点云数据的均值和标准方差
pcl::getMeanStd (const std::vector< float > &values, double &mean, double &stddev)
10、在给定边界的情况下,获取一组位于框中的点
pcl::getPointsInBox (const pcl::PointCloud< PointT > &cloud, Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt, std::vector< int > &indices)
11、给定点云数据中点与点之间的最大距离的值
pcl::getMaxDistance (const pcl::PointCloud< PointT > &cloud, const Eigen::Vector4f &pivot_pt, Eigen::Vector4f &max_pt)
12、获取给定点云中的在XYZ轴上的最大和最小值
pcl::getMinMax3D (const pcl::PointCloud< PointT > &cloud, PointT &min_pt, PointT &max_pt)
13、计算由三个点pa、pb和pc构成的三角形的外接圆半径。
pcl::getCircumcircleRadius (const PointT &pa, const PointT &pb, const PointT &pc)
14、获取点直方图上的最小值和最大值。
pcl::getMinMax (const PointT &histogram, int len, float &min_p, float &max_p)
15、根据给定的多边形的点云计算多边形的面积
pcl::calculatePolygonArea (const pcl::PointCloud< PointT > &polygon)
16、从Point_in把字段数据赋值到Point_out
pcl::copyPoint (const PointInT &point_in, PointOutT &point_out)
17、获取两条三维直线之间的最短三维线段
pcl::lineToLineSegment (const Eigen::VectorXf &line_a, const Eigen::VectorXf &line_b, Eigen::Vector4f &pt1_seg, Eigen::Vector4f &pt2_seg)
18、获取点到线的平方距离(由点和方向表示)
pcl::sqrPointToLineDistance (const Eigen::Vector4f &pt, const Eigen::Vector4f &line_pt, const Eigen::Vector4f &line_dir)
19、在给定的一组点中获得最大分段,并返回最小和最大点。
pcl::getMaxSegment (const pcl::PointCloud< PointT > &cloud, PointT &pmin, PointT &pmax)
20、确定最小特征值及其对应的特征向量
pcl::eigen22 (const Matrix &mat, typename Matrix::Scalar &eigenvalue, Vector &eigenvector)
21、确定对称半正定输入矩阵给定特征值对应的特征向量
pcl::computeCorrespondingEigenVector (const Matrix &mat, const typename Matrix::Scalar &eigenvalue, Vector &eigenvector)
22、确定对称半正定输入矩阵最小特征值的特征向量和特征值
pcl::eigen33 (const Matrix &mat, typename Matrix::Scalar &eigenvalue, Vector &eigenvector)
23、计算2x2矩阵的逆。
pcl::invert2x2 (const Matrix &matrix, Matrix &inverse)
24、计算3x3对称矩阵的逆。
pcl::invert3x3SymMatrix (const Matrix &matrix, Matrix &inverse)
24、计算3x3矩阵的行列式
pcl::determinant3x3Matrix (const Matrix &matrix)
26、获得唯一 的3D旋转,将Z轴旋转成(0,0,1)Y轴旋转成(0,1,0)并且两个轴是正交的。
pcl::getTransFromUnitVectorsZY (const Eigen::Vector3f &z_axis, const Eigen::Vector3f &y_direction, Eigen::Affine3f &transformation)
27、得到将origin转化为(0,0,0)的变换,并将Z轴旋转成(0,0,1)和Y方向(0,1,0)
pcl::getTransformationFromTwoUnitVectorsAndOrigin (const Eigen::Vector3f &y_direction, const Eigen::Vector3f &z_axis, const Eigen::Vector3f &origin, Eigen::Affine3f &transformation)
28、从给定的变换矩阵中提取欧拉角
pcl::getEulerAngles (const Eigen::Transform< Scalar, 3, Eigen::Affine > &t, Scalar &roll, Scalar &pitch, Scalar &yaw)
29、给定的转换中,提取XYZ以及欧拉角
pcl::getTranslationAndEulerAngles (const Eigen::Transform< Scalar, 3, Eigen::Affine > &t, Scalar &x, Scalar &y, Scalar &z, Scalar &roll, Scalar &pitch, Scalar &yaw)
30、从给定的平移和欧拉角创建转换矩阵
pcl::getTransformation (float x, float y, float z, float roll, float pitch, float yaw)
31、保存或者写矩阵到一个输出流中
pcl::saveBinary (const Eigen::MatrixBase< Derived > &matrix, std::ostream &file)
32、从输入流中读取矩阵
pcl::loadBinary (Eigen::MatrixBase< Derived > const &matrix, std::istream &file)
33、获取空间中两条三维直线作为三维点的交点。
pcl::lineWithLineIntersection (const Eigen::VectorXf &line_a, const Eigen::VectorXf &line_b, Eigen::Vector4f &point, double sqr_eps=1e-4)
34、获取指定字段的索引(即维度/通道)
pcl::getFieldIndex (const pcl::PCLPointCloud2 &cloud, const std::string &field_name)
35、获取给定点云中所有可用字段的列表
pcl::getFieldsList (const pcl::PointCloud< PointT > &cloud)
36、获取特定字段数据类型的大小(字节)。
pcl::getFieldSize (const int datatype)
37、连接 pcl::PCLPointCloud2类型的点云字段,用于将两个点云连接成一个新的点云。这在需要合并两个点云数据时非常有用
pcl::concatenatePointCloud (const pcl::PCLPointCloud2 &cloud1, const pcl::PCLPointCloud2 &cloud2, pcl::PCLPointCloud2 &cloud_out)
三、接口原理
3.1 正则化角度
用于将角度标准化。具体来说,这个函数将一个给定的角度 alpha
规范化到 [−𝜋,𝜋]范围内。在许多计算机视觉和点云处理的应用中,角度规范化是一个常见的需求。例如,两个角度的差异计算、角度比较、旋转等操作都需要角度在一定范围内表示,以确保计算的正确性和一致性。
假设有一个角度 alpha
,它的值可能超出 [−𝜋,𝜋] 的范围。通过调用pcl::normAngle(alpha)
,可以将这个角度变换到 [−𝜋,𝜋]范围内。
例如:
#include <iostream>
#include <pcl/common/common.h>
int main() {
float alpha = 4.0f; // 假设一个角度,单位是弧度
float normalized_angle = pcl::normAngle(alpha);
std::cout << "Original angle: " << alpha << std::endl;
std::cout << "Normalized angle: " << normalized_angle << std::endl;
return 0;
}
3.2 计算点云质心
点云质心(Centroid of a Point Cloud)是指点云中所有点的几何中心位置。它是一个向量,表示点云中所有点坐标的平均值。在三维空间中,点云质心的坐标通常由 𝑥x、𝑦y 和 𝑧z 三个分量组成。
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/common/centroid.h>
#include <Eigen/Dense>
#include <iostream>
int main() {
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 读取点云文件(假设有一个名为 "example.pcd" 的点云文件)
if (pcl::io::loadPCDFile<pcl::PointXYZ>("example.pcd", *cloud) == -1) {
PCL_ERROR("Couldn't read file example.pcd \n");
return -1;
}
Eigen::Vector4f centroid;
bool success = pcl::compute3DCentroid(*cloud, centroid);
if (success) {
std::cout << "Computed centroid: " << std::endl;
std::cout << "x: " << centroid[0] << std::endl;
std::cout << "y: " << centroid[1] << std::endl;
std::cout << "z: " << centroid[2] << std::endl;
std::cout << "w: " << centroid[3] << std::endl;
} else {
std::cerr << "Failed to compute centroid." << std::endl;
}
return 0;
}
3.3 三维点云的协方差矩阵
3.3.1什么是点云的协方差矩阵
在三维点云处理中,协方差矩阵(Covariance Matrix)是一个非常重要的数学工具,它用于描述点云的分布特性和内部结构。具体来说,协方差矩阵提供了以下几个方面的重要信息:
-
点云的分布和扩展方向: 协方差矩阵可以揭示点云在不同方向上的分布情况。通过对协方差矩阵进行特征值分解,可以得到点云的主方向和扩展性。特征值越大,说明点云在该方向上分布得越广。
-
点云的形状特性: 协方差矩阵的特征值和特征向量可以用于描述点云的几何形状。例如:
- 一个特征值显著大于另外两个特征值时,点云呈现出细长的形状(如线)。
- 两个特征值较大,第三个特征值较小时,点云呈现出平面形状。
- 三个特征值差不多相等时,点云在三维空间中均匀分布,接近球形。
-
点云的主成分分析(PCA): 通过计算点云的协方差矩阵并进行主成分分析(Principal Component Analysis, PCA),可以提取点云的主要方向和降维后的表示。在点云配准、特征提取和降噪等任务中,PCA是一种常用的方法。
3.3.2 计算方法
以下是使用PCL(Point Cloud Library)计算点云协方差矩阵的示例代码:
3.3.3 示例1
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/common/common.h>
#include <pcl/common/eigen.h>
#include <iostream>
int main() {
// 创建一个点云对象
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 读取点云文件(假设有一个名为 "example.pcd" 的点云文件)
if (pcl::io::loadPCDFile<pcl::PointXYZ>("example.pcd", *cloud) == -1) {
PCL_ERROR("Couldn't read file example.pcd \n");
return -1;
}
// 计算质心
Eigen::Vector4f centroid;
pcl::compute3DCentroid(*cloud, centroid);
// 计算协方差矩阵
Eigen::Matrix3f covariance_matrix;
pcl::computeCovarianceMatrix(*cloud, centroid, covariance_matrix);
// 输出协方差矩阵
std::cout << "Covariance matrix: \n" << covariance_matrix << std::endl;
return 0;
}
3.3.4 协方差矩阵进行特征值分解
协方差矩阵的特征值分解(Eigenvalue Decomposition)是将矩阵表示为其特征向量和特征值的过程。这在点云处理中非常有用,因为特征值和特征向量可以揭示点云的几何特性。以下是如何进行特征值分解的详细说明。
- 数学原理
- 几何意义
协方差矩阵经过特征值分解了之后,可以理解为重新找到了三个基向量,以及特征值对点云进行重新表达,此时正好可以通过特征值看出点云在三个基向量的分布方向。
3.3.5 特征值分解的意义
- 特征值:表示点云在对应特征向量方向上的分布方差。较大的特征值意味着点云在该方向上分布较广。
- 特征向量:表示点云的主要方向。特征向量对应于特征值,从大到小排序,依次表示点云的主方向、次主方向和最小方向。
以下是使用Eigen库对PCL点云协方差矩阵进行特征值分解的示例代码:
3.4.6 示例2
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/common/common.h>
#include <pcl/common/eigen.h>
#include <Eigen/Dense>
#include <iostream>
int main() {
// 创建一个点云对象
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 读取点云文件(假设有一个名为 "example.pcd" 的点云文件)
if (pcl::io::loadPCDFile<pcl::PointXYZ>("example.pcd", *cloud) == -1) {
PCL_ERROR("Couldn't read file example.pcd \n");
return -1;
}
// 计算质心
Eigen::Vector4f centroid;
pcl::compute3DCentroid(*cloud, centroid);
// 计算协方差矩阵
Eigen::Matrix3f covariance_matrix;
pcl::computeCovarianceMatrix(*cloud, centroid, covariance_matrix);
// 输出协方差矩阵
std::cout << "Covariance matrix: \n" << covariance_matrix << std::endl;
// 对协方差矩阵进行特征值分解
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(covariance_matrix);
Eigen::Matrix3f eigen_vectors = eigen_solver.eigenvectors();
Eigen::Vector3f eigen_values = eigen_solver.eigenvalues();
// 输出特征值和特征向量
std::cout << "Eigenvalues: \n" << eigen_values << std::endl;
std::cout << "Eigenvectors: \n" << eigen_vectors << std::endl;
return 0;
}
3.4 两条线之间的距离和位置
3.4.1 示例
#include <pcl/common/intersections.h>
#include <Eigen/Dense>
#include <iostream>
int main() {
// 定义第一条线的参数:一个点和方向向量
Eigen::VectorXf line_a(6);
line_a << 0.0, 0.0, 0.0, 1.0, 1.0, 0.0; // 点 (0, 0, 0) 和方向 (1, 1, 0)
// 定义第二条线的参数:一个点和方向向量
Eigen::VectorXf line_b(6);
line_b << 1.0, 0.0, 0.0, 0.0, 1.0, 1.0; // 点 (1, 0, 0) 和方向 (0, 1, 1)
// 用于存储输出的最近点对
Eigen::Vector4f pt1_seg, pt2_seg;
// 调用 lineToLineSegment 函数
bool result = pcl::lineToLineSegment(line_a, line_b, pt1_seg, pt2_seg);
if (result) {
std::cout << "The nearest points are:\n";
std::cout << "Point on line A: (" << pt1_seg[0] << ", " << pt1_seg[1] << ", " << pt1_seg[2] << ")\n";
std::cout << "Point on line B: (" << pt2_seg[0] << ", " << pt2_seg[1] << ", " << pt2_seg[2] << ")\n";
} else {
std::cerr << "Failed to find the nearest points.\n";
}
return 0;
}