Octree空间 划分,获取叶子节点,vtk显示
·实现思路
·1 vs2017配置VTK,QT,PCL
在vs2017的平台上进行VTK,QT,PCL的配置,我的顺序是:安装配置vs2017 --> QT5.12 --> VTK8.1 -->PCL1.9。根据网上的配置方法进行配置,在此过程中会遇到各种问题,要根据自己电脑的实际情况进行问题解决,在这里不赘述。
· 2 读入显示给定点云数据,利用Octree对给定点云进行空间划分
在配置好所有的环境之后,使用PCL进行点云数据的读取并与八叉树相结合实现空间划分,需要注意的是PCL进行点云数据读取的时候,只能读取pcd格式的数据,所以在数据读取之前需要将asc格式的数据转换成pcd格式的数据,具体实现如下图所示:
//在vtk控件中显示点云
void PointCloudManage::VTK_Show(string s)
{
//ui->pushButton3->setText(tr("()"));
// 数据读取
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile<pcl::PointXYZ>(s, *cloud);
if (pcl::io::loadPCDFile<pcl::PointXYZ>(s, *cloud) == -1)
{
std::cout << "Cloud reading failed。" << std::endl;
return;
//pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud,"z"); // 按照z字段进行渲染
//viewer->addPointCloud<pcl::PointXYZ>(cloud, fildColor, "sample cloud");
// 设置单一颜色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> singleColor(cloud, 0, 255, 0);//0-255 设置成绿色
// 颜色显示
viewer->addPointCloud<pcl::PointXYZ>(cloud, singleColor, "sample");//显示点云,其中fildColor为颜色显示
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");
std::cout <<"宽:"<< cloud->width << std::endl;
std::cout <<"高:"<< cloud->height<<std::endl;
viewer->updatePointCloud(cloud, "cloud");
}
·点云数据结果显示
· 根据空间划分结果,获取叶子节点
在空间划分的基础上,使用PCL中八叉树的getVoxelBounds函数来获取特定深度和体素的情况下的叶子节点的最大值以及最小值。并使用pcl中的addCube函数进行显示(该函数显示很慢,建议使用vtk显示,提高程序效率)。下面是体素为:5,深度为6 叶子节点的显示(可修改),如下图所示。
// 叶子节点显示
void PointCloudManage::GetLeafShow()
{
// 点云数据的存储
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile<pcl::PointXYZ>("bunny.pcd", *cloud1);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("bunny.pcd", *cloud1) == -1)
{
std::cout << "Cloud reading failed。" << std::endl;
return;
}
// 存储体素的下标
map<int, vector<Eigen::Vector3f>>_bodyVoxel;
// 存储叶子节点
//pcl::PointCloud<pcl::PointXYZ>::Ptr cloudLeaf(new pcl::PointCloud<pcl::PointXYZ>);
// 最小体素的边长
float resolution = 5.0f;
pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(resolution);
//octree.setTreeDepth(8);
octree.setInputCloud(cloud1);
// 从输入点云构建八叉树
octree.addPointsFromInputCloud();
pcl::PointXYZ searchPoint;
int depth = octree.getTreeDepth();
int countVoxel = 0;
// 求出体素边界
int idString = 0;
for (auto it = octree.begin(depth);it != octree.end();++it)
{
if (it.isLeafNode())
{
Eigen::Vector3f voxel_min, voxel_max;
octree.getVoxelBounds(it, voxel_min, voxel_max);
vector<Eigen::Vector3f> list;
list.push_back(voxel_min);
list.push_back(voxel_max);
_bodyVoxel.insert(pair<int, vector<Eigen::Vector3f>>(countVoxel, list));
std::cout << "最小值: " << voxel_min.x() << " " << voxel_min.y() << " " << voxel_min.z() << std::endl;
std::cout << "最大值: " << voxel_max.x() << " " << voxel_max.y() << " " << voxel_max.z() << std::endl;
std::cout << std::endl;
countVoxel++;
}
}
std::cout << "深度: " << depth << std::endl;
// 画图
vector<Eigen::Vector3f> list;
Eigen::Vector3f voxel_min, voxel_max;
countLeaf = 0;
for (auto it = _bodyVoxel.begin();it != _bodyVoxel.end();it++)
{
list = it->second;
voxel_min = list[0];
voxel_max = list[1];
viewer->addCube(voxel_min.x(), voxel_max.x(), voxel_min.y(), voxel_max.y(), voxel_min.z(), voxel_max.z(), 1, 0, 0, std::to_string(countLeaf));
countLeaf++;
}
std::cout << "**********叶子节点个数********" << octree.getLeafCount() << std::endl;
std::cout << "叶子节点个数: " << countLeaf << std::endl;
// 对叶子节点容器初始化
}