ROS kinetic环境下,利用PCL实现三维点云的滤波

1 篇文章 0 订阅
1 篇文章 0 订阅

新建ROS功能包,需要添加如下依赖

pcl_conversions pcl_ros roscpp sensor_msgs

功能:加载.pcd文件实现直通滤波+crophull滤波+统计学滤波+体素滤波

  • 直通滤波部分的函数代码使用时需要注意,可以将该函数的输入输出的数据类型改写成crophull滤波函数的数据类型
  • PCL中的crophull滤波只能使用pcl::PointCloud < pcl::PointXYZ >数据类型,使用pcl::PointCloud< pcl::PointXYZRGB >数据类型可以编译成功,但是运行时会报错。
#include <ros/ros.h>
// PCL specific includes
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/PCLPointCloud2.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/crop_hull.h>
#include <pcl/surface/concave_hull.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <iostream>

using namespace std;
 
ros::Publisher pub;

/*直通滤波*/
pcl::PCLPointCloud2 passthrough(pcl::PCLPointCloud2* msg)
{
    /*直通滤波*/
    pcl::PCLPointCloud2 passthrough_filtered_x; 
    pcl::PCLPointCloud2 passthrough_filtered_y; 
    pcl::PCLPointCloud2 passthrough_filtered_z; 

    /*进行X方向直通滤波*/ 
    pcl::PCLPointCloud2ConstPtr cloudPtr_x(msg);
    pcl::PassThrough<pcl::PCLPointCloud2> pass;
    pass.setInputCloud (cloudPtr_x);
    pass.setFilterFieldName ("x");
    pass.setFilterLimits (-0.05, 0.05);
    //pass.setFilterLimitsNegative (true);
    pass.filter (passthrough_filtered_x);
    
    /*进行Y方向直通滤波*/
    pcl::PCLPointCloud2* cloud_y = new pcl::PCLPointCloud2;
    *cloud_y = passthrough_filtered_x;
    pcl::PCLPointCloud2ConstPtr cloudPtr_y(cloud_y);
    pass.setInputCloud (cloudPtr_y);
    pass.setFilterFieldName ("y");
    pass.setFilterLimits (-0.2, 0.2);
    //pass.setFilterLimitsNegative (true);
    pass.filter (passthrough_filtered_y);

    /*进行Z方向直通滤波*/
    pcl::PCLPointCloud2* cloud_z = new pcl::PCLPointCloud2;
    *cloud_z = passthrough_filtered_y;
    pcl::PCLPointCloud2ConstPtr cloudPtr_z(cloud_z);
    pass.setInputCloud (cloudPtr_z);
    pass.setFilterFieldName ("z");
    pass.setFilterLimits (0.1, 0.3);
    //pass.setFilterLimitsNegative (true);
    pass.filter (passthrough_filtered_z);

    return passthrough_filtered_z; 
}



/*crophull滤波*/
pcl::PointCloud<pcl::PointXYZ>::Ptr crophull(pcl::PointCloud<pcl::PointXYZ>::Ptr msg)
{
    /*设置封闭范围顶点*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr boundingbox_ptr (new pcl::PointCloud<pcl::PointXYZ>);
    boundingbox_ptr->push_back(pcl::PointXYZ(0.1, 0.1, 0.1));
    boundingbox_ptr->push_back(pcl::PointXYZ(0.1, -0.1,0.1 ));
    boundingbox_ptr->push_back(pcl::PointXYZ(-0.1, 0.1,0.1 ));

    /*构造凸包*/
    pcl::ConvexHull<pcl::PointXYZ> hull;
	hull.setInputCloud(boundingbox_ptr);
	hull.setDimension(2);
	std::vector<pcl::Vertices> polygons;
	pcl::PointCloud<pcl::PointXYZ>::Ptr surface_hull (new pcl::PointCloud<pcl::PointXYZ>);
	hull.reconstruct(*surface_hull, polygons);

    /*crophull滤波*/
	pcl::PointCloud<pcl::PointXYZ>::Ptr objects (new pcl::PointCloud<pcl::PointXYZ>);
    
	pcl::CropHull<pcl::PointXYZ> bb_filter;
	bb_filter.setDim(2);
	bb_filter.setInputCloud(msg);
	bb_filter.setHullIndices(polygons);
	bb_filter.setHullCloud(surface_hull);
	bb_filter.filter(*objects);
    return objects;
}

/*统计学滤波*/
pcl::PointCloud<pcl::PointXYZ>::Ptr statisticalRemoval(pcl::PointCloud<pcl::PointXYZ>::Ptr msg)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr objects (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
    sor.setInputCloud (msg);
    sor.setMeanK (50);
    sor.setStddevMulThresh (1.0);
    sor.filter (*objects);
    return objects;
}

/*体素滤波*/
pcl::PointCloud<pcl::PointXYZ>::Ptr voxelGrid(pcl::PointCloud<pcl::PointXYZ>::Ptr msg)
{
    /*进行体素滤波*/ 
    /*定义指针时一定要记得分配指向的内存空间*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr voxelgrid_filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    pcl::VoxelGrid<pcl::PointXYZ> sor;
    sor.setInputCloud (msg);
    sor.setLeafSize (0.005, 0.005, 0.005);
    // apply filter
    sor.filter (*voxelgrid_filtered);
    return voxelgrid_filtered;
}

/*对三维点云实现预处理*/
void preprocess(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud,string outputFile)
{


    /*直通滤波*/
    /*
    pcl::PCLPointCloud2* passthrough_filtered = new pcl::PCLPointCloud2; 
    *passthrough_filtered = passthrough(cloud);*/
    
    /*CropHull滤波*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr crophull_output(new pcl::PointCloud<pcl::PointXYZ>);
    crophull_output = crophull(inputCloud);
    
    /*统计学滤波*/
    /*有过一次测试,在CropHull滤波之后,在进行统计学滤波容易产生空洞*/
    //pcl::PointCloud<pcl::PointXYZ>::Ptr statistical_output(new pcl::PointCloud<pcl::PointXYZ>);
    //statistical_output = statisticalRemoval(crophull_output);
    
    /*体素滤波*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr voxelgrid_output(new pcl::PointCloud<pcl::PointXYZ>);
    voxelgrid_output = voxelGrid(crophull_output); 
    
    /*保存滤波后的点云文件*/
    pcl::PointCloud<pcl::PointXYZ>::Ptr &output = voxelgrid_output;
    pcl::io::savePCDFileASCII(outputFile, *output);
    cout<<"pointcloud_filtered size = "<<output->points.size()<<endl;
} 

int main (int argc, char** argv)
{
    // Initialize ROS
    ros::init (argc, argv, "VoxelGrid");
    ros::NodeHandle nh;
    string inputFile = "test_pointcloud_init.pcd";
    string outputFile = "./888test_pointcloud_filtered.pcd";
    /*加载pcd文件并保存为inputCloud*/
    pcl::PointCloud<pcl::PointXYZ> inputCloud;
    if (pcl::io::loadPCDFile(inputFile, inputCloud) == -1)
    {
        ROS_INFO("couldn't read file ");
        return -1;
    }
    else
    {
        ROS_INFO("Read %s!",inputFile.c_str());
        /*进行预处理工作*/
        pcl::PointCloud<pcl::PointXYZ>::Ptr input(new pcl::PointCloud<pcl::PointXYZ>);
        *input = inputCloud;
        preprocess(input,outputFile);
        ROS_INFO("Preprocessing is Completed! ");
    }
    return 0;
}

后期关于滤波改进的想法

  • 学习基于曲率的点云下采样
  • 将体素滤波与基于曲率的点云下采样结合起来,弥补各自的不足
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ROS(Robot Operating System)是一个用于机器人软件开发的框架,它提供了一种在不同模块间进行通信和数据交换的机制。ROS中的topic是一种用于消息传递的机制,可以实现节点间的发布与订阅。 三维点云数据是一种在三维空间中表示物体形状和表面特征的数据形式。在ROS中,三维点云数据可以通过PointCloud2类型的消息进行传输和存储。PointCloud2消息结构包括点云数据的类型和大小信息,以及每个点的坐标和属性信息。 PointCloud2消息中的点云数据以二进制形式存储,并使用一维数组表示。数组中的每个元素表示一个点的属性信息,例如坐标、颜色、法线等。通过定义点云的字段(Field)来描述每个元素的含义和数据类型。常用的字段类型包括FLOAT32、FLOAT64、UINT8等。 在PointCloud2消息中,点云数据的存储顺序可以是按照行优先(row-major)或列优先(column-major)方式。通过设置header中的“is_bigendian”字段可以指定数据的字节序,以确保在不同平台上的兼容性。 除了PointCloud2消息,ROS中还提供了一些用于处理三维点云数据的相关工具和库,如PCL(Point Cloud Library),它提供了一系列用于点云数据处理的算法和工具函数,可以方便地进行点云数据的滤波、配准、分割等操作。 通过使用ROS的topic机制和PointCloud2消息,我们可以方便地在不同模块间传输和处理三维点云数据,实现机器人的感知和环境建模等应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值