注意:本例是调用PCL自己的接口,直接计算 AABB包围盒 + OBB包围盒 + 特征值 + 特征向量 + 惯性矩 + 偏心率。
使用该接口计算速度非常慢!!!工作中使用时,建议自己重写一次!!!
1.原理
(1)AABB包围盒(轴对齐包围盒):包围盒XYZ轴都与坐标轴对齐。AABB盒解释
(2)OBB包围盒(有向包围盒):包围盒XYZ轴都紧贴物体(比AABB包围盒描述物体更加的紧密)。OBB盒解释
(3)特征值和特征向量:在协方差矩阵那一块有讲解。特征值及特征向量解释
(4)惯性矩:不重要。惯性矩
(5)偏心率:不重要。偏心率
(6)质心:在点云场景中,一般被当做一块点云的中心点。质心解释
2.使用场景
(1)测试用
(2)如果自己写的算法计算不正确,直接调PCL的,
但注意:首先做计算的点云数据量要小,其次,最好先进行一次体素抽稀(保持点云形态结构)/法向量下采样(保存点云边缘),以降低数据量。再做计算。
3.注意事项
速度很慢。
4.关键函数
(1)获取AABB盒
pcl::PointXYZ aabbMin, aabbMax; // AABB盒最大xyz值,最小xyz值
bool bAabb = feature.getAABB(aabbMin, aabbMax); // 计算成功为true,否则为false
(2)获取OBB盒
pcl::PointXYZ obbMin, obbMax, pos; // obb盒最大xyz值,最小xyz值,中心点位置
Eigen::Matrix3f obbMat; // obb盒的旋转矩阵
bool bObb = feature.getOBB(obbMin, obbMax, pos, obbMat); // 计算成功为true,否则为false
(3)获取特征值
float majorValue, middleValue, minorValue; // 三特征值:主要、中间、次要
bool bEigenValue = feature.getEigenValues(majorValue, middleValue, minorValue); // 计算成功为true,否则为false
(4)获取特征向量
Eigen::Vector3f majorVector, middleVector, minorVector; // 三特征向量:主要、中间、次要
bool bEigenVector = feature.getEigenVectors(majorVector, middleVector, minorVector); // 计算成功为true,否则为false
(5)获取惯性矩
std::vector <float> momentOfInertia; // 计算惯性矩
bool bMomentOfInertia = feature.getMomentOfInertia(momentOfInertia); // 计算成功为true,否则为false
(6)获取偏心度
std::vector <float> eccentricity; // 计算偏心度
bool bEccentricity = feature.getEccentricity(eccentricity); // 计算成功为true,否则为false
(7)获取质心
Eigen::Vector3f mass_center; // 计算质心
bool bMassCenter = feature.getMassCenter(mass_center); // 计算成功为true,否则为false
5.代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/features/moment_of_inertia_estimation.h>
#include <pcl/features/moment_invariants.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>
int main()
{
/***************通过惯性矩和偏心率计算AABB、OBB等一系列值********************/
// 原始点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("D:/code/csdn/data/person4.pcd", *cloud_in); // 加载原始点云数据
pcl::MomentOfInertiaEstimation<pcl::PointXYZ> feature;
feature.setInputCloud(cloud_in);
feature.compute();
// 获取AABB盒
pcl::PointXYZ aabbMin, aabbMax; // AABB盒最大xyz值,最小xyz值
bool bAabb = feature.getAABB(aabbMin, aabbMax); // 计算成功为true,否则为false
// 获取OBB盒
pcl::PointXYZ obbMin, obbMax, pos; // obb盒最大xyz值,最小xyz值,中心点位置
Eigen::Matrix3f obbMat; // obb盒的旋转矩阵
bool bObb = feature.getOBB(obbMin, obbMax, pos, obbMat); // 计算成功为true,否则为false
// 获取特征值
float majorValue, middleValue, minorValue; // 三特征值:主要、中间、次要
bool bEigenValue = feature.getEigenValues(majorValue, middleValue, minorValue); // 计算成功为true,否则为false
// 获取特征向量
Eigen::Vector3f majorVector, middleVector, minorVector; // 三特征向量:主要、中间、次要
bool bEigenVector = feature.getEigenVectors(majorVector, middleVector, minorVector); // 计算成功为true,否则为false
// 获取惯性矩
std::vector <float> momentOfInertia; // 计算惯性矩
bool bMomentOfInertia = feature.getMomentOfInertia(momentOfInertia); // 计算成功为true,否则为false
// 获取偏心度
std::vector <float> eccentricity; // 计算偏心度
bool bEccentricity = feature.getEccentricity(eccentricity); // 计算成功为true,否则为false
// 获取质心
Eigen::Vector3f mass_center; // 计算质心
bool bMassCenter = feature.getMassCenter(mass_center); // 计算成功为true,否则为false
/****************打印********************/
std::cout << "AABB盒:" << bAabb << std::endl;
std::cout << "最小值:" << aabbMin << ";" << "最大值:" << aabbMax << ";" << std::endl;
std::cout << " " << std::endl;
std::cout << "OBB盒:" << bObb << std::endl;
std::cout << "最小值:" << obbMin << ";" << "最大值:" << obbMax << ";" << "位置:" << pos << ";" << "旋转矩阵:" << obbMat << ";" << std::endl;
std::cout << " " << std::endl;
std::cout << "特征值:" << bEigenValue << std::endl;
std::cout << "主要:" << majorValue << ";" << "中间:" << middleValue << ";" << "次要:" << minorValue << ";" << std::endl;
std::cout << " " << std::endl;
std::cout << "特征向量:" << bEigenVector << std::endl;
std::cout << "主要:" << majorVector << ";" << "中间:" << middleVector << ";" << "次要:" << minorVector << ";" << std::endl;
std::cout << " " << std::endl;
std::cout << "质心:" << bMassCenter << std::endl;
std::cout << "质心:" << mass_center << ";" << std::endl;
/****************展示********************/
// AABB点云
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("AABB"));
viewer->setBackgroundColor(1, 1, 1);
viewer->addCoordinateSystem(1.0);
viewer->addPointCloud<pcl::PointXYZ>(cloud_in, pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(cloud_in, 0, 255, 0), "AABB");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "AABB");
// AABB盒
viewer->addCube(aabbMin.x, aabbMax.x, aabbMin.y, aabbMax.y, aabbMin.z, aabbMax.z, 1.0, 0.0, 0.0, "AABB");
viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_REPRESENTATION, pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME, "AABB");
// OBB点云
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer1(new pcl::visualization::PCLVisualizer("OBBCloud"));
viewer1->setBackgroundColor(1, 1, 1);
viewer1->addCoordinateSystem(1.0);
viewer1->addPointCloud<pcl::PointXYZ>(cloud_in, pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(cloud_in, 0, 255, 0), "OBBCloud");
viewer1->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "OBBCloud");
// OBB盒子
const Eigen::Vector3f translation(pos.x, pos.y, pos.z);
const Eigen::Quaternionf rotation(obbMat);
viewer1->addCube(translation, rotation, obbMax.x - obbMin.x , obbMax.y - obbMin.y, obbMax.z - obbMin.z, "OBB");
viewer1->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_REPRESENTATION, pcl::visualization::PCL_VISUALIZER_REPRESENTATION_WIREFRAME, "OBB");
viewer1->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 0.0, 0.0, "OBB");
while (!viewer->wasStopped() || !viewer1->wasStopped())
{
viewer->spinOnce(100);
viewer1->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return (0);
}
6.结果展示
(1)计算得到的各项值
(2)AABB包围盒
(3)OBB包围盒