地面滤波算法学习及测试记录

1.CSF布料滤波算法

1.1 环境配置:

环境:Win10+ VS2019
参考文章:使用CSF对kitti的点云数据过滤出地面点云,结合PCL使用,C++实现
下载代码后,新建build文件夹
地面滤波算法学习及测试记录_第1张图片
打开CMake-gui
地面滤波算法学习及测试记录_第2张图片
点击Configure, 出现红色的设置提醒,好像没啥好设置的,再点击Configure,Generate

按照该博主的步骤,打开CSF.sln,右键ALL_BUILD,点击生成。

出现报错:2>cl : 命令行 error D8021: 无效的数值参数“/Werror”
命令行 error D8021: 无效的数值参数“/Wextra”

百度有博主说是python文件夹下的setup.py文件里面有设置了这个参数,但查找该代码下的内容,并未找到。
按照错误提示找到D:\Program Files (x86)\CSF\CSF-master\src\CMakeLists.txt,
删除target_compile_options里面的内容,只剩下(CSF PRIVATE -Wall ),保存。
重新打开CSF.sln,右键ALL_BUILD,点击生成。
地面滤波算法学习及测试记录_第3张图片
虽然有很多报错,但是显示生成成功。并生成了lib文件。
地面滤波算法学习及测试记录_第4张图片

1.2 代码运行

按照参考文章的步骤配置环境,博主给的代码如下:

#include 
#include 
#include //PCL对各种格式的点的支持头文件
#include //PCL的PCD格式文件的输入输出头文件
#include //点云查看窗口头文件
#include 	//滤波相关头文件
#include 
#include 
#include "CSF.h"

using namespace std;

void clothSimulationFilter(const vector< csf::Point >& pc,vector<int> &groundIndexes,vector<int> & offGroundIndexes)
{
	//step 1 read point cloud
	CSF csf;
	csf.setPointCloud(pc);// or csf.readPointsFromFile(pointClouds_filepath); 
	//pc can be vector< csf::Point > or PointCloud defined in point_cloud.h

	//step 2 parameter settings
	//Among these paramters:  
	//time_step  interations class_threshold can remain as defualt in most cases.
	csf.params.bSloopSmooth = false;
	csf.params.cloth_resolution = 0.5;
	csf.params.rigidness = 3;

	csf.params.time_step = 0.65;
	csf.params.class_threshold = 0.5;
	csf.params.interations = 500;

	//step 3 do filtering
	//result stores the index of ground points or non-ground points in the original point cloud
	
	csf.do_filtering(groundIndexes, offGroundIndexes);
	//csf.do_filtering(groundIndexes, offGroundIndexes,true); 
	//if the third parameter is set as true, then a file named "cloth_nodes.txt" will be created, 
	//it respresents the cloth nodes.By default, it is set as false

}


void addPointCloud(const vector<int>& index_vec, const pcl::PointCloud<pcl::PointXYZI>::Ptr cloud, pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_filtered)
{
	auto& points = cloud_filtered->points;
	const auto& pointclouds = cloud->points;

	for_each(index_vec.begin(), index_vec.end(), [&](const auto& index) {
		pcl::PointXYZI pc;
		pc.x = pointclouds[index].x;
		pc.y = pointclouds[index].y;
		pc.z = pointclouds[index].z;
		pc.intensity = pointclouds[index].intensity;

		points.push_back(pc);
	});

	cloud_filtered->height = 1;
	cloud_filtered->width = cloud_filtered->points.size();
}


int main()
{
	string pcd_path = "E:\\kitti\\data_object_velodyne\\testing\\pcd\\000060.pcd";

	// Generate pointcloud data,新建指针cloud存放点云
	pcl::PointCloud<pcl::PointXYZI>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZI>);	

	if (pcl::io::loadPCDFile<pcl::PointXYZI>(pcd_path, *cloud) == -1)//打开点云文件。
	{
		PCL_ERROR("Couldn't read that pcd file\n");
		return(-1);
	}

	vector<csf::Point> pc;
	const auto& pointclouds = cloud->points;
	pc.resize(cloud->size());
	transform(pointclouds.begin(), pointclouds.end(), pc.begin(), [&](const auto& p)->csf::Point {
		csf::Point pp;
		pp.x = p.x;
		pp.y = p.y;
		pp.z = p.z;
		return pp;
		});

	std::vector<int> groundIndexes, offGroundIndexes;
	clothSimulationFilter(pc, groundIndexes, offGroundIndexes);

	pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZI>);
	

	addPointCloud(groundIndexes, cloud,cloud_filtered);
	pcl::PCDWriter writer;
	writer.write<pcl::PointXYZI>("groundPointCloud.pcd", *cloud_filtered, false);

	cloud_filtered->points.clear();
	addPointCloud(offGroundIndexes, cloud,cloud_filtered);
	writer.write<pcl::PointXYZI>("nonGroundPointCloud.pcd", *cloud_filtered, false);

	//pcl::visualization::CloudViewer viewer("this is a point cloud viewer haha!!");
	//viewer.showCloud(cloud_filtered);
	//while (!viewer.wasStopped())
	//{
	//}

	return 0;
}

用点云库PCL从入门到精通\第十二章\9Identifying ground returns using Progressive Morphological Filter segmentation\Source\samp11-utm.pcd 测试一下
源点云:
地面滤波算法学习及测试记录_第5张图片
分割后:蓝色为地面点云地面滤波算法学习及测试记录_第6张图片
分割自己的数据:桥墩部分,有一些被分成地面了
地面滤波算法学习及测试记录_第7张图片
地面滤波算法学习及测试记录_第8张图片

2. 索引滤波器过滤地面

参考链接:PCL滤波—使用索引滤波器过滤地面
作者给出的代码

//索引滤波
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 

int
main(int argc, char** argv)
{
    //sensor_msgs::PointCloud2::Ptr cloud_blob (new sensor_msgs::PointCloud2), cloud_filtered_blob (new sensor_msgs::PointCloud2);
    pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2);
    pcl::PCLPointCloud2::Ptr cloud_filtered_blob(new pcl::PCLPointCloud2);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>), cloud_p(new pcl::PointCloud<pcl::PointXYZ>), cloud_f(new pcl::PointCloud<pcl::PointXYZ>);

    // 填入点云数据
    pcl::PCDReader reader;
    reader.read("C:\\Users\\oh_clm\\Desktop\\桥梁\\桥梁点云文件\\7\\test.pcd", *cloud_blob);
    std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl;

    // 创建滤波器对象:使用叶大小为1cm的下采样
    pcl::VoxelGrid< pcl::PCLPointCloud2> sor;    //体素栅格下采样对象
    sor.setInputCloud(cloud_blob);               //设置下采样原始点云数据
    sor.setLeafSize(0.01f, 0.01f, 0.01f);        //设置采样的体素大小
    sor.filter(*cloud_filtered_blob);            //执行采样保存数据cloud_filtered_blob

    //统计滤波器,删除离群点
    pcl::StatisticalOutlierRemoval<pcl::PCLPointCloud2> Static;   //创建滤波器对象
    Static.setInputCloud(cloud_filtered_blob);                           //设置待滤波的点云
    Static.setMeanK(50);                               //设置在进行统计时考虑查询点临近点数
    Static.setStddevMulThresh(0.5);                      //设置判断是否为离群点的阀值
    Static.filter(*cloud_filtered_blob);                    //存储

    // 转化为模板点云
    //pcl::fromROSMsg(*cloud_filtered_blob, *cloud_filtered);
    pcl::fromPCLPointCloud2(*cloud_filtered_blob, *cloud_filtered);
    std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;

    // 将下采样后的数据存入磁盘
    pcl::PCDWriter writer;
    //writer.write("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices());


    pcl::SACSegmentation<pcl::PointXYZ> seg;  //创建分割对象
    //可选
    seg.setOptimizeCoefficients(true);        //设置对估计的模型参数进行优化处理
    //必选
    seg.setModelType(pcl::SACMODEL_PLANE);    //设置分割模型类别
    seg.setMethodType(pcl::SAC_RANSAC);       //设置用哪个随机参数估计方法
    seg.setMaxIterations(100);               //设置最大迭代次数
    seg.setDistanceThreshold(0.15);           //设置判断是否为模型内点的距离阈值

    // 创建滤波器对象
    pcl::ExtractIndices<pcl::PointXYZ> extract;
    int i = 0, nr_points = (int)cloud_filtered->points.size();

    //为了处理点云中包含多个模型,在一个循环中执行该过程,
    //并在每次模型被提取后,我们保存剩余的点,进行迭代;
    //模型内点通过分割过程获取;
    //当还有60%原始点云数据时退出循环
    while (cloud_filtered->points.size() > 0.6 * nr_points)
    {
        // 从余下的点云中分割最大平面组成部分
        seg.setInputCloud(cloud_filtered);
        seg.segment(*inliers, *coefficients);
        if (inliers->indices.size() == 0)
        {
            std::cerr << "Could not estimate a planar model for the given dataset." << std::endl;
            break;
        }

        // 分离内层
        extract.setInputCloud(cloud_filtered);
        extract.setIndices(inliers);
        extract.setNegative(false);
        extract.filter(*cloud_p);
        std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl;
        std::stringstream ss;
        ss << "C:\\Users\\oh_clm\\Desktop\\桥梁\\桥梁点云文件\\7\\table_scene_lms400_plane_" << i << ".pcd";
        // writer.write(ss.str(), *cloud_p, false);

         // 创建滤波器对象
        extract.setNegative(true);
        extract.filter(*cloud_f);
        cloud_filtered.swap(cloud_f);
        i++;
    }
    cout << "迭代次数:" << i << endl;
    pcl::visualization::CloudViewer viewer("Cloud Viewer");     //创建viewer对象
    viewer.showCloud(cloud_f);
    // viewer.runOnVisualizationThreadOnce(viewerOneOff);
    while (!viewer.wasStopped())
    {
        //在此处可以添加其他处理

    }
    return (0);
}

这个代码并不适用于目标带有平面的物体
地面滤波算法学习及测试记录_第9张图片

3.渐进式形态学滤波

参考文章:PCL 渐进式形态学滤波

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
int
main(int argc, char** argv)
{
	// --------------------------------加载点云数据----------------------------------------
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PCDReader reader;

	if (reader.read("C:\\Users\\oh_clm\\Desktop\\桥梁\\桥梁点云文件\\7\\test.pcd", *cloud) < 0)
	{
		PCL_ERROR("Could not read file\n");
		return (-1);
	}
	printf("从点云数据中加载 %lld 个点\n", cloud->points.size());
	// ------------------------------------渐进式形态学滤波---------------------------------------
	pcl::StopWatch time;
	pcl::ProgressiveMorphologicalFilter<pcl::PointXYZ> pmf;
	pmf.setInputCloud(cloud);      // 待处理点云
	pmf.setMaxWindowSize(20);      // 最大窗口大小
	pmf.setSlope(1.0f);            // 地形坡度参数
	pmf.setInitialDistance(0.5f);  // 初始高差阈值
	pmf.setMaxDistance(3.0f);      // 最大高差阈值
	/*可选参数*/
	pmf.setCellSize(3);      // 设置窗口的大小
	pmf.setBase(3);          //设置计算渐进窗口大小时使用的基数
	pmf.setExponential(true);//设置是否以指数方式增加窗口大小

	pcl::PointIndicesPtr ground(new pcl::PointIndices);
	pmf.extract(ground->indices);  // 获取地面点的索引
	cout << "渐进式形态学滤波算法运行时间:" << time.getTimeSeconds() << "秒" << endl;
	// ----------------------------------------提取地面-------------------------------------------
	pcl::PointCloud<pcl::PointXYZ>::Ptr ground_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::ExtractIndices<pcl::PointXYZ> extract;
	extract.setInputCloud(cloud);
	extract.setIndices(ground);
	extract.filter(*ground_cloud);
	printf("地面点的个数为: %lld\n", ground_cloud->size());
	pcl::PCDWriter writer;
	writer.write("C:\\Users\\oh_clm\\Desktop\\桥梁\\桥梁点云文件\\7\\samp11-utm_ground.pcd", *ground_cloud, true); //设置为true,可提高效率
	// --------------------------------------提取非地面------------------------------------------
	pcl::PointCloud<pcl::PointXYZ>::Ptr non_ground_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	extract.setNegative(true);
	extract.filter(*non_ground_cloud);
	printf("非地面点的个数为: %lld\n", non_ground_cloud->size());
	writer.write("C:\\Users\\oh_clm\\Desktop\\桥梁\\桥梁点云文件\\7\\samp11-utm_object.pcd", *non_ground_cloud, true);
	// ---------------------------------------可视化---------------------------------------------
	pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D-viewer"));
	viewer->setWindowName("渐进式形态学地面滤波");
	viewer->addPointCloud(ground_cloud, pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(ground_cloud, 255, 0, 0), "ground");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "ground");

	pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(non_ground_cloud, "z"); // 按照z字段进行渲染
	viewer->addPointCloud<pcl::PointXYZ>(non_ground_cloud, fildColor, "non_ground");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "non_ground");
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, 0.7, "non_ground");// 设置透明度

	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(1000));
	}

	return (0);
}

可能是数据太大,没有成功。
地面滤波算法学习及测试记录_第10张图片

你可能感兴趣的:(pcl点云库学习记录,算法,学习,c++)