目录
6.1 3D包围盒裁剪器Class BoxClipper3D< PointT >
6.2 平面裁剪器Class pcl::PlaneClipper3D< PointT >
6.3 立方体过滤Class pcl::CropBox< PointT >
6.4 曲面或多边形过滤 Class pcl::CropHull< PointT >
6.5 完整代码
6.1 3D包围盒裁剪器Class BoxClipper3D< PointT >
类BoxClipper3D实现用一个以原点为中心、XYZ各个方向尺寸为2、经过用户指定仿射变换的立方体进行"空间裁剪",通过设置一个仿射变换矩阵先对立方体进行"变换处理",之后输出仿射变换后落在该立方体内的点集。
void boxclip3d(pcl::PointCloud<pcl::PointXYZRGB> &cloud_in)
{
Eigen::Affine3f transformation = Eigen::Affine3f::Identity();
//查找点云中心
Eigen::Vector4f center;
pcl::compute3DCentroid(cloud_in,center);
cout << center.x() << "," << center.y() << "," << center.z() << endl;
// 将点云中心移到centor
transformation.translation() << -center.x(), -center.y() , -center.z()-1;
// BoxClipper3D
pcl::BoxClipper3D<pcl::PointXYZRGB>bclip3d(transformation);
pcl::Indices cliped;
bclip3d.clipPointCloud3D(cloud_in,cliped);
cout << cliped.size() << endl;
// 将过滤的点云变色
for(auto &idx : cliped)
{
cloud_in.points[idx].r = 255;
cloud_in.points[idx].g = 0;
}
}
6.2 平面裁剪器Class pcl::PlaneClipper3D< PointT >
类PlaneClipper3D在三维空间实现平面裁剪。
void planeClip3D(pcl::PointCloud<pcl::PointXYZRGB> &cloud_in)
{
// 设置裁减平面
Eigen::Vector4f plane(20,20,-1,1);
pcl::PlaneClipper3D<pcl::PointXYZRGB> pclip(plane);
// pcl::PlaneClipper3D
pcl::Indices clipped;
pclip.clipPointCloud3D(cloud_in,clipped);
// 将过滤的点云变色
for(const auto &idx : clipped)
{
cloud_in.points[idx].r = 0;
cloud_in.points[idx].b = 0;
}
cout << clipped.size() << endl;
}
6.3 立方体过滤Class pcl::CropBox< PointT >
类CropBox过滤掉在用户给定立方体内的点云数据。
void cropBox(pcl::PointCloud<pcl::PointXYZRGB> &cloud_in)
{
Eigen::Vector4f center;
pcl::compute3DCentroid(cloud_in,center);
cout << center.x() << "," << center.y() << "," << center.z() << endl;
// 设置过滤的立方体
pcl::CropBox<pcl::PointXYZRGB> cropbox;
cropbox.setInputCloud(cloud_in.makeShared());
cropbox.setMin(Eigen::Vector4f(-0.5,0,1.5,1)); //设置最小点
cropbox.setMax(Eigen::Vector4f(0,0.5,2,1));//设置最大点
// pcl::CropBox
pcl::Indices clipped;
cropbox.filter(clipped);
// 将过滤的点云变色
for(const auto &idx : clipped)
{
cloud_in.points[idx].r = 0;
cloud_in.points[idx].b = 0;
}
cout << clipped.size() << endl;
}
6.4 曲面或多边形过滤 Class pcl::CropHull< PointT >
类CropBox过滤在给定三维封闭曲面或二维封闭多边形内部或外部的点云数据,封闭曲面或多边形由类ConvexHull或ConcaveHull 处理产生。
oid cropHull(pcl::PointCloud<pcl::PointXYZRGB> &cloud_in)
{
Eigen::Vector4f center;
pcl::compute3DCentroid(cloud_in,center);
//定义2D平面点云
pcl::PointCloud<pcl::PointXYZRGB> boundingbox_ptr;
boundingbox_ptr.push_back(pcl::PointXYZRGB(10, 10, 0,255,0,0));
boundingbox_ptr.push_back(pcl::PointXYZRGB(10, -10, 0, 255,0,0 ));
boundingbox_ptr.push_back(pcl::PointXYZRGB(-10, 10, 0 ,255,0,0));
boundingbox_ptr.push_back(pcl::PointXYZRGB(-10, -10, 0 ,255,0,0));
boundingbox_ptr.push_back(pcl::PointXYZRGB(15, 10, 0 ,255,0,0));
pcl::ConvexHull<pcl::PointXYZRGB> hull; //创建凸包对象
hull.setInputCloud(boundingbox_ptr.makeShared()); //设置输入点云
hull.setDimension(2); //设置凸包维度
std::vector<pcl::Vertices> polygons; //设置向量,用于保存凸包定点
pcl::PointCloud<pcl::PointXYZRGB> surface_hull; //该点运用于描述凸包形状
hull.reconstruct(surface_hull, polygons); //计算2D凸包结果
pcl::CropHull<pcl::PointXYZRGB> bb_filter; //创建crophull对象
bb_filter.setDim(2); //设置维度:该维度需要与凸包维度一致
bb_filter.setInputCloud(cloud_in.makeShared()); //设置需要滤波的点云
bb_filter.setHullIndices(polygons); //输入封闭多边形的顶点
bb_filter.setHullCloud(surface_hull.makeShared()); //输入封闭多边形的形状
pcl::Indices clipped;
bb_filter.filter(clipped); //执行CropHull滤波,存出结果在objects
cout << clipped.size() << endl;
for(auto &idx : clipped)
{
cloud_in.points[idx].r = 255;
cloud_in.points[idx].g = 0;
}
}
6.5 完整代码
cmake_minimum_required(VERSION 2.6)
project(BoxClipper3D)
find_package(PCL 1.10 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable(BoxClipper3D BoxClipper3D.cpp)
target_link_libraries (BoxClipper3D ${PCL_LIBRARIES} )
install(TARGETS BoxClipper3D RUNTIME DESTINATION bin)
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/box_clipper3D.h>
#include <pcl/filters/plane_clipper3D.h>
#include <pcl/filters/crop_box.h>
#include <pcl/filters/crop_hull.h>
#include <pcl/surface/convex_hull.h>
#include <pcl/common/transforms.h>
#include <pcl/common/centroid.h>
#include <pcl/common/common_headers.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/console/parse.h>
using namespace std;
void boxclip3d(pcl::PointCloud<pcl::PointXYZRGB> &cloud_in)
{
Eigen::Affine3f transformation = Eigen::Affine3f::Identity();
//查找点云中心
Eigen::Vector4f center;
pcl::compute3DCentroid(cloud_in,center);
cout << center.x() << "," << center.y() << "," << center.z() << endl;
// 将点云中心移到centor
transformation.translation() << -center.x()-0.5, -center.y()-1 , -center.z()-1;
// BoxClipper3D
pcl::BoxClipper3D<pcl::PointXYZRGB>bclip3d(transformation);
pcl::Indices cliped;
bclip3d.clipPointCloud3D(cloud_in,cliped);
cout << cliped.size() << endl;
// 将过滤的点云变色
for(auto &idx : cliped)
{
cloud_in.points[idx].r = 255;
cloud_in.points[idx].g = 0;
}
}
void planeClip3D(pcl::PointCloud<pcl::PointXYZRGB> &cloud_in)
{
// 设置裁减平面
// 构造函数以Eigen::Vector4f作为平面的齐次表示形式。
Eigen::Vector4f plane(20,20,-1,1);
pcl::PlaneClipper3D<pcl::PointXYZRGB> pclip(plane);
// pcl::PlaneClipper3D
pcl::Indices clipped;
pclip.clipPointCloud3D(cloud_in,clipped);
// 将过滤的点云变色
for(const auto &idx : clipped)
{
cloud_in.points[idx].r = 0;
cloud_in.points[idx].b = 0;
}
cout << clipped.size() << endl;
}
void cropBox(pcl::PointCloud<pcl::PointXYZRGB> &cloud_in)
{
Eigen::Vector4f center;
pcl::compute3DCentroid(cloud_in,center);
cout << center.x() << "," << center.y() << "," << center.z() << endl;
// 设置过滤的立方体
pcl::CropBox<pcl::PointXYZRGB> cropbox;
cropbox.setInputCloud(cloud_in.makeShared());
cropbox.setMin(Eigen::Vector4f(-0.5,0,1.5,1)); //设置最小点
cropbox.setMax(Eigen::Vector4f(0,0.5,2,1));//设置最大点
// pcl::CropBox
pcl::Indices clipped;
cropbox.filter(clipped);
// 将过滤的点云变色
for(const auto &idx : clipped)
{
cloud_in.points[idx].r = 0;
cloud_in.points[idx].b = 0;
}
cout << clipped.size() << endl;
}
void cropHull(pcl::PointCloud<pcl::PointXYZRGB> &cloud_in)
{
Eigen::Vector4f center;
pcl::compute3DCentroid(cloud_in,center);
Eigen::Affine3f transformation = Eigen::Affine3f::Identity();
transformation.translation() << -center.x(), -center.y() , -center.z();
pcl::transformPointCloud<pcl::PointXYZRGB>(cloud_in,cloud_in,transformation);
//定义2D平面点云
pcl::PointCloud<pcl::PointXYZRGB> boundingbox_ptr;
boundingbox_ptr.push_back(pcl::PointXYZRGB(10, 10, 0,255,0,0));
boundingbox_ptr.push_back(pcl::PointXYZRGB(10, -10, 0, 255,0,0 ));
boundingbox_ptr.push_back(pcl::PointXYZRGB(-10, 10, 0 ,255,0,0));
boundingbox_ptr.push_back(pcl::PointXYZRGB(-10, -10, 0 ,255,0,0));
boundingbox_ptr.push_back(pcl::PointXYZRGB(15, 10, 0 ,255,0,0));
pcl::ConvexHull<pcl::PointXYZRGB> hull; //创建凸包对象
hull.setInputCloud(boundingbox_ptr.makeShared()); //设置输入点云
hull.setDimension(2); //设置凸包维度
std::vector<pcl::Vertices> polygons; //设置向量,用于保存凸包定点
pcl::PointCloud<pcl::PointXYZRGB> surface_hull; //该点运用于描述凸包形状
hull.reconstruct(surface_hull, polygons); //计算2D凸包结果
pcl::CropHull<pcl::PointXYZRGB> bb_filter; //创建crophull对象
bb_filter.setDim(2); //设置维度:该维度需要与凸包维度一致
bb_filter.setInputCloud(cloud_in.makeShared()); //设置需要滤波的点云
bb_filter.setHullIndices(polygons); //输入封闭多边形的顶点
bb_filter.setHullCloud(surface_hull.makeShared()); //输入封闭多边形的形状
pcl::Indices clipped;
bb_filter.filter(clipped); //执行CropHull滤波,存出结果在objects
cout << clipped.size() << endl;
for(auto &idx : clipped)
{
cloud_in.points[idx].r = 255;
cloud_in.points[idx].g = 0;
}
}
int main(int argc, char *argv[])
{
//load点云
pcl::PCLPointCloud2 cloud;
pcl::io::loadPCDFile("../pig.pcd",cloud);
pcl::PointCloud<pcl::PointXYZRGB> cloud_in;
pcl::fromPCLPointCloud2(cloud,cloud_in);
//Clipper
//boxclip3d(cloud_in);
//planeClip3D(cloud_in);
//cropBox(cloud_in);
cropHull(cloud_in);
// 创建窗口
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer());
viewer->setWindowName("BoxClipper3D");
pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud_in.makeShared());
viewer->addPointCloud(cloud_in.makeShared(),rgb);
//viewer->addCube(-0.5,0,0,0.5,1.5,2,1.0,0.0,0.0);
//viewer->addPolygon<pcl::PointXYZRGB>(boundingbox_ptr,0,1.0,0);
viewer->setRepresentationToWireframeForAllActors();
while(!viewer->wasStopped())
viewer->spinOnce(100);
return 0;
}