点云的预处理主要包括:点云去噪和点云的简化
点云的去噪主要是去除离群点点云的平滑处理
去除离群点方法:半径滤波和统计滤波
平滑处理方法:双边滤波和导向滤波
点云简化:体素滤波
去除背景:主要是去除地面
方法:渐进形态学滤波,平面拟合,布料法
点云体素滤波
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
using namespace std;
int
main(int argc, char** argv)
{
// -------------------------------读入点云数据--------------------------------
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCDReader reader;
reader.read("data//table_scene_lms400.pcd", *cloud);
cout << "PointCloud before filtering: " << *cloud << endl;
// --------------------------------VoxelGrid----------------------------------
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
pcl::VoxelGrid<pcl::PointXYZ> vg;
vg.setInputCloud(cloud); // 输入点云
vg.setLeafSize(0.3,0.3,0.3); // 设置最小体素边长
vg.filter(*cloud_filtered); // 进行滤波
cout << "PointCloud after filtering: " << *cloud_filtered << endl;
// ---------------------------------保存结果----------------------------------
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ>("2f.pcd", *cloud_filtered, false);
// ---------------------------------结果可视化--------------------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("ShowCloud"));
int v1(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->setBackgroundColor(0, 0, 0, v1);
viewer->addText("Raw point clouds", 10, 10, "v1_text", v1);
int v2(0);
viewer->createViewPort(0.5, 0.0, 1, 1.0, v2);
viewer->setBackgroundColor(0.1, 0.1, 0.1, v2);
viewer->addText("filtered point clouds", 10, 10, "v2_text", v2);
viewer->setWindowName("VoxelGrid");
viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud", v1);
viewer->addPointCloud<pcl::PointXYZ>(cloud_filtered, "cloud_filtered", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "sample cloud", v1);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_filtered", v2);
//view->addCoordinateSystem(1.0);
//view->initCameraParameters();
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return 0;
}
统计滤波
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/filters/radius_outlier_removal.h>
using namespace std;
void VisualizeCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& filter_cloud) {
//-----------------------显示点云-----------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("显示点云"));
int v1(0), v2(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->setBackgroundColor(0, 0, 0, v1);
viewer->addText("point clouds", 10, 10, "v1_text", v1);
viewer->createViewPort(0.5, 0.0, 1, 1.0, v2);
viewer->setBackgroundColor(0.1, 0.1, 0.1, v2);
viewer->addText("filtered point clouds", 10, 10, "v2_text", v2);
// 按照z字段进行渲染,将z改为x或y即为按照x或y字段渲染
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud, "z");
viewer->addPointCloud<pcl::PointXYZ>(cloud, fildColor, "sample cloud", v1);
viewer->addPointCloud<pcl::PointXYZ>(filter_cloud, "cloud_filtered", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_filtered", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "cloud_out", v3);
//viewer->addCoordinateSystem(1.0);
//viewer->initCameraParameters();
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}
int
main()
{
// pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOrign(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
//读入点云数据
pcl::PCDReader reader;
reader.read<pcl::PointXYZ>("d://PCD//11.pcd", *cloud);
cout << "Cloud before filtering:\n " << cloud->size() << endl;
// -----------------统计滤波-------------------
// 创建滤波器,对每个点分析的临近点的个数设置为50 ,并将标准差的倍数设置为1 这意味着如果一
// 个点的距离超出了平均距离一个标准差以上,则该点被标记为离群点,并将它移除,存储起来
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
sor.setInputCloud(cloud); //设置待滤波的点云
sor.setMeanK(50); //设置在进行统计时考虑查询点邻近点数
sor.setStddevMulThresh(10); //设置判断是否为离群点的阈值,里边的数字表示标准差的倍数,1个标准差以上就是离群点。
//即:当判断点的k近邻平均距离(mean distance)大于全局的1倍标准差+平均距离(global distances mean and standard),则为离群点。
sor.filter(*cloud_filtered); //存储内点
cout << "Cloud after filtering: \n" << cloud_filtered->size() << endl;
// 保存点云
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("d://filter.pcd", *cloud_filtered, true);
// 可视化
VisualizeCloud(cloud, cloud_filtered);
return (0);
}
半径滤波
}
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/filters/radius_outlier_removal.h>
using namespace std;
void VisualizeCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& filter_cloud) {
//-----------------------显示点云-----------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("显示点云"));
int v1(0), v2(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->setBackgroundColor(0, 0, 0, v1);
viewer->addText("point clouds", 10, 10, "v1_text", v1);
viewer->createViewPort(0.5, 0.0, 1, 1.0, v2);
viewer->setBackgroundColor(0.1, 0.1, 0.1, v2);
viewer->addText("filtered point clouds", 10, 10, "v2_text", v2);
// 按照z字段进行渲染,将z改为x或y即为按照x或y字段渲染
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud, "z");
viewer->addPointCloud<pcl::PointXYZ>(cloud, fildColor, "sample cloud", v1);
viewer->addPointCloud<pcl::PointXYZ>(filter_cloud, "cloud_filtered", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_filtered", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "cloud_out", v3);
//viewer->addCoordinateSystem(1.0);
//viewer->initCameraParameters();
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}
int
main()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
//读入点云数据
pcl::PCDReader reader;
reader.read<pcl::PointXYZ>("d://PCD//11.pcd", *cloud);
cout << "Cloud before filtering:\n " << cloud->size() << endl;
pcl::RadiusOutlierRemoval<pcl::PointXYZ> radius;
radius.setInputCloud(cloud);
radius.setRadiusSearch(radius_search);
radius.setMinNeighborsInRadius(num);
radius.filter(*cloud_filtered);
cout << "Cloud after filtering: \n" << cloud_filtered->size() << endl;
// 保存点云
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("d://filter.pcd", *cloud_filtered, true);
// 可视化
VisualizeCloud(cloud, cloud_filtered);
return (0);
}
导向滤波
GuildFilter.h
#pragma once
#include<pcl/point_types.h>
#include <pcl/common/centroid.h>
#include <pcl/search/kdtree.h> // for KdTree
namespace plug
{
template<typename PointTin, typename PointTout>
class GuildFilter : public pcl::PointCloud<PointTin>
{
protected:
using SearcherPtr = typename pcl::search::Search<PointTin>::Ptr;
public:
// 输入点云
inline bool
setInputCloud(pcl::PointCloud<PointTin>::Ptr& input_cloud)
{
m_input = input_cloud;
return true;
};
// k近邻搜索的邻域点数
inline void
setKsearch(int nr_k)
{
m_k = nr_k;
}
// 参数阈值
inline void
setEpsilonThresh(double epsilon)
{
m_epsilon = epsilon;
}
// 导向滤波实现过程
void filter(pcl::PointCloud<PointTout>& output)
{
output = *m_input;
if (!m_searcher)
m_searcher.reset(new pcl::search::KdTree<PointTin>(false));
m_searcher->setInputCloud(m_input);
// The arrays to be used
pcl::Indices nn_indices(m_k);
std::vector<float> nn_dists(m_k);
for (int i = 0; i < static_cast<int> (m_input->size()); ++i)
{
if (m_searcher->nearestKSearch(m_input->points[i], m_k, nn_indices, nn_dists) > 0)
{
Eigen::Vector4f point_mean;
pcl::compute3DCentroid(*m_input, nn_indices, point_mean);
double neigh_mean_2 = 0.0;
for (size_t idx = 0; idx < nn_indices.size(); ++idx)
{
neigh_mean_2 += m_input->points[nn_indices[idx]].getVector3fMap().squaredNorm();
}
neigh_mean_2 /= nn_indices.size();
double point_mean_2 = point_mean.head<3>().squaredNorm();
double a = (neigh_mean_2 - point_mean_2) / (neigh_mean_2 - point_mean_2 + m_epsilon);
pcl::PointXYZ b;
b.x = (1.0 - a) * point_mean[0];
b.y = (1.0 - a) * point_mean[1];
b.z = (1.0 - a) * point_mean[2];
output.points[i].x = a * m_input->points[i].x + b.x;
output.points[i].y = a * m_input->points[i].y + b.y;
output.points[i].z = a * m_input->points[i].z + b.z;
}
}
}
private:
pcl::PointCloud<PointTin>::Ptr m_input;
SearcherPtr m_searcher;
int m_k = 20;
double m_epsilon = 0.05;
};
}
main
#include <iostream>
#include<pcl/io/pcd_io.h>
#include<pcl/point_cloud.h>
#include"GuildFilter.h"
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
using namespace std;
int main(int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile<pcl::PointXYZ>("bunnyAddGausiss.pcd", *cloud);
// -----------------------------导向滤波---------------------------------
plug::GuildFilter<pcl::PointXYZ, pcl::PointXYZ>gf;
gf.setInputCloud(cloud);
gf.setKsearch(20);
gf.setEpsilonThresh(0.05);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOut(new pcl::PointCloud<pcl::PointXYZ>);
gf.filter(*cloudOut);
pcl::io::savePCDFileBinary("guild_filter.pcd", *cloudOut);
// ------------------------------可视化---------------------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("ShowCloud"));
viewer->setWindowName("点云导向滤波");
int v1(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->setBackgroundColor(0, 0, 0, v1);
viewer->addText("Raw point clouds", 10, 10, "v1_text", v1);
int v2(0);
viewer->createViewPort(0.5, 0.0, 1, 1.0, v2);
viewer->setBackgroundColor(0.1, 0.1, 0.1, v2);
viewer->addText("filtered point clouds", 10, 10, "v2_text", v2);
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> Color(cloud, "z");
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> FilterColor(cloudOut, "z");
viewer->addPointCloud<pcl::PointXYZ>(cloud, Color, "sample cloud", v1);
viewer->addPointCloud<pcl::PointXYZ>(cloudOut, FilterColor, "cloud_filtered", v2);
//view->addCoordinateSystem(1.0);
//view->initCameraParameters();
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return 0;
}