PCL模型滤波(model_outlier_removal)

1.原理

生成一个模型,通过点云各点和此模型之间的相似程度(通过点云点和模型之间的距离阈值判断相似程度:小于距离阈值的即为相似点,保留;大于距离阈值的即为非相似点,不保留),筛选同模型相似的点云点,生成结果点云。

(1)生成模型(PCL支持模型类型附在文末)。

(2)通过距离阈值判断模型到点云点之间的距离,筛选小于该用户设定的距离阈值的点云

(3)将筛选出来的点云生成新点云。

原理介绍如下图所示(以平面模型滤波举例):

想象平面A为我们设定好的平面模型,这些点为散列点云,距离阈值设定为m。

我们将所有的散列点计算得到该点到平面A的距离n,如果n<m,则保留,如果n>m则不保留。

2.使用场景

例如提取地面;还有其他裁剪某些有特殊形状的物体,诸如用圆柱体模型裁剪点云得到一棵树的点云等等。

3.注意事项

本示例代码中添加了三个点计算平面方程的C++实现,可自行取用。

// 计算三维平面公式Ax + By + Cz + D = 0中的各个系数(三点确定一个平面
double x1 = 143.01;    double y1 = 49.68;    double z1 = 24.53;
double x2 = 159.08;    double y2 = 44.23;    double z2 = 24.67;
double x3 = 161.39;    double y3 = 51.24;    double z3 = 24.5;
double A = (y3 - y1) * (z3 - z1) - (z2 - z1) * (y3 - y1);
double B = (x3 - x1) * (z2 - z1) - (x2 - x1) * (z3 - z1);
double C = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
double D = -(A * x1 + B * y1 + C * z1);

4.关键函数

(1)设置距离阈值:判断模型到点云点之间的距离,已确定是否保留该点云点。

setThreshold()

(2)设置模型类型(可设置的类型附在文末)

setModelType()

5.代码

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/model_outlier_removal.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

int main()
{
    /****************模型滤波********************/
    // 原始点云
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::io::loadPCDFile("D:/code/csdn/data/JZDM.pcd", *cloud);   // 加载原始点云数据
    // 结果点云
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZRGB>);

    // 设置模型
    // 计算三维平面公式ax+by+cz+d = 0中的各个系数(三点确定一个平面)   测试示例使用,平常如果知道平面系数不用计算,如果不知道,取三个点用以下公式计算即可
    double x1 = 143.01;    double y1 = 49.68;    double z1 = 24.53;
    double x2 = 159.08;    double y2 = 44.23;    double z2 = 24.67;
    double x3 = 161.39;    double y3 = 51.24;    double z3 = 24.5;
    double A = (y3 - y1) * (z3 - z1) - (z2 - z1) * (y3 - y1);
    double B = (x3 - x1) * (z2 - z1) - (x2 - x1) * (z3 - z1);
    double C = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
    double D = -(A * x1 + B * y1 + C * z1);

    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);           // 模型系数
    coefficients->values.resize(4);
    coefficients->values[0] = A;                                                    // 设置各系数
    coefficients->values[1] = B;
    coefficients->values[2] = C;
    coefficients->values[3] = D;

    // 模型滤波
    pcl::ModelOutlierRemoval<pcl::PointXYZRGB> filter;
    filter.setModelCoefficients(*coefficients);                                     // 设置模型系数
    filter.setThreshold(10.0);                                                      // 距离阈值(即实际点云点到模型面之间的距离)
    filter.setModelType(pcl::SACMODEL_PLANE);                                       // 设置SAC模型类型
    filter.setInputCloud(cloud);
    filter.filter(*cloud_filtered);

    /****************展示********************/
    boost::shared_ptr<pcl::visualization::PCLVisualizer> view_raw(new pcl::visualization::PCLVisualizer("raw"));
    view_raw->addPointCloud<pcl::PointXYZRGB>(cloud, "raw cloud");
    view_raw->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "raw cloud");

    boost::shared_ptr<pcl::visualization::PCLVisualizer> view_filtered(new pcl::visualization::PCLVisualizer("filter"));
    view_filtered->addPointCloud<pcl::PointXYZRGB>(cloud_filtered, "filtered cloud");
    view_filtered->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "filtered cloud");

    while (!view_raw->wasStopped())
    {
        view_raw->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }
    while (!view_filtered->wasStopped())
    {
        view_filtered->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }

    return 0;
}

6.结果展示

7.附PCL支持模型类型

  • SACMODEL_PLANE 平面模型
  • SACMODEL_LINE 直线模型
  • SACMODEL_CIRCLE2D 2d圆模型
  • SACMODEL_CIRCLE3D 3d圆模型
  • SACMODEL_SPHERE 球模型
  • SACMODEL_CYLINDER 圆柱模型
  • SACMODEL_CONE 圆锥模型
  • SACMODEL_TORUS 圆环模型,目前还未实现
  • SACMODEL_PARALLEL_LINE 和给定轴平行的直线
  • SACMODEL_PERPENDICULAR_PLANE 和给定轴垂直的平面
  • SACMODEL_NORMAL_PLANE 拟合一个平面,用于拟合的内点的法相量与最后输出的平面之间法相量的夹角必须小于某个阈值
  • SACMODEL_NORMAL_SPHERE 拟合一个球,用于拟合的内点的法相量与最后输出的球面之间法相量的夹角必须小于某个阈值
  • SACMODEL_PARALLEL_PLANE 拟合出和给定轴平行的平面
  • SACMODEL_NORMAL_PARALLEL_PLANE 拟合一个平面,其约束条件为 SACMODEL_NORMAL_PLANE + SACMODEL_PERPENDICULAR_PLANE
  • SACMODEL_STICK 棒状模型
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`pcl::SACMODEL_CIRCLE3D`是[PCL库](https://pcl.readthedocs.io/projects/tutorials/en/latest/)中的一个模型,用于拟合3D点云中的圆。该模型可以在噪声和异常值存在的情况下,从三维空间中的点云中计算出一个最优拟合圆,以及圆上的内外点。 以下是使用`pcl::SACMODEL_CIRCLE3D`模型拟合点云的步骤: 1. 加载点云数据,将其转换为`pcl::PointCloud<pcl::PointXYZ>`格式; 2. 创建一个`pcl::SACSegmentation<pcl::PointXYZ>`对象; 3. 设置模型类型为`pcl::SACMODEL_CIRCLE3D`; 4. 设置其他参数,例如最小拟合点数、迭代次数和距离阈值等; 5. 使用`pcl::ModelCoefficients`和`pcl::PointIndices`存储拟合结果; 6. 调用`pcl::SACSegmentation`对象的`segment`方法进行拟合; 7. 从结果中提取拟合的圆心和半径; 以下是代码示例: ```cpp pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile<pcl::PointXYZ>("cloud.pcd", *cloud); pcl::SACSegmentation<pcl::PointXYZ> seg; seg.setOptimizeCoefficients(true); seg.setModelType(pcl::SACMODEL_CIRCLE3D); seg.setMethodType(pcl::SAC_RANSAC); seg.setDistanceThreshold(0.01); seg.setInputCloud(cloud); seg.setRadiusLimits(0, 0.1); pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients); pcl::PointIndices::Ptr inliers(new pcl::PointIndices); seg.segment(*inliers, *coefficients); Eigen::Vector3f center(coefficients->values, coefficients->values, coefficients->values); float radius = coefficients->values; std::cout << "Fitted circle center: " << center << std::endl; std::cout << "Fitted circle radius: " << radius << std::endl; ``` 其中,`cloud.pcd`是一个点云文件,包含需要拟合的点云数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值