PCL学习八叉树

建立空间索引在点云数据处理中有着广泛的应用,常见的空间索引一般 是自顶而下逐级划分空间的各种空间索引结构,比较有代表性的包括BSP树,KD树,KDB树,R树,四叉树,八叉树等索引结构,而这些结构中,KD树和八叉树使用比较广泛

八叉树(Octree)是一种用于描述三维空间的数据结构八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点,这八个子节点所表示的体积元素加在一起就等于父节点的体积。一般中心点作为节点的分叉中心。

 

百度百科释义八叉树(Octree)的定义是:若不为空树的话,树中任一节点的子节点恰好只会有八个,或零个,也就是子节点不会有0与8以外的数目。那么,这要用来做什么?想象一个立方体, 我们最少可以切成多少个相同等分的小立方体?答案就是8个。再想象我们有一个房间,房间里某个角落藏着一枚金币,我们想很快的把金币找出来,聪明的你会怎 么做?我们可以把房间当成一个立方体,先切成八个小立方体,然后排除掉没有放任何东西的小立方体,再把有可能藏金币的小立方体继续切八等份….如此下去, 平均在Log8(房间内的所有物品数)的时间内就可找到金币。因此,八叉树就是用在3D空间中的场景管理,可以很快地知道物体在3D场景中的位置,或侦测 与其它物体是否有碰撞以及是否在可视范围内。

实现八叉树的原理 

  (1). 设定最大递归深度。

  (2). 找出场景的最大尺寸,并以此尺寸建立第一个立方体。

  (3). 依序将单位元元素丢入能被包含且没有子节点的立方体。

  (4). 若没达到最大递归深度,就进行细分八等份,再将该立方体所装的单位元元素全部分担给八个子立方体。

  (5). 若发现子立方体所分配到的单位元元素数量不为零且跟父立方体是一样的,则该子立方体停止细分,因为跟据空间分割理论,细分的空间所得到的分配必定较少,若是一样数目,则再怎么切数目还是一样,会造成无穷切割的情形。

  (6). 重复3,直到达到最大递归深度。

八叉树的逻辑结构如下:

假设要表示的形体V可以放在一个充分大的正方体C内,C的边长为2n,形体V=C,它的八叉树可以用以下的递归方法来定义:八 叉树的每个节点与C的一个子立方体对应,

树根与C本身相对应,如果V=C,那么V的八叉树仅有树根,如果V≠C,则将C等分为八个子立方体,每个子立方体 与树根的一个子节点相对应。只要某个子立方体不是完

全空白或完全为V所占据,就要被八等分,从而对应的节点也就有了八个子节点。这样的递 归判断、分割一直要进行到节点所对应的立方体或是完全空白,或是完全为V占

据,或是其大小已是预先定义的体素大小,并且对它与V之交作一定的“舍入”,使 体素或认为是空白的,或认为是V占据的。

                              
                                                                                               

PCL中Octree模块及类介绍

pcl::octree::Octree2BufBase< LeafContainerT, BranchContainerT >    实现了同时存储管理两个八叉树与内存中,可以十分高效的实现八叉树的建立管理等操作,并且节点实现对临近树节点的结构的探测,对应到空间点云,其就可以对空间曲面的动态变化进行探测,在进行空间动态变化探测中非常有用

Public Types

typedef Octree2BufBase< LeafContainerT, BranchContainerT > OctreeT
typedef BufferedBranchNode< BranchContainerT > BranchNode
typedef OctreeLeafNode< LeafContainerT > LeafNode
typedef BranchContainerT BranchContainer
typedef LeafContainerT LeafContainer
typedef OctreeDepthFirstIterator< OctreeTIterator
typedef const OctreeDepthFirstIterator< OctreeTConstIterator
typedef OctreeLeafNodeIterator< OctreeTLeafNodeIterator
typedef const OctreeLeafNodeIterator< OctreeTConstLeafNodeIterator
typedef OctreeDepthFirstIterator< OctreeTDepthFirstIterator
typedef const OctreeDepthFirstIterator< OctreeTConstDepthFirstIterator
typedef OctreeBreadthFirstIterator< OctreeTBreadthFirstIterator
typedef const OctreeBreadthFirstIterator< OctreeTConstBreadthFirstIterator

 

Public Member Functions

void setMaxVoxelIndex (unsigned int max_voxel_index_arg)
 Set the maximum amount of voxels per dimension. 设置在各个维度的最大的体素个数
void setTreeDepth (unsigned int depth_arg)
 Set the maximum depth of the octree. 设置八叉树的深度,需要在初始化八叉树时设置
unsigned int getTreeDepth () const
 Get the maximum depth of the octree  获得八叉树的深度
LeafContainerT * createLeaf (unsigned int idx_x_arg, unsigned int idx_y_arg, unsigned int idx_z_arg)
 Create new leaf node at (idx_x_arg, idx_y_arg, idx_z_arg). 创建叶节点
LeafContainerT * findLeaf (unsigned int idx_x_arg, unsigned int idx_y_arg, unsigned int idx_z_arg)
 Find leaf node at (idx_x_arg, idx_y_arg, idx_z_arg). 找出页节点
bool existLeaf (unsigned int idx_x_arg, unsigned int idx_y_arg, unsigned int idx_z_arg) const
 Check for the existence of leaf node at (idx_x_arg, idx_y_arg, idx_z_arg). 判断在(idx_x_arg, idx_y_arg, idx_z_arg)对应的叶子节点是否存在
void removeLeaf (unsigned int idx_x_arg, unsigned int idx_y_arg, unsigned int idx_z_arg)
 Remove leaf node at (idx_x_arg, idx_y_arg, idx_z_arg). 移除在(。。。)的节点
std::size_t getLeafCount () const
 Return the amount of existing leafs in the octree.返回八叉树叶子的个数
std::size_t getBranchCount () const 
 Return the amount of existing branches in the octree. 返回八叉树分支的个数
void deleteTree ()
 Delete the octree structure and its leaf nodes. 删除八叉树结构包括节点
void deletePreviousBuffer ()
 Delete octree structure of previous buffer. 删除另一个缓存区对应的八叉树的结构及其字节点
void deleteCurrentBuffer ()
 Delete the octree structure in the current buffer删除当前缓存区对应的八叉树的结构及其字节点
void switchBuffers ()
 Switch buffers and reset current octree structure. 交换缓存区中对应的八叉树的结构和其叶子节点
void serializeTree (std::vector< char > &binary_tree_out_arg, bool do_XOR_encoding_arg=false)
 Serialize octree into a binary output vector describing its branch node structure.
void serializeTree (std::vector< char > &binary_tree_out_arg, std::vector< LeafContainerT * > &leaf_container_vector_arg, bool do_XOR_encoding_arg=false)
 Serialize octree into a binary output vector describing its branch node structure and and push all DataT elements stored in the octree to a vector.串行化输出八叉树结构
void serializeLeafs (std::vector< LeafContainerT * > &leaf_container_vector_arg)
 Outputs a vector of all DataT elements that are stored within the octree leaf nodes.
void serializeNewLeafs (std::vector< LeafContainerT * > &leaf_container_vector_arg)
 Outputs a vector of all DataT elements from leaf nodes, that do not exist in the previous octree buffer
void deserializeTree (std::vector< char > &binary_tree_in_arg, bool do_XOR_decoding_arg=false)
 Deserialize a binary octree description vector and create a corresponding octree structure.
void deserializeTree (std::vector< char > &binary_tree_in_arg, std::vector< LeafContainerT * > &leaf_container_vector_arg, bool do_XOR_decoding_arg=false)
 Deserialize a binary octree description and create a corresponding octree structure.

 更多详细查看  docs.pointclouds.org/trunk/classpcl_1_1octree_1_1_octree2_buf_base.html#aeea7ecfd6ebe82e93d3c7bb869355502

应用实例

点云由海量的数据集组成,这些数据集通过距离 颜色  法线  等附加信息来描述空间的三维点,此外,点云还能易非常高的速度被创建出来,因此需要占用相当大的存储资源,一旦点云需要存储或者通过速率受限制的通信信道进行传输,提供针对这种数据的压缩方法就变得十分有用,PCL 提供了点云的压缩功能,它允许编码压缩所有类型的点云,

点云压缩示意图:

                                                             octreeCompression

新建工程ch3_2,新建文件 point_cloud_compression.cpp

#include <pcl/point_cloud.h>                         // 点云类型
#include <pcl/point_types.h>                          //点数据类型
#include <pcl/io/openni_grabber.h>                    //点云获取接口类
#include <pcl/visualization/cloud_viewer.h>            //点云可视化类

#include <pcl/compression/octree_pointcloud_compression.h>   //点云压缩类

#include <stdio.h>
#include <sstream>
#include <stdlib.h>#ifdef WIN32
# define sleep(x) Sleep((x)*1000)
#endifclass SimpleOpenNIViewer
{
public:SimpleOpenNIViewer () :viewer (" Point Cloud Compression Example"){}
/************************************************************************************************在OpenNIGrabber采集循环执行的回调函数cloud_cb_中,首先把获取的点云压缩到stringstream缓冲区,下一步就是解压缩,它对压缩了的二进制数据进行解码,存储在新的点云中解码了点云被发送到点云可视化对象中进行实时可视化
*************************************************************************************************/void  cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud){if (!viewer.wasStopped ()){// 存储压缩点云的字节流对象
      std::stringstream compressedData;// 存储输出点云pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloudOut (new pcl::PointCloud<pcl::PointXYZRGBA> ());// 压缩点云PointCloudEncoder->encodePointCloud (cloud, compressedData);// 解压缩点云PointCloudDecoder->decodePointCloud (compressedData, cloudOut);// 可视化解压缩的点云
      viewer.showCloud (cloudOut);}}
/**************************************************************************************************************在函数中创建PointCloudCompression类的对象来编码和解码,这些对象把压缩配置文件作为配置压缩算法的参数所提供的压缩配置文件为OpenNI兼容设备采集到的点云预先确定的通用参数集,本例中使用MED_RES_ONLINE_COMPRESSION_WITH_COLOR配置参数集,用于快速在线的压缩,压缩配置方法可以在文件/io/include/pcl/compression/compression_profiles.h中找到,在PointCloudCompression构造函数中使用MANUAL——CONFIGURATION属性就可以手动的配置压缩算法的全部参数
******************************************************************************************************************/void run (){bool showStatistics = true;  //设置在标准设备上输出打印出压缩结果信息// 压缩选项详情在: /io/include/pcl/compression/compression_profiles.hpcl::io::compression_Profiles_e compressionProfile = pcl::io::MED_RES_ONLINE_COMPRESSION_WITH_COLOR;// 初始化压缩和解压缩对象  其中压缩对象需要设定压缩参数选项,解压缩按照数据源自行判断PointCloudEncoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> (compressionProfile, showStatistics);PointCloudDecoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> ();/***********************************************************************************************************下面的代码为OpenNI兼容设备实例化一个新的采样器,并且启动循环回调接口,每从设备获取一帧数据就回调函数一次,,这里的回调函数就是实现数据压缩和可视化解压缩结果。************************************************************************************************************///创建从OpenNI获取点云的抓取对象pcl::Grabber* interface = new pcl::OpenNIGrabber ();// 建立回调函数boost::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f = boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);//建立回调函数和回调信息的绑定boost::signals2::connection c = interface->registerCallback (f);// 开始接受点云的数据流interface->start ();while (!viewer.wasStopped ()){sleep (1);}interface->stop ();// 删除压缩与解压缩的实例delete (PointCloudEncoder);delete (PointCloudDecoder);}pcl::visualization::CloudViewer viewer;pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudEncoder;pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudDecoder;};int
main (int argc, char **argv)
{SimpleOpenNIViewer v;  //创建一个新的SimpleOpenNIViewer  实例并调用他的run方法
  v.run ();return (0);
}

 编译后运行的结果如下:

图示为带有RGB纹理信息的实时可视化结果,缩放可视化结果看到经过压缩后点云进行了重采样,纹理信息有所丢失,但数据量有所减小,在实际应用中需要折中取舍

同时在压缩和解压缩的过程中  因为设置compressedData为true所以在标准输出上打印处压缩率帧数等信息:

 

压缩配置文件:压缩配置文件为PCL点云编码器定义了参数集,并针对压缩从openNI采集器获取的普通点云进行了优化设置,注意,解码对象不需要用参数表示,因为它在解码是检测并获取对应编码参数配置,例如下面的压缩配置文件

LOW_RES_ONLINE_COMPRESSION_WITHOUT_COLOR,             //分别率为  1   cm^3   无颜色      快速在线编码
      LOW_RES_ONLINE_COMPRESSION_WITH_COLOR,                 //分别率为  1    cm^3   有颜色      快速在线编码

      MED_RES_ONLINE_COMPRESSION_WITHOUT_COLOR,             //分别率为  5    mm^3   无颜色      快速在线编码
      MED_RES_ONLINE_COMPRESSION_WITH_COLOR,                    //分别率为  5    mm^3   有颜色      快速在线编码

      HIGH_RES_ONLINE_COMPRESSION_WITHOUT_COLOR,         //分别率为  1    mm^3   无颜色      快速在线编码
      HIGH_RES_ONLINE_COMPRESSION_WITH_COLOR,                 //分别率为  1    mm^3   有颜色      快速在线编码

      LOW_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR,       //分别率为  1    cm^3   无颜色      高效离线编码
      LOW_RES_OFFLINE_COMPRESSION_WITH_COLOR,              //分别率为  1    cm^3   有颜色      高效离线编码

      MED_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR,      //分别率为  5    mm^3   无颜色      高效离线编码
      MED_RES_OFFLINE_COMPRESSION_WITH_COLOR,             //分别率为  5    mm^3   有颜色      高效离线编码

      HIGH_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR,     //分别率为  1    mm^3   无颜色      高效离线编码
      HIGH_RES_OFFLINE_COMPRESSION_WITH_COLOR,              //分别率为  1    mm^3   有颜色      高效离线编码
      MANUAL_CONFIGURATION                                                   //允许为高级参数化进行手工配置

微信公众号号可扫描二维码一起共同学习交流

未完待续*********************************************8888

转载于:https://www.cnblogs.com/li-yao7758258/p/6436117.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372851.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android实现自定义带文字和图片的Button

在Android开发中经常会需要用到带文字和图片的button&#xff0c;下面来讲解一下常用的实现办法。 一.用系统自带的Button实现 最简单的一种办法就是利用系统自带的Button来实现&#xff0c;这种方式代码量最小。在Button的属性中有一个是drawableLeft&#xff0c;这个 属性可以…

mysql语句中的注释方法_MySQL语句注释方式简介

MySQL支持三种注释方式&#xff1a;1.从‘#字符从行尾。2.从‘-- 序列到行尾。请注意‘-- (双破折号)注释风格要求第2个破折号后面至少跟一个空格符(例如空格、tab、换行符等等)。3.从/*序列到后面的*/序列。结束序列不一定在同一行中&#xff0c;因此该语法允许注释跨越多行。…

android框架----下沉文字Titanic的使用

Titanic is a simple illusion obtained by applying an animated translation on the TextView TextPaint Shaders matrix. Titanic的使用 Titanic的使用&#xff0c;项目结构如下&#xff1a; 一、下载Titanic并且部署到项目中 Titanic的项目地址&#xff1a; https://github…

linux 自动安装mysql_Linux安装mysql

一、下载这里我创建了一目录software用于存放我们待会要下载的mysql包&#xff0c;先去到该目录命令&#xff1a;cd /software命令&#xff1a;wget http://mirrors.sohu.com/mysql/MySQL-5.7/mysql-5.7.17-linux-glibc2.5-x86_64.tar下载完成后&#xff0c;你会在software这个…

Animation用法

测试代码及说明&#xff1a; <!DOCTYPE html> <html lang"en-US"> <head><meta charset"UTF-8"><title>Simple CSS3 Animation</title><style type"text/css">#demo {position: absolute;left: 30%;t…

mysql备份 where_MySQL备份与还原

1.mysqldumpmysqlbinlog介绍mysqldump备份结合binlog日志恢复。MySQL备份一般采取全库备份加日志备份的方式&#xff0c;例如每天执行一次全备份&#xff0c;每小时执行一次二进制日志备份&#xff0c;这样在MySQL故障后可以使用全备份和日志备份将数据恢复到最后一个二进制日志…

JMeter:负载测试关系数据库

Apache JMeter是完全使用Java编写的性能测试工具。 可以在请求/响应模型上运行的任何应用程序都可以使用JMeter进行负载测试。 关系数据库也不例外&#xff1a;接收sql查询&#xff0c;执行它们并返回执行结果。 我将向您展示使用JMeter的图形用户界面设置测试方案有多么容易。…

new: Set up a window

Nehe的教程确实太老了&#xff0c;不过我认为它也能够让我了解OpenGL3.2以前的管线渲染模式&#xff0c;即使它在现在已经不常见了。因为想要了解&#xff0c;所以我还是会看完Nehe的教程。 现在这是一个新的教程 - JoeyDeVries的教程&#xff0c;可以说是网上最好的OpenGL教程…

Python全栈开发:socket

Socket socket通常也称作"套接字"&#xff0c;用于描述IP地址和端口&#xff0c;是一个通信链的句柄&#xff0c;应用程序通常通过"套接字"向网络发出请求或者应答网络请求。 socket起源于Unix&#xff0c;而Unix/Linux基本哲学之一就是“一切皆文件”&…

NetBeans 7.1:创建自定义提示

我已经在帖子中介绍了一些我最喜欢的NetBeans提示 &#xff0c;这些信息是用于使Java代码现代化的七个NetBeans提示和七个不可或缺的NetBeans Java提示 。 这两个帖子中涉及的十四个提示仅占NetBeans支持的“即开即用”提示总数的一小部分。 但是&#xff0c;由于NetBeans 7.1使…

qregexp括号匹配_转:Qt的正则表达式和QRegExp

考虑一下我们经常遇到的问题&#xff0c;比如gemfield想从青岛之光读书(www.civilnet.cn/book)中找一个关键的电话号码&#xff0c;通常第一步就是将书中所有的电话号码查找出来放在手边。那么怎么拟定查询条件呢&#xff1f;电话的格式有如下几种&#xff1a;01088888888010 8…

具有Tron效果的JavaFX 2 Form

这是一个具有TRON效果的简单JavaFX登录表单。 在此示例中&#xff0c;我使用CSS设置TextField和Button的样式。 这是CSS和Effect代码的片段&#xff1a; .text-field{-fx-background-color: transparent;-fx-border-color: #00CCFF;-fx-text-fill: white; }.password-field{-fx…

Akka的字数统计MapReduce

在我与Akka的日常工作中&#xff0c;我最近写了一个字数映射表简化示例。 本示例实现了Map Reduce模型&#xff0c;该模型非常适合横向扩展设计方法。 流 客户端系统&#xff08;FileReadActor&#xff09;读取文本文件&#xff0c;并将每一行文本作为消息发送给ClientActor。…

Struts2之环境配置

在学习struts2之前&#xff0c;首先我们要明白使用struts2的目的是什么&#xff1f;它能给我们带来什么样的好处&#xff1f; 设计目标 Struts设计的第一目标就是使MVC模式应用于web程序设计。在这儿MVC模式的好处就不在提了。 技术优势 Struts2有两方面的技术优势&#xff0c;…

基于JavaFX的SimpleDateFormat演示程序

对于使用Java Date进行格式化的新手甚至对于使用Java Date进行格式化的有经验的Java开发人员而言&#xff0c;可能有些棘手的事情是使用SimpleDateFormat规范日期/时间格式。 SimpleDateFormat的基于类级别的Javadoc的文档非常详尽&#xff0c;涵盖了表示日期/时间的各个组成部…

iOS与H5交互

前提&#xff1a;在iOS控制器中加载UIWebView&#xff0c;设置代理&#xff0c;遵守UIWebViewDelegate协议。 一、iOS调用JS方法 通过iOS调用JS代码实现起来比较方便直接调用UIWebView的方法- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script…

markdownTest

MARKDOWNTEST 11111111111111有一种神奇的语言&#xff0c;它比html还简单&#xff0c;它巧妙地将内容与格式整合在一起——它就是Markdown有一种神奇的语言&#xff0c;它比html还简单&#xff0c;它巧妙地将内容与格式整合在一起——它就是Markdown 111111111111111222222222…

Aleri –复杂事件处理

Sybase的Aleri流媒体平台是CEP市场中最受欢迎的产品之一。 它在Sybase的交易平台RAP版本中使用&#xff0c;该版本在资本市场中广泛用于管理投资组合中的头寸。 今天&#xff0c;在这个由多个部分组成的系列文章的第一个部分中&#xff0c;我希望提供Aleri平台的概述&#xff0…

python版本回退_Python爬虫之BeautifulSoup解析之路

上一篇分享了正则表达式的使用&#xff0c;相信大家对正则也已经有了一定的了解。它可以针对任意字符串做任何的匹配并提取所需信息。但是我们爬虫基本上解析的都是html或者xml结构的内容&#xff0c;而非任意字符串。正则表达式虽然很强大灵活&#xff0c;但是对于html这样结构…

WebStorm 运行Rect Native 项目

今天教大家如何直接使用WebStorm这个IDE直接完成编码运行项目工作.这样就可以不用打开Xcode了. 1.首先点击WebStorm右上方的下拉箭头弹出的Edit Configurations.... 2.然后会进入一个配置页面.点击左上方的.在弹出的列表中选中npm.如图. 3.在右边的配置框中,先选择Command为hel…