PCL 求八叉树的体素中心

news/2024/9/29 2:58:03/

目录

一、概述

1.1原理

1.2实现步骤

1.3应用场景

二、代码实现

2.1关键函数

2.1.1 八叉树构建

2.1.2 获取体素中心

2.2完整代码

三、实现效果


PCL点云算法汇总及实战案例汇总的目录地址链接:

PCL点云算法与项目实战案例汇总(长期更新)


一、概述

        在三维点云处理中,八叉树 是一种常用的数据结构,用来对三维空间进行递归划分。在 PCL 中,八叉树不仅可以用于搜索和变化检测,还可以用于计算每个体素(Voxel)的中心点,这对于空间划分、点云简化等应用十分有用。

1.1原理

        八叉树通过递归地将三维空间划分为多个子区域(体素),每个体素的边界由其最小和最大坐标定义,体素的中心是该最小和最大边界的中点。通过计算体素的中心点,可以获得该体素的空间位置,用于后续的点云处理。

1.2实现步骤

  1. 读取点云数据。
  2. 使用 pcl::octree::OctreePointCloud 创建八叉树并构建体素。
  3. 遍历八叉树中的每个体素,获取其最小和最大边界。
  4. 计算每个体素的中心点,存储并可视化体素中心点。

1.3应用场景

  1. 空间划分可视化:通过计算体素的中心点,展示空间的分布。
  2. 点云简化:使用体素中心点作为简化后的点云代表点。
  3. 邻域搜索:通过体素中心点快速找到空间中的目标区域。

二、代码实现

2.1关键函数

2.1.1 八叉树构建

        通过 pcl::octree::OctreePointCloud 构建八叉树,并根据点云数据生成体素。

#include <pcl/octree/octree_pointcloud.h>// 设置八叉树分辨率
float resolution = 0.05f;  // 分辨率决定了体素的大小
pcl::octree::OctreePointCloud<pcl::PointXYZ> octree(resolution);// 构建八叉树
octree.setInputCloud(cloud);  // cloud 是输入点云
octree.addPointsFromInputCloud();  // 生成八叉树

2.1.2 获取体素中心

        通过 getVoxelBounds 获取每个体素的最小和最大边界,并计算其中心点。

Eigen::Vector3f min_pt, max_pt;  // 用于存储体素的最小和最大边界
std::vector<Eigen::Vector3f> voxel_centers;  // 存储体素中心点// 遍历八叉树的每个叶子节点(体素)
for (auto it = octree.leaf_begin(); it != octree.leaf_end(); ++it)
{octree.getVoxelBounds(it, min_pt, max_pt);  // 获取体素的边界// 计算体素中心点Eigen::Vector3f center = (min_pt + max_pt) / 2.0f;voxel_centers.push_back(center);  // 将中心点存储起来
}

2.2完整代码

#include <iostream>
#include <vector>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/octree/octree_pointcloud.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <Eigen/Dense>// 封装的可视化函数
void visualizePointCloudsWithOctree(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,  // 原始点云pcl::PointCloud<pcl::PointXYZ>::Ptr voxel_center_cloud)  // 体素中心点云
{// 创建可视化窗口pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("Dual PointCloud Viewer"));// 设置视口1,显示原始点云int vp_1;viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp_1);  // 左侧窗口viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_1);  // 白色背景viewer->addText("Original PointCloud", 10, 10, "vp1_text", vp_1);  // 标题pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color_handler(cloud, 0, 255, 0);  // 绿色viewer->addPointCloud(cloud, cloud_color_handler, "original_cloud", vp_1);// 设置视口2,显示体素中心点云int vp_2;viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp_2);  // 右侧窗口viewer->setBackgroundColor(1.0, 1.0, 1.0, vp_2);  // 白色背景viewer->addText("Voxel Center PointCloud", 10, 10, "vp2_text", vp_2);  // 标题pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> voxel_center_color_handler(voxel_center_cloud, 255, 0, 0);  // 红色viewer->addPointCloud(voxel_center_cloud, voxel_center_color_handler, "voxel_center_cloud", vp_2);// 设置点的大小viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud", vp_1);viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 4, "voxel_center_cloud", vp_2);// 添加坐标系viewer->addCoordinateSystem(0.1);viewer->initCameraParameters();// 可视化循环while (!viewer->wasStopped()){viewer->spinOnce(100);}
}int main(int argc, char** argv)
{// -----------------------------读取点云数据---------------------------------pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPCDFile<pcl::PointXYZ>("bunny.pcd", *cloud) == -1){PCL_ERROR("Couldn't read the PCD file!\n");return -1;}// -----------------------------构建八叉树---------------------------------float resolution = 0.01f;  // 八叉树分辨率pcl::octree::OctreePointCloud<pcl::PointXYZ> octree(resolution);octree.setInputCloud(cloud);  // 设置输入点云octree.addPointsFromInputCloud();  // 生成八叉树// -----------------------------计算体素中心---------------------------------Eigen::Vector3f min_pt, max_pt;  // 用于存储体素的最小和最大边界pcl::PointCloud<pcl::PointXYZ>::Ptr voxel_center_cloud(new pcl::PointCloud<pcl::PointXYZ>);  // 存储体素中心点云// 遍历八叉树的每个叶子节点(体素)for (auto it = octree.leaf_begin(); it != octree.leaf_end(); ++it){octree.getVoxelBounds(it, min_pt, max_pt);  // 获取体素的边界pcl::PointXYZ point;point.x = (min_pt.x() + max_pt.x()) / 2.0f;  // 计算中心点point.y = (min_pt.y() + max_pt.y()) / 2.0f;point.z = (min_pt.z() + max_pt.z()) / 2.0f;voxel_center_cloud->points.push_back(point);  // 将中心点添加到点云}voxel_center_cloud->width = voxel_center_cloud->points.size();voxel_center_cloud->height = 1;voxel_center_cloud->is_dense = true;// -----------------------------可视化---------------------------------visualizePointCloudsWithOctree(cloud, voxel_center_cloud);return 0;
}

三、实现效果


http://www.ppmy.cn/news/1530672.html

相关文章

CentOS Linux教程(6)--CentOS目录

文章目录 1. 根目录2. cd目录切换命令3. CentOS目录介绍4. pwd命令介绍5. ls命令介绍5.1 ls5.2 ls -a5.3 ls -l 1. 根目录 Windows电脑的根目录是计算机(我的电脑)&#xff0c;然后C盘、D盘。 Linux系统的根目录是/&#xff0c;我们可以使用cd /进入根目录&#xff0c;然后使…

HarmonyOS鸿蒙开发实战(5.0)自定义安全键盘场景实践

鸿蒙HarmonyOS开发实战往期必看文章&#xff1a;&#xff08;持续更新......&#xff09; HarmonyOS NEXT应用开发性能实践总结&#xff08;持续更新......&#xff09; HarmonyOS NEXT应用开发案例实践总结合集&#xff08;持续更新......&#xff09; 一分钟了解”纯血版&…

Linux系统备份Gitee等云git所有仓库与所有分支的数字资产

思路&#xff1a; 1. ssh 配置 2. reps.txt 列出所有仓库名 3. exp的自动化备份脚本 -- 环境安装&#xff1a; exp需要依赖安装的文件&#xff0c;所以先执行下(以ubuntu为例)&#xff1a; sudo apt-get install expect 操作步骤&#xff1a; ssh 配置 1. 添加公钥至 …

CoreDNS实现跨集群service解析实践

CoreDNS实现跨集群service解析实践 背景介绍使用条件实现方案 CoreDNS是一款使用Go语言实现的专为云原生应用而生的DNS服务器。本文介绍CoreDNS在特定实际场景下的一种进阶使用实践&#xff0c;也许能为其他也在使用CoreDNS做服务发现的同学提供一些启发和思考。 背景介绍 在…

使用AI进行需求分析的案例研究

生成式 AI 的潜在应用场景似乎无穷无尽。虽然这令人兴奋&#xff0c;但也可能让人不知所措。因此&#xff0c;团队在使用这项技术时需要有明确的目标&#xff1a;关键是要明确生成式 AI 在团队工作中能产生哪些实质性影响。 在软件工程中&#xff0c;一个引人注目的应用场景是…

Python Web 面试题

1 Web 相关 get 和 post 区别 get&#xff1a; 请求数据在 URL 末尾&#xff0c;URL 长度有限制 请求幂等&#xff0c;即无论请求多少次&#xff0c;服务器响应始终相同&#xff0c;这是因为 get 至少获取资源&#xff0c;而不修改资源 可以被浏览器缓存&#xff0c;以便以后…

LeetCode 1014. 最佳观光组合 一次遍历数组,时间复杂度O(n)

1014. 最佳观光组合 today 1014 最佳观光组合 题目描述 给定正整数数组 A&#xff0c;A[i] 表示第 i 个观光景点的评分&#xff0c;评分由 1 到 10^6 之间的整数。 一对景点&#xff08;A[i], A[j]&#xff09;的观光总得分为 A[i] A[j] i - j&#xff0c;其中 i < j。…

付费进群V5版本首发源码

付费进群V5版本首发 最新分站大屏 更新三个模板 仿官方模板等等 最新防注入技术 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/89797314 更多资源下载&#xff1a;关注我。