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/zh-hant/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

發表回復

登錄後才能評論