obb包围盒详解

一、obb包围盒算法

obb包围盒即是用一个有向盒子框住物体,这个盒子有三个轴(长轴、中轴、短轴),轴上的长度叫做半长宽高。obb包围盒的算法是根据物体的点云数据生成obb包围盒,而点云数据是物体表面上的点的集合。obb包围盒算法的具体步骤如下:

1. 将点云数据转化为本体坐标系下的点集(即减去物体中心点坐标)

void processPointCloud(const pcl::PointCloud::Ptr &cloud, pcl::PointCloud::Ptr &outputCloud) {
    Eigen::Vector4f centroid;
    pcl::compute3DCentroid(*cloud, centroid);
    Eigen::Matrix4f transformationMatrix = Eigen::Matrix4f::Identity();
    transformationMatrix(0,3) = -centroid(0);
    transformationMatrix(1,3) = -centroid(1);
    transformationMatrix(2,3) = -centroid(2);
    pcl::transformPointCloud(*cloud, *outputCloud, transformationMatrix);
}

2. 进行主分量分析(PCA)得到obb包围盒的长轴、中轴、短轴和半长宽高

pcl::PCA pca;
pca.setInputCloud(cloud);
Eigen::Matrix3f eigenVectorsPCA = pca.getEigenVectors();
Eigen::Vector3f eigenValuesPCA = pca.getEigenValues();
Eigen::Matrix4f transformationMatrix = Eigen::Matrix4f::Identity();
transformationMatrix.block(0,0) = eigenVectorsPCA.transpose();
transformationMatrix(0,3) = pca.getMean()(0);
transformationMatrix(1,3) = pca.getMean()(1);
transformationMatrix(2,3) = pca.getMean()(2);
// 半长宽高
float boxLength = max(max(maxX - minX, maxY - minY), maxZ - minZ);
float boxWidth = min(min(maxX - minX, maxY - minY), maxZ - minZ);
float boxHeight = boxLength * (eigenValuesPCA(0) / eigenValuesPCA(2));

二、obb包围盒算法实现

上述obb包围盒算法的具体实现需要使用到第三方库pcl,pcl包含了很多点云相关的算法,因此可以很方便地生成obb包围盒。而obb包围盒可视化的最直观的方式是通过vtk库,代码实现如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));

void visualizeOBB(pcl::PointCloud::Ptr cloud, float boxLength, float boxWidth, float boxHeight) {
    vtkSmartPointer cube = vtkSmartPointer::New();
    cube->SetXLength(boxLength);
    cube->SetYLength(boxWidth);
    cube->SetZLength(boxHeight);
    cube->SetCenter(0, 0, 0);
    vtkSmartPointer cubeMapper = vtkSmartPointer::New();
    cubeMapper->SetInputConnection(cube->GetOutputPort());
    vtkSmartPointer cubeActor = vtkSmartPointer::New();
    cubeActor->SetMapper(cubeMapper);
    vtkSmartPointer transform = vtkSmartPointer::New();
    transform->Translate(cloud->at(0).x, cloud->at(0).y, cloud->at(0).z);
    vtkSmartPointer transformFilter = vtkSmartPointer::New();
    transformFilter->SetInputConnection(cube->GetOutputPort());
    transformFilter->SetTransform(transform);
    transformFilter->Update();
    cubeMapper->SetInputConnection(transformFilter->GetOutputPort());
    cubeActor->SetMapper(cubeMapper);
    viewer->addActor(cubeActor);
    viewer->setBackgroundColor(0.1, 0.1, 0.1);
    viewer->resetCamera();
    viewer->spin();
}

三、obb包围盒碰撞检测

obb包围盒在游戏、物理引擎等领域中广泛应用,碰撞检测是obb包围盒的一个常见应用。obb包围盒间的碰撞检测可以转化为obb包围盒间的距离计算问题,距离为0即为碰撞,例如obb1和obb2两个包围盒间的距离计算公式为:

float distance = sqrt((obj2.position.x - obj1.position.x) * eigenVectorsPCA(0, 0) +
                       (obj2.position.y - obj1.position.y) * eigenVectorsPCA(0, 1) + 
                       (obj2.position.z - obj1.position.z) * eigenVectorsPCA(0, 2)) - (boxLength1 + boxLength2) / 2;

四、obb包围盒中心点、半长宽高

obb包围盒有三个重要参数:中心点、半长宽高。中心点是有向盒子的中点,通常是通过点云数据计算得到的物体几何中心点,即计算点云数据点坐标的平均值得到。半长宽高是obb包围盒三个轴上的长度,因此要根据PCA得到obb包围盒的长轴、中轴、短轴和半长宽高。

Eigen::Vector4f centroid;
pcl::compute3DCentroid(*cloud, centroid);
float centerX = centroid(0);
float centerY = centroid(1);
float centerZ = centroid(2);
float boxLength = max(max(maxX - minX, maxY - minY), maxZ - minZ);
float boxWidth = min(min(maxX - minX, maxY - minY), maxZ - minZ);
float boxHeight = boxLength * (eigenValuesPCA(0) / eigenValuesPCA(2));

五、aabb包围盒

与obb包围盒相对应的是aabb包围盒(轴对齐包围盒,也叫AABB包围盒)。aabb包围盒与obb包围盒最大的区别是aabb包围盒的轴与坐标轴重合,因而如下代码即可计算出物体的aabb包围盒:

float minX, minY, minZ, maxX, maxY, maxZ;
pcl::getMinMax3D(*cloud, minX, minY, minZ, maxX, maxY, maxZ);
Eigen::Vector4f centroid;
pcl::compute3DCentroid(*cloud, centroid);
float centerX = centroid(0);
float centerY = centroid(1);
float centerZ = centroid(2);
float boxLength = maxX - minX;
float boxWidth = maxY - minY;
float boxHeight = maxZ - minZ;

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/159881.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-11-20 00:16
下一篇 2024-11-20 00:16

相关推荐

  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Python安装OS库详解

    一、OS简介 OS库是Python标准库的一部分,它提供了跨平台的操作系统功能,使得Python可以进行文件操作、进程管理、环境变量读取等系统级操作。 OS库中包含了大量的文件和目…

    编程 2025-04-25
  • git config user.name的详解

    一、为什么要使用git config user.name? git是一个非常流行的分布式版本控制系统,很多程序员都会用到它。在使用git commit提交代码时,需要记录commi…

    编程 2025-04-25
  • Python输入输出详解

    一、文件读写 Python中文件的读写操作是必不可少的基本技能之一。读写文件分别使用open()函数中的’r’和’w’参数,读取文件…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • MPU6050工作原理详解

    一、什么是MPU6050 MPU6050是一种六轴惯性传感器,能够同时测量加速度和角速度。它由三个传感器组成:一个三轴加速度计和一个三轴陀螺仪。这个组合提供了非常精细的姿态解算,其…

    编程 2025-04-25
  • Java BigDecimal 精度详解

    一、基础概念 Java BigDecimal 是一个用于高精度计算的类。普通的 double 或 float 类型只能精确表示有限的数字,而对于需要高精度计算的场景,BigDeci…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25
  • 详解eclipse设置

    一、安装与基础设置 1、下载eclipse并进行安装。 2、打开eclipse,选择对应的工作空间路径。 File -> Switch Workspace -> [选择…

    编程 2025-04-25

发表回复

登录后才能评论