PCL:基于PCL绘制包围盒代码实现(2)
? ? ? ? 本博客基于pcl::MomentOflnertiaEstimation類獲取基于慣性矩(moment of inertia)與偏心率(eccentricity)的描述子,而該類的另一個功能就是提取有向包圍盒(OBB)和坐標軸對齊包圍盒(AABB),但是所提取的有向包圍盒OBB并不一定是最小的包圍盒。
主特征向量概念:
? ? ?? 一個矩陣可以有多個特征值,在這些特征值中,模最大的那個特征值即主特征值(對于實數陣即絕對值最大的特征值),主特征值對應的特征向量稱為主特征向量。(“主特征向量是指主特征值對應的特征向量而主特征值是指模最大(如果是實數的話就是絕對值最大)的特征值一般用冪迭代或者阿諾爾迪迭代等等可以求出主特征值和主特征向量”)
右手系原則:
? ? ? ? 右手系(right-hand system)是在空間中規定直角坐標系的方法之一。此坐標系中x軸,y軸和z軸的正方向是如下規定的:把右手放在原點的位置,使大姆指,食指和中指互成直角,把大姆指指向x軸的正方向,食指指向y軸的正方向時,中指所指的方向就是z軸的正方向。也可以按如下方法確定右手(左手)坐標系:如果當右手(左手)的大拇指指向第一個坐標軸(x軸)的正向,而其余手指以第二個軸(y軸)繞第一軸轉動的方向握緊,就與第三個軸(z軸)重合,就稱此坐標系為右手(左手)坐標系。
理論基礎:
? ? ? ? 該特征提取的核心思想如下:首先計算點云的協方差矩陣,然后提取特征值和特征向量,并且構造局部坐標系,以點云重心為坐標系原心,得到的特征向量已被歸一化,并且以主特征向量(Major Eigen Vector)作為X軸,最小特征值對應的特征向量(Minor Eigen Vector)作為Z軸,剩下的特征向量作為Y軸,符合右手坐標系原則。接下來進行迭代計算,每一次迭代,主特征向量即X軸按照循序繞其他兩個軸(YZ軸)旋轉,實現當中具體是外循環繞Y軸0到90度,內循環繞Z軸0到360度,每次添加一定的角度(用step_變量控制),最終的X軸正方向遍歷了整個Z軸負方向的半球離散方向,我們將這個旋轉主向量X軸作為當前軸。對于每個當前軸,計算一個慣性矩。另外,利用當前軸也可以計算一個偏心率,具體是將當前軸正向即旋轉后的X軸正向視為假設平面的法向量,然后將輸入點云投影到該假設平面上。接下來,根據獲取的投影就可以構造一個偏心率,其中長軸和短軸的數值是通過投影后點云的協方差矩陣得到。這樣就在每個當前軸上得到一個慣性矩和一個偏心率,迭代完成后得到兩個向量來存儲慣性矩和偏心率作為特征。類pcl::MomentOflnertiaEstimation不僅提供了對上述特征的獲取過程,并且可以輸出AABB(與坐標系本身的軸向對應),以及OBB,其中OBB就是局部坐標系對應的AABB。
PS:上述OBB對應的局部坐標系就是應用PCA找到的新的坐標系。AABB對應的是本身坐標系。
慣性矩:
慣性矩(moment of inertia of an area)是一個幾何量,通常被用作描述截面抵抗彎曲的性質。
偏心率:
? ? ?? 偏心率(Eccentricity)是用來描述圓錐曲線軌道形狀的數學量,定義為曲線到定點(焦點)的距離與到定直線(準線)的距離之比。對于橢圓,偏心率即為兩焦點間的距離(焦距,2c)和長軸長度(2a)的比值,即e=c/a(偏心率一般用e表示)。
圓錐曲線軌道形狀與偏心率的關系 。
代碼如下:
#include<iostream>
#include <vector>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/features/moment_of_inertia_estimation.h>
#include <pcl/visualization/cloud_viewer.h>
#include <boost/thread/thread.hpp>using namespace std;int main(int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());pcl::io::loadPCDFile("F:\\coutsaved\\test\\boxes\\pcd\\boxes.pcd", *cloud);//------------創建pcl::MomentOfInertiaEstimation 類-------------pcl::MomentOfInertiaEstimation <pcl::PointXYZ> feature_extractor;feature_extractor.setInputCloud(cloud);feature_extractor.compute();vector <float> moment_of_inertia;//存儲慣性矩的特征向量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);//AABB對應的左下角和右上角坐標feature_extractor.getOBB(min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);//OBB對應的相關參數feature_extractor.getEigenValues(major_value, middle_value, minor_value);//三個特征值feature_extractor.getEigenVectors(major_vector, middle_vector, minor_vector);//三個特征向量feature_extractor.getMassCenter(mass_center);//點云中心坐標//------------------可視化---------------------------------cout << "藍色的包圍盒為OBB,紅色的包圍盒為AABB" << endl;boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("基于慣性矩與偏心率的描述子"));viewer->setBackgroundColor(0, 0, 0);viewer->addCoordinateSystem(1.0);viewer->initCameraParameters();viewer->addPointCloud<pcl::PointXYZ>(cloud, pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(cloud, 0, 255, 0), "sample cloud");viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud");viewer->addCube(min_point_AABB.x, max_point_AABB.x, min_point_AABB.y, max_point_AABB.y, min_point_AABB.z, max_point_AABB.z, 1.0, 0.0, 0.0, "AABB");viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "AABB");//綠框viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, 0.5, "AABB");viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 3, "AABB");Eigen::Vector3f position(position_OBB.x, position_OBB.y, position_OBB.z);cout << "position_OBB: " << position_OBB << endl;cout << "mass_center: " << mass_center << endl;Eigen::Quaternionf quat(rotational_matrix_OBB);viewer->addCube(position, quat, max_point_OBB.x - min_point_OBB.x, max_point_OBB.y - min_point_OBB.y, max_point_OBB.z - min_point_OBB.z, "OBB");viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 0, 1, "OBB");//藍框viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, 0.5, "OBB");viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 3, "OBB");viewer->setRepresentationToWireframeForAllActors();pcl::PointXYZ center(mass_center(0), mass_center(1), mass_center(2));pcl::PointXYZ x_axis(major_vector(0) + mass_center(0), major_vector(1) + mass_center(1), major_vector(2) + mass_center(2));pcl::PointXYZ y_axis(middle_vector(0) + mass_center(0), middle_vector(1) + mass_center(1), middle_vector(2) + mass_center(2));pcl::PointXYZ z_axis(minor_vector(0) + mass_center(0), minor_vector(1) + mass_center(1), minor_vector(2) + mass_center(2));viewer->addLine(center, x_axis, 1.0f, 0.0f, 0.0f, "major eigen vector");viewer->addLine(center, y_axis, 0.0f, 1.0f, 0.0f, "middle eigen vector");viewer->addLine(center, z_axis, 0.0f, 0.0f, 1.0f, "minor eigen vector");cout << "size of cloud :" << cloud->points.size() << endl;cout << "moment_of_inertia :" << moment_of_inertia.size() << endl;cout << "eccentricity :" << eccentricity.size() << endl;while (!viewer->wasStopped()){viewer->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}return (0);
}
結果如下:
藍色框為OBB。
綠色框為AABB。
? ? ? ?
封裝函數:https://blog.csdn.net/u012010729/article/details/104115932
總結
以上是生活随笔為你收集整理的PCL:基于PCL绘制包围盒代码实现(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PCL:基于PCL绘制包围盒基础介绍(1
- 下一篇: QT:(2)Window10、VS15下