CloudCompare二次开发之如何通过PCL进行点云滤波?

文章目录

  • 0.引言
  • 1.CloudCompare界面设计滤波(filter)按钮
  • 2.PassThrough直通滤波器
  • 3.VoxelGrid体素滤波器
  • 4.UniformSampling均匀采样
  • 5.StatisticalOutlierRemoval统计滤波器
  • 6.RadiusOutlierRemoval半径滤波器
  • 7.ConditionRemoval条件滤波器
  • 8.ProjectInliers投影滤波器
  • 9.ModelOutlierRemoval模型滤波器
  • 10.GaussianKernel高斯滤波器

0.引言

  因笔者课题涉及点云处理,需要通过PCL进行点云数据一系列处理分析,查阅现有网络资料,对常用PCL点云滤波器进行代码实现,本文记录滤波器实现过程。

1.CloudCompare界面设计滤波(filter)按钮

  (1)设计.ui文件
  ①设计按钮
  在这里插入图片描述

  ②编译.ui
  在这里插入图片描述

  (2)修改mainwindow.h文件
  在这里插入图片描述

//点云滤波
void doActionPCLPassThrough(); // 直通滤波器  
void doActionPCLVoxelGrid(); // 体素滤波器  
void doActionPCLUniformSampling(); // 均匀采样  
void doActionPCLStatisticalOutlierRemoval(); // 统计滤波器  
void doActionPCLRadiusOutlierRemoval(); // 半径滤波器  
void doActionPCLConditionRemoval(); // 条件滤波器  
void doActionPCLProjectInliers(); // 投影滤波器  
void doActionPCLModelOutlierRemoval(); // 模型滤波器  
void doActionPCLGaussianKernel(); // 高斯滤波器

  (3)修改mainwindow.cpp文件
  ①添加头文件
  在这里插入图片描述

#include <pcl/filters/passthrough.h>// 直通滤波器
#include <pcl/filters/voxel_grid.h>// 体素滤波器  
#include <pcl/keypoints/uniform_sampling.h>// 均匀采样  
#include <pcl/filters/statistical_outlier_removal.h>// 统计滤波器  
#include <pcl/filters/radius_outlier_removal.h>// 半径滤波器  
#include <pcl/filters/conditional_removal.h>// 条件滤波器  
#include <pcl/filters/project_inliers.h>// 投影滤波器  
#include <pcl/filters/model_outlier_removal.h>// 模型滤波器  
#include <pcl/ModelCoefficients.h>  
#include <pcl/filters/convolution_3d.h>// GaussianKernel高斯滤波器

  ②添加实现代码
  在这里插入图片描述

// 直通滤波器
void MainWindow::doActionPCLPassThrough()  
{  
}  
// 体素滤波器  
void MainWindow::doActionPCLVoxelGrid()  
{  
}  
// 均匀采样  
void MainWindow::doActionPCLUniformSampling()  
{  
}  
// 统计滤波器  
void MainWindow::doActionPCLStatisticalOutlierRemoval()  
{  
}  
// 半径滤波器  
void MainWindow::doActionPCLRadiusOutlierRemoval()  
{  
}  
// 条件滤波器  
void MainWindow::doActionPCLConditionRemoval()  
{  
}  
// 投影滤波器  
void MainWindow::doActionPCLProjectInliers()  
{  
}  
// 模型滤波器  
void MainWindow::doActionPCLModelOutlierRemoval()  
{  
}  
// 高斯滤波器  
void MainWindow::doActionPCLGaussianKernel()  
{  
}

  ③添加信号槽函数
  在这里插入图片描述

connect(m_UI->actionPassThrough, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLPassThrough);//直通滤波器
connect(m_UI->actionVoxelGrid, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLVoxelGrid);//体素滤波器  
connect(m_UI->actionUniformSampling, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLUniformSampling);//均匀采样  
connect(m_UI->actionStatisticalOutlierRemoval, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLStatisticalOutlierRemoval);//统计滤波器  
connect(m_UI->actionRadiusOutlierRemoval, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLRadiusOutlierRemoval);//半径滤波器  
connect(m_UI->actionConditionRemoval, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLConditionRemoval);//条件滤波器  
connect(m_UI->actionProjectInliers, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLProjectInliers);//投影滤波器  
connect(m_UI->actionModelOutlierRemoval, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLModelOutlierRemoval);//模型滤波器  
connect(m_UI->actionGaussianKernel, &amp;QAction::triggered, this, &amp;MainWindow::doActionPCLGaussianKernel);//GaussianKernel高斯滤波器

  (4)生成
  在这里插入图片描述

2.PassThrough直通滤波器

  (1)实现代码

// 直通滤波器
void MainWindow::doActionPCLPassThrough()  
{  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    // -----------------------------对话框---------------------------------------  
    //float radius = QInputDialog::getDouble(this, QStringLiteral("参数设置"), QStringLiteral("搜索半径: "), 0.1, 0, 100, 4);  
    // ----------------------------直通滤波器--------------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    pcl::PassThrough<pcl::PointXYZ> us;  
    us.setInputCloud(cloud);  
    us.setFilterFieldName("z");//设置滤波所需字段z  
    us.setFilterLimits(-0.1,1);//设置z字段过滤范围  
    us.setFilterLimitsNegative(true);//默认false,保留范围内的点云;true,保存范围外的点云  
    us.filter(*filtered);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (!filtered->empty())  
    {  
        ccPointCloud* newPointCloud = new ccPointCloud(QString("PassThrough"));  
        for (int i = 0; i < filtered->size(); ++i)  
        {  
            double x = filtered->points[i].x;  
            double y = filtered->points[i].y;  
            double z = filtered->points[i].z;  
            newPointCloud->addPoint(CCVector3(x, y, z));  
        }  
        newPointCloud->setRGBColor(ccColor::Rgba(255, 255, 255, 255));  
        newPointCloud->showColors(true);  
        if (ccCloud->getParent())  
        {  
            ccCloud->getParent()->addChild(newPointCloud);  
        }  
        ccCloud->setEnabled(false);  
        addToDB(newPointCloud);  
        refreshAll();  
        updateUI();  
    }  
    else  
    {  
        ccCloud->setEnabled(true);  
        // Display a warning message in the console  
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);  
    }  
}

  (2)滤波结果
  ①滤波前
  在这里插入图片描述

  ②滤波后
  在这里插入图片描述

3.VoxelGrid体素滤波器

  (1)实现代码

// 体素滤波器
void MainWindow::doActionPCLVoxelGrid()  
{  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    // -----------------------------对话框---------------------------------------  
    float radius = QInputDialog::getDouble(this, QStringLiteral("参数设置"), QStringLiteral("体素大小: "), 0.1, 0, 100, 4);  
    // ----------------------------体素滤波器--------------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    pcl::VoxelGrid<pcl::PointXYZ> us;  
    us.setInputCloud(cloud);  
    us.setLeafSize(radius, radius, radius);  
    us.filter(*filtered);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (!filtered->empty())  
    {  
        ccPointCloud* newPointCloud = new ccPointCloud(QString("VoxelGrid"));  
        for (int i = 0; i < filtered->size(); ++i)  
        {  
            double x = filtered->points[i].x;  
            double y = filtered->points[i].y;  
            double z = filtered->points[i].z;  
            newPointCloud->addPoint(CCVector3(x, y, z));  
        }  
        newPointCloud->setRGBColor(ccColor::Rgba(255, 255, 255, 255));  
        newPointCloud->showColors(true);  
        if (ccCloud->getParent())  
        {  
            ccCloud->getParent()->addChild(newPointCloud);  
        }  
        ccCloud->setEnabled(false);  
        addToDB(newPointCloud);  
        refreshAll();  
        updateUI();  
    }  
    else  
    {  
        ccCloud->setEnabled(true);  
        // Display a warning message in the console  
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);  
    }  
}

  (2)滤波结果
  ①滤波前
  在这里插入图片描述

  ②滤波后
  在这里插入图片描述

4.UniformSampling均匀采样

  (1)实现代码

// 均匀采样
void MainWindow::doActionPCLUniformSampling()  
{  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    // -----------------------------对话框---------------------------------------  
    float radius = QInputDialog::getDouble(this, QStringLiteral("参数设置"), QStringLiteral("搜索半径: "), 0.1, 0, 100, 4);  
    // ----------------------------均匀采样--------------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    pcl::UniformSampling<pcl::PointXYZ> us;  
    us.setInputCloud(cloud);  
    us.setRadiusSearch(radius);  
    us.filter(*filtered);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (!filtered->empty())  
    {  
        ccPointCloud* newPointCloud = new ccPointCloud(QString("UniformSampling"));  
        for (int i = 0; i < filtered->size(); ++i)  
        {  
            double x = filtered->points[i].x;  
            double y = filtered->points[i].y;  
            double z = filtered->points[i].z;  
            newPointCloud->addPoint(CCVector3(x, y, z));  
        }  
        newPointCloud->setRGBColor(ccColor::Rgba(255, 255, 255, 255));  
        newPointCloud->showColors(true);  
        if (ccCloud->getParent())  
        {  
            ccCloud->getParent()->addChild(newPointCloud);  
        }  
        ccCloud->setEnabled(false);  
        addToDB(newPointCloud);  
        refreshAll();  
        updateUI();  
    }  
    else  
    {  
        ccCloud->setEnabled(true);  
        // Display a warning message in the console  
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);  
    }  
}

  (2)滤波结果
  ①滤波前
  在这里插入图片描述

  ②滤波后
  在这里插入图片描述

5.StatisticalOutlierRemoval统计滤波器

  (1)实现代码

// 统计滤波器
void MainWindow::doActionPCLStatisticalOutlierRemoval()  
{  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    // -----------------------------对话框---------------------------------------  
    //float radius = QInputDialog::getDouble(this, QStringLiteral("参数设置"), QStringLiteral("搜索半径: "), 0.1, 0, 100, 4);  
    // ----------------------------统计滤波器--------------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> us;  
    us.setInputCloud(cloud);        //设置待滤波点云  
    us.setMeanK(50);        //设置查询点近邻点的个数  
    us.setStddevMulThresh(1.0);                //设置标准差乘数,来计算是否为离群点的阈值  
    //sor.setNegative(true);        //默认false,保存内点;true,保存滤掉的离群点  
    us.filter(*filtered);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (!filtered->empty())  
    {  
        ccPointCloud* newPointCloud = new ccPointCloud(QString("StatisticalOutlierRemoval"));  
        for (int i = 0; i < filtered->size(); ++i)  
        {  
            double x = filtered->points[i].x;  
            double y = filtered->points[i].y;  
            double z = filtered->points[i].z;  
            newPointCloud->addPoint(CCVector3(x, y, z));  
        }  
        newPointCloud->setRGBColor(ccColor::Rgba(255, 255, 255, 255));  
        newPointCloud->showColors(true);  
        if (ccCloud->getParent())  
        {  
            ccCloud->getParent()->addChild(newPointCloud);  
        }  
        ccCloud->setEnabled(false);  
        addToDB(newPointCloud);  
        refreshAll();  
        updateUI();  
    }  
    else  
    {  
        ccCloud->setEnabled(true);  
        // Display a warning message in the console  
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);  
    }  
}

  (2)滤波结果
  ①滤波前
  在这里插入图片描述

  ②滤波后
  在这里插入图片描述

6.RadiusOutlierRemoval半径滤波器

  (1)实现代码

// 半径滤波器
void MainWindow::doActionPCLRadiusOutlierRemoval()  
{  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    // -----------------------------对话框---------------------------------------  
    float radius = QInputDialog::getDouble(this, QStringLiteral("参数设置"), QStringLiteral("半径: "), 0.05, 0, 100, 4);  
    // ----------------------------半径滤波器--------------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    pcl::RadiusOutlierRemoval<pcl::PointXYZ> us;  
    us.setInputCloud(cloud);        //设置待滤波点云  
    us.setRadiusSearch(radius);        //设置查询点的半径范围  
    us.setMinNeighborsInRadius(5);        //设置判断是否为离群点的阈值,即半径内至少包括的点数  
    us.setNegative(true);        //默认false,保存内点;true,保存滤掉的外点  
    us.filter(*filtered);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (!filtered->empty())  
    {  
        ccPointCloud* newPointCloud = new ccPointCloud(QString("RadiusOutlierRemoval"));  
        for (int i = 0; i < filtered->size(); ++i)  
        {  
            double x = filtered->points[i].x;  
            double y = filtered->points[i].y;  
            double z = filtered->points[i].z;  
            newPointCloud->addPoint(CCVector3(x, y, z));  
        }  
        newPointCloud->setRGBColor(ccColor::Rgba(255, 255, 255, 255));  
        newPointCloud->showColors(true);  
        if (ccCloud->getParent())  
        {  
            ccCloud->getParent()->addChild(newPointCloud);  
        }  
        ccCloud->setEnabled(false);  
        addToDB(newPointCloud);  
        refreshAll();  
        updateUI();  
    }  
    else  
    {  
        ccCloud->setEnabled(true);  
        // Display a warning message in the console  
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);  
    }  
}

  (2)滤波结果
  ①滤波前
  在这里插入图片描述

  ②滤波后
  在这里插入图片描述

7.ConditionRemoval条件滤波器

  (1)实现代码

// 条件滤波器
void MainWindow::doActionPCLConditionRemoval()  
{  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    // -----------------------------对话框---------------------------------------  
    //float radius = QInputDialog::getDouble(this, QStringLiteral("参数设置"), QStringLiteral("搜索半径: "), 0.1, 0, 100, 4);  
    // ----------------------------条件滤波器--------------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    /*创建条件限定下的滤波器*/  
    pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());//创建条件定义对象range_cond  
    //为条件定义对象添加比较算子  
    range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new  
        pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::GT, -0.1)));//添加在x字段上大于 -0.1 的比较算子  
  
    range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new  
        pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::LT, 1.0)));//添加在x字段上小于 1.0 的比较算子  
  
    pcl::ConditionalRemoval<pcl::PointXYZ> us;        //创建滤波器对象  
    us.setCondition(range_cond);                //用条件定义对象初始化  
    us.setInputCloud(cloud);                //设置待滤波点云  
    us.filter(*filtered);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (!filtered->empty())  
    {  
        ccPointCloud* newPointCloud = new ccPointCloud(QString("ConditionRemoval"));  
        for (int i = 0; i < filtered->size(); ++i)  
        {  
            double x = filtered->points[i].x;  
            double y = filtered->points[i].y;  
            double z = filtered->points[i].z;  
            newPointCloud->addPoint(CCVector3(x, y, z));  
        }  
        newPointCloud->setRGBColor(ccColor::Rgba(255, 255, 255, 255));  
        newPointCloud->showColors(true);  
        if (ccCloud->getParent())  
        {  
            ccCloud->getParent()->addChild(newPointCloud);  
        }  
        ccCloud->setEnabled(false);  
        addToDB(newPointCloud);  
        refreshAll();  
        updateUI();  
    }  
    else  
    {  
        ccCloud->setEnabled(true);  
        // Display a warning message in the console  
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);  
    }  
}

  (2)滤波结果
  ①滤波前
  在这里插入图片描述

  ②滤波后
  在这里插入图片描述

8.ProjectInliers投影滤波器

  (1)实现代码

// 投影滤波器
void MainWindow::doActionPCLProjectInliers()  
{  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    // -----------------------------对话框---------------------------------------  
    float radius = QInputDialog::getDouble(this, QStringLiteral("参数设置"), QStringLiteral("搜索半径: "), 0.1, 0, 100, 4);  
    // ----------------------------投影滤波器--------------------------------------  
    //创建 x+y+z=0 平面  
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());  
    coefficients->values.resize(4);        //设置模型系数的大小  
    coefficients->values[0] = 1.0;        //x系数  
    coefficients->values[1] = 1.0;        //y系数  
    coefficients->values[2] = 1.0;        //z系数  
    coefficients->values[3] = 0.0;        //常数项  
    //投影滤波  
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    pcl::ProjectInliers<pcl::PointXYZ> us;  
    us.setModelType(pcl::SACMODEL_PLANE);        //设置对象对应的投影模型  
    us.setInputCloud(cloud);                //设置输入点云  
    us.setModelCoefficients(coefficients);//设置模型对应的系数  
    us.filter(*filtered);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (!filtered->empty())  
    {  
        ccPointCloud* newPointCloud = new ccPointCloud(QString("ProjectInliers"));  
        for (int i = 0; i < filtered->size(); ++i)  
        {  
            double x = filtered->points[i].x;  
            double y = filtered->points[i].y;  
            double z = filtered->points[i].z;  
            newPointCloud->addPoint(CCVector3(x, y, z));  
        }  
        newPointCloud->setRGBColor(ccColor::Rgba(255, 255, 255, 255));  
        newPointCloud->showColors(true);  
        if (ccCloud->getParent())  
        {  
            ccCloud->getParent()->addChild(newPointCloud);  
        }  
        ccCloud->setEnabled(false);  
        addToDB(newPointCloud);  
        refreshAll();  
        updateUI();  
    }  
    else  
    {  
        ccCloud->setEnabled(true);  
        // Display a warning message in the console  
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);  
    }  
}

  (2)滤波结果
  ①滤波前
  在这里插入图片描述

  ②滤波后
  在这里插入图片描述

9.ModelOutlierRemoval模型滤波器

  (1)实现代码

// 模型滤波器
void MainWindow::doActionPCLModelOutlierRemoval()  
{  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    // -----------------------------对话框---------------------------------------  
    //float radius = QInputDialog::getDouble(this, QStringLiteral("参数设置"), QStringLiteral("搜索半径: "), 0.1, 0, 100, 4);  
    // ----------------------------模型滤波器--------------------------------------  
    //设置模型系数  
    pcl::ModelCoefficients model_coeff;  
    model_coeff.values.resize(4);  
    model_coeff.values[0] = 1.0;  
    model_coeff.values[1] = 1.0;  
    model_coeff.values[2] = 1.0;  
    model_coeff.values[3] = 0.0;  
    ///模型滤波  
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    pcl::ModelOutlierRemoval<pcl::PointXYZ> us;  
    us.setModelCoefficients(model_coeff);                //为模型对象添加模型系数  
    us.setThreshold(0.1);                //设置判断是否为模型内点的阈值  
    us.setModelType(pcl::SACMODEL_PLANE);                //设置模型类别  
    us.setInputCloud(cloud);                //输入待滤波点云  
    us.setNegative(true);        //默认false,保存内点;true,保存滤掉的外点  
    us.filter(*filtered);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (!filtered->empty())  
    {  
        ccPointCloud* newPointCloud = new ccPointCloud(QString("ModelOutlierRemoval"));  
        for (int i = 0; i < filtered->size(); ++i)  
        {  
            double x = filtered->points[i].x;  
            double y = filtered->points[i].y;  
            double z = filtered->points[i].z;  
            newPointCloud->addPoint(CCVector3(x, y, z));  
        }  
        newPointCloud->setRGBColor(ccColor::Rgba(255, 255, 255, 255));  
        newPointCloud->showColors(true);  
        if (ccCloud->getParent())  
        {  
            ccCloud->getParent()->addChild(newPointCloud);  
        }  
        ccCloud->setEnabled(false);  
        addToDB(newPointCloud);  
        refreshAll();  
        updateUI();  
    }  
    else  
    {  
        ccCloud->setEnabled(true);  
        // Display a warning message in the console  
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);  
    }  
}

  (2)滤波结果
  ①滤波前
  在这里插入图片描述

  ②滤波后
  在这里插入图片描述

10.GaussianKernel高斯滤波器

  (1)实现代码

// 高斯滤波器
void MainWindow::doActionPCLGaussianKernel()  
{  
    if (getSelectedEntities().size() != 1)  
    {  
        ccLog::Print(QStringLiteral("只能选择一个点云实体"));  
    return;  
    }  
    ccHObject* entity = getSelectedEntities()[0];  
    ccPointCloud* ccCloud = ccHObjectCaster::ToPointCloud(entity);  
    // ---------------------------读取数据到PCL----------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);  
    cloud->resize(ccCloud->size());  
    for (int i = 0; i < cloud->size(); ++i)  
    {  
        const CCVector3* point = ccCloud->getPoint(i);  
        cloud->points[i].x = point->x;  
        cloud->points[i].y = point->y;  
        cloud->points[i].z = point->z;  
    }  
    // -----------------------------对话框---------------------------------------  
    float radius = QInputDialog::getDouble(this, QStringLiteral("参数设置"), QStringLiteral("搜索半径: "), 0.1, 0, 100, 4);  
    // ----------------------------高斯滤波器--------------------------------------  
    pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);  
    //pcl::BilateralFilter<pcl::PointXYZ> us;  
    //-----------基于高斯核函数的卷积滤波实现------------------------  
    pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ> kernel;  
    kernel.setSigma(4);//高斯函数的标准方差,决定函数的宽度  
    kernel.setThresholdRelativeToSigma(4);//设置相对Sigma参数的距离阈值  
    kernel.setThreshold(0.05);//设置距离阈值,若点间距离大于阈值则不予考虑  
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);  
    tree->setInputCloud(cloud);  
    //---------设置Convolution 相关参数---------------------------  
    pcl::filters::Convolution3D<pcl::PointXYZ, pcl::PointXYZ, pcl::filters::GaussianKernel<pcl::PointXYZ, pcl::PointXYZ>> convolution;  
    convolution.setKernel(kernel);//设置卷积核  
    convolution.setInputCloud(cloud);  
    convolution.setNumberOfThreads(8);  
    convolution.setSearchMethod(tree);  
    convolution.setRadiusSearch(radius);  
    convolution.convolve(*filtered);  
    // ------------------------PCL->CloudCompare--------------------------------  
    if (!filtered->empty())  
    {  
        ccPointCloud* newPointCloud = new ccPointCloud(QString("GaussianKernel"));  
        for (int i = 0; i < filtered->size(); ++i)  
        {  
            double x = filtered->points[i].x;  
            double y = filtered->points[i].y;  
            double z = filtered->points[i].z;  
            newPointCloud->addPoint(CCVector3(x, y, z));  
        }  
        newPointCloud->setRGBColor(ccColor::Rgba(255, 255, 255, 255));  
        newPointCloud->showColors(true);  
        if (ccCloud->getParent())  
        {  
            ccCloud->getParent()->addChild(newPointCloud);  
        }  
        ccCloud->setEnabled(false);  
        addToDB(newPointCloud);  
        refreshAll();  
        updateUI();  
    }  
    else  
    {  
        ccCloud->setEnabled(true);  
        // Display a warning message in the console  
        dispToConsole("Warning: example shouldn't be used as is", ccMainAppInterface::WRN_CONSOLE_MESSAGE);  
    }  
}

  (2)滤波结果
  ①滤波前
  在这里插入图片描述

  ②滤波后
  在这里插入图片描述

参考资料:
[1] 来吧!我在未来等你!. CloudCompare二次开发之如何配置PCL点云库?; 2023-05-14 [accessed 2023-05-15].
[2] 悠缘之空. PCL函数库摘要——点云滤波; 2021-05-30 [accessed 2023-05-15].
[3] 孙 悟 空. PCL:点云滤波汇总:算法原理 + 代码实现; 2021-03-08 [accessed 2023-05-15].
[4] 学习OpenCV. PCL点云滤波器总结; 2022-03-03 [accessed 2023-05-15].
[5] 学习OpenCV. PCL点云处理_点云滤波(3); 2022-03-03 [accessed 2023-05-15].
[6] 点云侠. PCL 高斯滤波; 2021-02-27 [accessed 2023-05-15].

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/19879.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

写给程序员Android Framework 开发,

前言 在 Android 开发者技能中&#xff0c;如果想进大厂&#xff0c;一般拥有较好的学历可能有优势一些。但是如果你靠硬实力也是有机会的&#xff0c;例如死磕Framework。Framework 知识广泛应用在Android各个领域中&#xff0c;重要性显而易见。 成为一名Android Framework…

maven学习总结

生命周期 每个生命周期的各个环节都是由各种插件完成&#xff01;&#xff01;&#xff01;Maven有三个相互独立的生命周期&#xff08;Maven的这三个生命周期不能看成一个整体&#xff09;&#xff01;&#xff01;&#xff01; 我们在开发中描述的项目的生命周期&#xff0…

互联网营销之何谓真需求-想知道如何挖掘真需求看这篇就对了

互联网营销思维是以爆品为核心的迭代思维&#xff0c;本文结合“生日蛋糕”、“方便面”、“蜜雪冰城”几个小例子&#xff0c;以及我们具体的工作&#xff0c;展开聊聊什么是“真需求”。 1. 互联网营销和传统营销的区别 1.1 传统的营销思维&#xff1a; “定位4P&#xff0…

如何修复d3dcompiler_47.dll缺失?多种解决方法分享

在使用Windows操作系统的过程中&#xff0c;有时候会遇到d3dcompiler_47.dll缺失的情况。这个问题可能会导致某些应用程序无法正常运行&#xff0c;因此需要及时解决。本文将介绍如何修复d3dcompiler_47.dll缺失的问题。 一.什么是d3dcompiler_47.dll D3dcompiler_47.dll是Di…

基于html+css图展示57

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

前后端图片交互的简易方式

前后端图片交互的简易方式 一、交互方式说明二、前后端具体代码实现前端具体代码实现后端具体代码实现效果 测试结果 一、交互方式说明 在项目的实际开发中&#xff0c;难免会遇到前端需要渲染数据库中保存的图片&#xff0c;那咱知道图片也属于一种文件&#xff0c;不好保存到…

【零基础QQ机器人开发三】程序上云篇

前言&#xff1a;本文为大家带来QQ机器人程序上云的教程&#xff0c;环境搭建请参考下面链接 【0基础QQ机器人开发】基于go-cqhttp的QQ机器人开发教程,仅供自学 【零基础QQ机器人开发二】服务器篇 文章目录 程序Logger类StatuStore类MultiFunc类QQBot类main.py 前言&#xff1a…

高级Web题库

高级Web题库 For ZPT 声明 一切开发旨在学习&#xff0c;请勿用于非法用途 by rick rick 关注 永雏塔菲喵 永雏塔菲喵 选择题 第1题 知识点&#xff1a;CSS 题目&#xff1a;设置text-decoration属性的删除线的值为&#xff08; &#xff09;。 选项&#xff1a; A underlin…

Pytest自动化测试框架一些常见的插件

Pytest拥有丰富的插件架构&#xff0c;超过800个以上的外部插件和活跃的社区&#xff0c;在PyPI项目中以“ pytest- *”为标识。 本篇将列举github标星超过两百的一些插件进行实战演示。 插件库地址&#xff1a;http://plugincompat.herokuapp.com/ 1、pytest-html&#xff…

冗余-安全设计的基石

冗余构成原理就是在系统中采用2套中央处理器&#xff08;CPU&#xff09;单元&#xff0c;其中1套为工作主机&#xff0c;1套为热备&#xff0c;一旦工作主机发生故障&#xff0c;热备的CPU将自动投入工作&#xff0c;此时热备的CPU变为工作主机&#xff0c;原工作主机故障处理…

a标签属性href的多种写法

众所周知&#xff0c;a标签的最重要功能是实现超链接和锚点。而且&#xff0c;大多数人认为a标签最重要的作用是实现超链接&#xff0c;其实不单单是实现超链接的方法&#xff0c;今天新起点博客就来整理下a标签中href的几种用法。 1、a href“[removed]js_method();” 这是常用…

Android aidl及binder基础知识巩固

作者&#xff1a;义华 1、什么是binder binder是android framework提供的&#xff0c;用于跨进程方法调用的机制&#xff0c;具有安全高效等特点。 我们知道&#xff0c;在 Android 系统中&#xff0c;每个应用程序都运行在一个独立的进程中&#xff0c;各个进程之间需要进行…

chatGPT提问,BGP内容

ChatGPT提问&#xff1a;提问框架 背景角色任务要求 动态路由&#xff1a;内部网关协议&#xff1a;如RIP ISIS OSPF 在同一个公司内部运行的路由协议 外部网关协议&#xff1a;如 BGP 在不同公司之间运行的路由协议 AS&#xff1a;自治系统 每个自治系统都有唯一的…

玩机搞机-----安卓全机型 ADB FAST 各种指令解析说明与操作【二】基础联机

安卓全机型 玩机 搞机 ADB FAST 各种指令解析说明与操作_adb线刷命令_安卓机器的博客-CSDN博客 今天对上个帖子不足的地方进行补正。方便友友进行基础的联机操作&#xff0c;很多时候我们用adb指令的时候会有各种奇奇怪怪的问题。例如同一个机型&#xff0c;同一个指令。有时候…

OpenCL编程指南-4.4矢量操作符

矢量操作符 如下描述了可用于矢量数据类型或矢量和标量数据类型组合的各类操作符。 算术操作符 算术操作符&#xff08;加&#xff08;)、减&#xff08;–)、乘&#xff08;*&#xff09;和除&#xff08;/)&#xff09;&#xff0c;可以作用于内置整数、浮点标量和矢量数…

AWS 中的另外一种远程工具 AWS Session Manager

作者&#xff1a;SRE运维博客 博客地址&#xff1a;https://www.cnsre.cn/ 文章地址&#xff1a;https://www.cnsre.cn/posts/230129126154/ 相关话题&#xff1a;https://www.cnsre.cn/tags/aws/ 背景需求 因为项目的安全性。为了避免项目的服务器暴露在公网中。很多时候我们…

Python时间模块:time和datetime的区别与用法

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 目录标题 前言一. Python中表示时间的两种方式&#xff1a;二. time三. datetime1. datetime.datetime2.datetime.timedelta 尾语 &#x1f49d; 一. Python中表示时间的两种方式&#xff1a; 时间戳&#xff1a;相对于197…

OpenCL编程指南-3.2OpenCL上下文

OpenCL上下文 上下文是所有OpenCL应用的核心。上下文为关联的设备、内存对象&#xff08;例如&#xff0c;缓冲区和图像&#xff09;以及命令队列&#xff08;在上下文和各设备之间提供一个接口&#xff09;提供了一个容器。正是上下文驱动着应用程序与特定设备以及特定设备之…

Echarts 热力图的详细配置过程

文章目录 一&#xff0c;配置过程二&#xff0c;具体实例 一&#xff0c;配置过程 引入Echarts库和热力图插件 <script src"https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script> <script src"https://cdn.jsdelivr.net/npm/…

实时聊天如何做,让客户眼前一亮(二)

让我们继续讨论一下如何利用SaleSmartly&#xff08;ss客服&#xff09;在网站中的实时聊天视图如何提供出色的实时聊天体验。 四、在实时聊天会话期间 让我们来看看我们可以确保尽可能的提高客户体验的各种方法&#xff0c;使用SaleSmartly&#xff08;ss客服&#xff09;时聊…