在本教程中,我们将学习如何使用pcl::MomentOfInertiaEstimation
类来获取基于偏心率和惯性矩的描述符。这个类还允许提取云的轴对齐和定向的边界框。但请记住,提取的OBB不是最小可能的边界框。
#理论引入
特征提取方法的思想如下。首先计算点云的协方差矩阵,并提取其特征值和向量。你可以认为合成的特征向量是归一化的,总是形成右手坐标系(主特征向量代表X轴,次向量代表Z轴)。在下一步迭代过程发生。在每次迭代中,主要特征向量被旋转。旋转顺序总是相同的,并围绕其他特征向量执行,这为点云的旋转提供了不变性。今后,我们将把这个旋转的主矢量作为当前轴。
_images / eigen_vectors.png
计算每个当前轴的转动惯量。 此外,目前的轴也用于偏心计算。 出于这个原因,目前矢量被视为平面的法向量,并将输入云投影到其上。 之后,计算得到的投影的偏心率。
_images/projected_cloud.png
实现类还提供获取AABB和OBB的方法。面向对象的边界框沿着特征向量计算为AABB。
#代码
首先,您将需要本教程的点云。 这是截图中的一个。接下来,您需要做的是在您喜欢的任何编辑器中创建一个moment_of_inertia.cpp
文件,并在其中复制下面的代码:
#include <pcl/features/moment_of_inertia_estimation.h>
#include <vector>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <boost/thread/thread.hpp>
int main (int argc, char** argv)
{
if (argc != 2)
return (0);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());
if (pcl::io::loadPCDFile (argv[1], *cloud) == -1)
return (-1);
pcl::MomentOfInertiaEstimation <pcl::PointXYZ> feature_extractor;
feature_extractor.setInputCloud (cloud);
feature_extractor.compute ();
std::vector <float> moment_of_inertia;
std::vector <float> eccentricity;
pcl::PointXYZ min_point_AABB;
pcl::PointXYZ max_point_AABB;
pcl::PointXYZ min_point_OBB;
pcl::PointXYZ max_point_OBB;
pcl::PointXYZ position_OBB;
Eigen::Matrix3f rotational_matrix_OBB;
float major_value, middle_value, minor_value;
Eigen::Vector3f major_vector, middle_vector, minor_vector;
Eigen::Vector3f mass_center;
feature_extractor.getMomentOfInertia (moment_of_inertia);
feature_extractor.getEccentricity (eccentricity);
feature_extractor.getAABB (min_point_AABB, max_point_AABB);
feature_extractor.getOBB (min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
feature_extractor.getEigenValues (major_value, middle_value, minor_value);
feature_extractor.getEigenVectors (major_vector, middle_vector, minor_vector);
feature_extractor.getMassCenter (mass_center);
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
viewer->setBackgroundColor (