1.原理
即使用一个AABB盒,去裁剪位于立方体内部/外部的点云。
(1)定义AABB盒。
(2)使用该盒子裁剪点云,得到结果点云。
2.使用场景
当你需要用立方体裁剪点云的时候。多用在实际工作中三维情况下的框选。
3.注意事项
立方体裁剪可裁剪得到立方体的内部点和外部点。
4.关键函数
(1)是否保留删除点的索引,false为保留删除点的索引,true为不保留删除点的索引。
setKeepOrganized()
(2)设置被过滤的点不被删除的情况下,给其均赋予新值;与setKeepOrganized()联动使用。
setUserFilterValue()
(3)提取AABB包围盒内、外的点。
在使用立方体裁剪后,保存其索引,使用索引滤波提取立方体外的点。
片段代码示例:
// 内部点
pcl::ExtractIndices<pcl::PointXYZRGB> extr; // 索引滤波器
extr.setInputCloud(cloud); // 设置输入点云
extr.setIndices(indexes); // 设置索引
extr.filter(*cloud_in_box_filtered); // 提取对应索引的点云
// 外部点
extr.setNegative(true); // 提取对应索引之外的点
extr.filter(*cloud_out_box_filtered);
5.代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/filters/crop_box.h>
#include <pcl/filters/extract_indices.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>
int main()
{
/****************立方体裁剪********************/
// 原始点云
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::io::loadPCDFile("D:/code/csdn/data/bunny.pcd", *cloud); // 加载原始点云数据
// 结果点云
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_in_box_filtered(new pcl::PointCloud<pcl::PointXYZRGB>); // 裁剪后立方体内部的点云
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_out_box_filtered(new pcl::PointCloud<pcl::PointXYZRGB>); // 裁剪后立方体内部的点云
// 立方体裁剪
pcl::CropBox<pcl::PointXYZRGB> filters;
Eigen::Vector4f min_pt = { -0.1,-0.1,-0.1,0 }; // 立方体box值
Eigen::Vector4f max_pt = { 0.1,0.1,0.1,0 };
filters.setMin(min_pt); // 给定立体空间
filters.setMax(max_pt);
filters.setInputCloud(cloud); // 输入点云
filters.setKeepOrganized(false); // false保留删除的点云点的索引,true不保留删除的点云点的索引
filters.setUserFilterValue(0.1f); // 可设置被过滤的点不被删除,而是修改为其他值(本方法需与setKeepOrganized联用)
pcl::IndicesPtr indexes(new pcl::Indices()); // 记录索引
filters.filter(*indexes); // 获取位于框内点的索引
// 提取立方体内部和外部点
// 内部点
pcl::ExtractIndices<pcl::PointXYZRGB> extr; // 索引滤波器
extr.setInputCloud(cloud); // 设置输入点云
extr.setIndices(indexes); // 设置索引
extr.filter(*cloud_in_box_filtered); // 提取对应索引的点云
// 外部点
extr.setNegative(true); // 提取对应索引之外的点
extr.filter(*cloud_out_box_filtered);
/****************展示********************/
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("PCL"));
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGB> in(cloud_in_box_filtered, 255, 0, 0);
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGB> out(cloud_out_box_filtered, 0, 255, 0);
viewer->addCube(min_pt[0], max_pt[0], min_pt[1], max_pt[1], min_pt[2], max_pt[2], 0.5, 0, 0.5, "cube");
viewer->setRepresentationToWireframeForAllActors();
viewer->addPointCloud(cloud_in_box_filtered, in, "cloud_in_box");
viewer->addPointCloud(cloud_out_box_filtered, out, "cloud_out_box");
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return 0;
}