本文由CSDN点云侠原创,原文链接。爬虫自重,把自己当个人。博客长期更新,本文最近更新时间为:2023年8月10日。
1.概述
CloudCompare软件中默认的包围盒是轴向AABB包围盒,如下图的黄色立方体框所示,此包围盒并未与点云贴合。要想使包围盒与点云更贴合就需要计算点云的最小包围盒。
2.软件实现
'Tools——>Sand box——>Bounding box P.C.A. fit'
功能可以实现点云最小包围盒的计算。
如下图所示,为点云的最小包围盒。
3.算法源码
void MainWindow::doComputeBestFitBB()
{
if (QMessageBox::warning( this,
"This method is for test purpose only",
"Cloud(s) are going to be rotated while still displayed in their previous position! Proceed?",
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No ) != QMessageBox::Yes)
{
return;
}
//backup selected entities as removeObjectTemporarilyFromDBTree can modify them
ccHObject::Container selectedEntities = getSelectedEntities();
for (ccHObject *entity : selectedEntities) //warning, getSelectedEntites may change during this loop!
{
ccGenericPointCloud* cloud = ccHObjectCaster::ToGenericPointCloud(entity);
if (cloud && cloud->isA(CC_TYPES::POINT_CLOUD)) // TODO
{
CCLib::Neighbourhood Yk(cloud);
CCLib::SquareMatrixd covMat = Yk.computeCovarianceMatrix();
if (covMat.isValid())
{
CCLib::SquareMatrixd eigVectors;
std::vector<double> eigValues;
if (Jacobi<double>::ComputeEigenValuesAndVectors(covMat, eigVectors, eigValues, true))
{
Jacobi<double>::SortEigenValuesAndVectors(eigVectors, eigValues);
ccGLMatrix trans;
GLfloat* rotMat = trans.data();
for (unsigned j = 0; j < 3; ++j)
{
double u[3];
Jacobi<double>::GetEigenVector(eigVectors, j, u);
CCVector3 v(static_cast<PointCoordinateType>(u[0]),
static_cast<PointCoordinateType>(u[1]),
static_cast<PointCoordinateType>(u[2]));
v.normalize();
rotMat[j*4] = static_cast<float>(v.x);
rotMat[j*4+1] = static_cast<float>(v.y);
rotMat[j*4+2] = static_cast<float>(v.z);
}
const CCVector3* G = Yk.getGravityCenter();
assert(G);
trans.shiftRotationCenter(*G);
cloud->setGLTransformation(trans);
trans.invert();
//we temporarily detach entity, as it may undergo
//"severe" modifications (octree deletion, etc.) --> see ccPointCloud::applyRigidTransformation
ccHObjectContext objContext = removeObjectTemporarilyFromDBTree(cloud);
static_cast<ccPointCloud*>(cloud)->applyRigidTransformation(trans);
putObjectBackIntoDBTree(cloud,objContext);
entity->prepareDisplayForRefresh_recursive();
}
}
}
}
refreshAll();
}
4.相关代码
[1] PCL PCA构建点云包围盒
[2] matlab PCA构建点云OBB包围盒