• PCL补充之滤波、提取、配准方法


    0. 简介

    最近在看PCL滤波配准等操作,之前在自动驾驶-激光雷达预处理/特征提取和提到了一些滤除点云等操作,但是最近作者发现里面还有一些配准的方法还没有提到,所以这里重新开个章节来给大家列举一些常用的滤波方式,方便大家查阅和使用

    1. 滤波&聚类

    1.1 直通滤波器

    void pass_through_filter(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr &input_cloud) //直通滤波器
        {
            std::cout << "start pass_through_filter" << std::endl;
            calc_sight_center(); //计算视点中心,视点中心为滤波器的输入参数
            // void ex_segmentor::calc_sight_center()
            // {
            // double roll, pitch, yaw;
            // tf::Quaternion quat_tmp;
    
            // tf::quaternionMsgToTF(latest_camera_pos_.pose.pose.orientation, quat_tmp);
            // tf::Matrix3x3(quat_tmp).getRPY(roll, pitch, yaw);
    
            // centerX_ = latest_camera_pos_.pose.pose.position.x + gaze_length_ * cos(yaw);
            // centerY_ = latest_camera_pos_.pose.pose.position.y + gaze_length_ * sin(yaw);
            // centerZ_ = latest_camera_pos_.pose.pose.position.z - gaze_length_ * sin(pitch);
            // }
            // build the condition
            pcl::ConditionAnd<pcl::PointXYZRGB>::Ptr range_limit(new pcl::ConditionAnd<pcl::PointXYZRGB>);                                                                         //构建范围限制条件
            range_limit->addComparison(pcl::FieldComparison<pcl::PointXYZRGB>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZRGB>("x", pcl::ComparisonOps::GT, centerX_ - 1.5))); // x坐标大于视点中心x坐标-1.5
            range_limit->addComparison(pcl::FieldComparison<pcl::PointXYZRGB>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZRGB>("x", pcl::ComparisonOps::LT, centerX_ + 1.5))); // x坐标小于视点中心x坐标+1.5
            range_limit->addComparison(pcl::FieldComparison<pcl::PointXYZRGB>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZRGB>("y", pcl::ComparisonOps::GT, centerY_ - 1.5))); // y坐标大于视点中心y坐标-1.5
            range_limit->addComparison(pcl::FieldComparison<pcl::PointXYZRGB>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZRGB>("y", pcl::ComparisonOps::LT, centerY_ + 1.5))); // y坐标小于视点中心y坐标+1.5
            range_limit->addComparison(pcl::FieldComparison<pcl::PointXYZRGB>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZRGB>("z", pcl::ComparisonOps::GT, centerZ_ - 1.5))); // z坐标大于视点中心z坐标-1.5
            range_limit->addComparison(pcl::FieldComparison<pcl::PointXYZRGB>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZRGB>("z", pcl::ComparisonOps::LT, centerZ_ + 1.5))); // z坐标小于视点中心z坐标+1.5
    
            //构建滤波器
            pcl::ConditionalRemoval<pcl::PointXYZRGB> condrem; //构建滤波器
            condrem.setCondition(range_limit);                 //设置滤波条件
            condrem.setInputCloud(input_cloud);                //设置输入点云
    
            //滤波操作
            condrem.filter(*input_cloud);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    1.2 离群点滤波器

        void statical_outlier_filter(const pcl::PointCloud<PointXYZRGB>::Ptr &input_cloud, int nr_k, double stddev_mult) //滤波器移除离群点
        {
            pcl::StatisticalOutlierRemoval<PointXYZRGB> sorfilter(true); //构建滤波器
            sorfilter.setInputCloud(input_cloud);
            sorfilter.setMeanK(nr_k);                  //设置在进行统计时考虑的临近点个数
            sorfilter.setStddevMulThresh(stddev_mult); //设置判断是否为离群点的阀值,用来倍乘标准差,也就是上面的stddev_mult
            sorfilter.filter(*input_cloud);            //滤波结果存储到cloud_filtered
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1.3 体素化滤波器

        void voxel_filter(const pcl::PointCloud<PointXYZRGB>::Ptr &input_cloud, float resolution) //体素化滤波器
        {
            pcl::VoxelGrid<PointXYZRGB> voxel_grid; //构建体素化滤波器
            voxel_grid.setInputCloud(input_cloud);   //设置输入点云
            voxel_grid.setLeafSize(resolution, resolution, resolution); //设置体素的大小
            voxel_grid.filter(*input_cloud); //滤波结果存储到cloud_filtered
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.4 平面点滤除

        bool remove_plane(const pcl::PointCloud<PointXYZRGB>::Ptr &input_cloud, const Eigen::Vector3f &axis, double plane_thickness) //移除平面
        {
            pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients); //平面参数矩阵
            pcl::PointIndices::Ptr inliers(new pcl::PointIndices);                //平面内点索引
            // Create the segmentation object
            pcl::SACSegmentation<pcl::PointXYZRGB> seg; //构建分割对象
    
            seg.setOptimizeCoefficients(true);                   //设置是否优化系数
            seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE); //设置模型类型为平面
            seg.setMethodType(pcl::SAC_RANSAC);                  //设置分割方法为RANSAC
            seg.setMaxIterations(500);                           //设置最大迭代次数
            seg.setAxis(axis);                                   //设置分割轴
            seg.setEpsAngle(0.25);                               //设置角度阈值
            seg.setDistanceThreshold(plane_thickness);           //设置距离阈值  0.025 0.018
            seg.setInputCloud(input_cloud);                      //设置输入点云
            seg.segment(*inliers, *coefficients);                //分割平面
    
            if (inliers->indices.size() < 500)
            {
                // ROS_INFO("plane size is not enough large to remove.");
                return false;
            }
            pcl::ExtractIndices<pcl::PointXYZRGB> extract;
            extract.setInputCloud(input_cloud); //设置输入点云
            extract.setIndices(inliers);        //设置索引,用来滤除
            extract.setNegative(true);          //设置是否滤除索引内的点
            extract.filter(*input_cloud);
    
            return true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    1.5 RGBD颜色特征聚类

        void clustoring_with_color(pcl::PointCloud<pcl::PointXYZRGB>::Ptr &input_cloud, std::vector<pcl::PointCloud<PointXYZRGB>::Ptr> &clusters, int min_cluster_size, float distance_th, float color_th, float region_color_th, unsigned int num_nbr) //根据点云的颜色完成聚类
        {
            std::vector<pcl::PointIndices> clusters_indices;                                              //聚类索引
            pcl::search::KdTree<pcl::PointXYZRGB>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZRGB>); //构建kd树
            kdtree->setInputCloud(input_cloud);                                                           //设置输入点云
            // 基于颜色的区域生长聚类对象
            pcl::RegionGrowingRGB<pcl::PointXYZRGB> clustering;
            clustering.setInputCloud(input_cloud);
            clustering.setSearchMethod(kdtree); //设置搜索方法
            // 这里,最小簇大小也会影响后处理步骤: 小于这个值的clusters_indices将与邻点合并。
            clustering.setMinClusterSize(min_cluster_size); //设置最小簇大小
            // 设置距离阈值,以知道哪些点将被视为,邻点
            clustering.setDistanceThreshold(distance_th); // 1
            // 颜色阈值,用于比较两个点的RGB颜色
            clustering.setPointColorThreshold(color_th); // 9 6.5 25.0f 18.0f
            // 后处理步骤的区域颜色阈值:颜色在阈值内的clusters_indices将合并为一个。
            clustering.setRegionColorThreshold(region_color_th); // 2
            //区域耦合时检查的附近的数量。 默认为100, 在不影响结果的范围内适度设定小范围。
            clustering.setNumberOfRegionNeighbours(num_nbr); //设置近邻数量
    
            // clustering.setSmoothModeFlag(true);
            // clustering.setSmoothnessThreshold(0.95);
    
            clustering.extract(clusters_indices); //提取聚类索引
    
            for (std::vector<pcl::PointIndices>::const_iterator i = clusters_indices.begin(); i != clusters_indices.end(); ++i)//遍历聚类索引
            {
                pcl::PointCloud<pcl::PointXYZRGB>::Ptr cluster(new pcl::PointCloud<pcl::PointXYZRGB>); //构建聚类点云
                for (std::vector<int>::const_iterator pit = i->indices.begin(); pit != i->indices.end(); ++pit) //遍历聚类索引中的点索引
                {
                    cluster->points.push_back(input_cloud->points[*pit]); //将点添加到聚类点云
                }
                cluster->width = cluster->points.size();
                cluster->height = 1;
                cluster->is_dense = true;
                clusters.push_back(cluster); //将聚类点云添加到聚类点云集合中
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2. 匹配器

    2.1 ICP点云精配准

    …详情请参照古月居

  • 相关阅读:
    Word论文引用参考文献时et al.与等的快速替换方法
    uni-app checkout(多选)radio(单选)选中之后样式不会出现钩子
    光伏仪器-1763卫星帆板电源阵列模拟器
    从IoTDB的发展回顾时序数据库演进史
    MyBatis从入门到精通真没那么难!跟着我带你深入实践Mybatis技术原理与实战!
    Mac 苹果系统使用nvm use 切换node版本号
    Go语言基础之基本语法
    EF Core 批量插入操作原理分析
    Spring源码——Bean完整的生命周期详解
    【Zookeeper专题】Zookeeper经典应用场景实战(一)
  • 原文地址:https://blog.csdn.net/lovely_yoshino/article/details/125653528