PCL对不同稀疏度的点进行划分(点云分割)

内容介绍

在处理一些大型的点云数据时,总会出现部分点稀疏部分点密集的情况,直接进行曲面重构时的参数会无法同时满足不同情况,此时可以进行下采样降低密集点的密度,也可以进行上采样增加稀疏点的密度,这里直接把稀疏点和密集点划分为两部分,分别进行重构。

代码

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <iostream>
#include <vector>
#include <unordered_set>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/filters/voxel_grid.h>

// DBSCAN参数
const float EPSILON = 23; // 邻域半径
const int MIN_POINTS = 10; // 构成簇的最小点数

// DBSCAN算法
void dbscan(const pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, std::vector<int>& labels) {
    int cluster_id = 0;
    labels.resize(cloud->points.size(), -1); // -1表示未分类

    pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
    kdtree.setInputCloud(cloud);

    for (size_t i = 0; i < cloud->points.size(); ++i) {
        if (labels[i] != -1) continue; // 已经处理过

        std::vector<int> neighbors;
        std::vector<float> distances;
        kdtree.radiusSearch(cloud->points[i], EPSILON, neighbors, distances);

        if (neighbors.size() < MIN_POINTS) {
            labels[i] = -2; // 噪声点
            continue;
        }

        // 创建新簇
        cluster_id++;
        std::vector<int> cluster;
        cluster.push_back(i);
        labels[i] = cluster_id;

        // 遍历邻居
        size_t index = 0;
        while (index < cluster.size()) {
            int point_idx = cluster[index];
            std::vector<int> new_neighbors;
            std::vector<float> new_distances;
            kdtree.radiusSearch(cloud->points[point_idx], EPSILON, new_neighbors, new_distances);

            if (new_neighbors.size() >= MIN_POINTS) {
                for (size_t j = 0; j < new_neighbors.size(); ++j) {
                    if (labels[new_neighbors[j]] == -1 || labels[new_neighbors[j]] == -2) {
                        if (labels[new_neighbors[j]] == -1) {
                            cluster.push_back(new_neighbors[j]);
                        }
                        labels[new_neighbors[j]] = cluster_id;
                    }
                }
            }
            index++;
        }
    }
}

int main(int argc, char** argv) {
    // 加载点云数据
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("1.pcd", *cloud) == -1) {
        PCL_ERROR("Couldn't read file input.pcd \n");
        return (-1);
    }
    pcl::VoxelGrid<pcl::PointXYZ> vg;
    vg.setInputCloud(cloud);
    vg.setLeafSize(10.0f, 10.0f, 10.0f);  // 设置体素大小
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_smoothed(new pcl::PointCloud<pcl::PointXYZ>);
    vg.filter(*cloud_smoothed); 

    // 执行DBSCAN聚类
    std::vector<int> labels;
    dbscan(cloud_smoothed, labels);

    // 提取密集点和稀疏点
    pcl::PointCloud<pcl::PointXYZ>::Ptr dense_points(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr sparse_points(new pcl::PointCloud<pcl::PointXYZ>);
    for (size_t i = 0; i < labels.size(); ++i) {
        if (labels[i] > 0) { // 密集点
            dense_points->points.push_back(cloud_smoothed->points[i]);
        }
        else { // 稀疏点
            sparse_points->points.push_back(cloud_smoothed->points[i]);
        }
    }
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("original_cloud"));
    viewer->setBackgroundColor(0, 0, 0); //设置背景
    viewer->addPointCloud(cloud);
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer1(new pcl::visualization::PCLVisualizer("original_cloud"));
    viewer1->setBackgroundColor(0, 0, 0); //设置背景
    viewer1->addPointCloud(dense_points);
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer2(new pcl::visualization::PCLVisualizer("rebuild_cloud"));
    viewer2->setBackgroundColor(0, 0, 0); //设置背景
    viewer2->addPointCloud(sparse_points); //设置显示的网格
    //viewer->addCoordinateSystem(1.0); //设置坐标系
    //viewer->initCameraParameters();
    dense_points->width = dense_points->points.size();
    dense_points->height = 1;
    sparse_points->width = sparse_points->points.size();
    sparse_points->height = 1;
    pcl::io::savePCDFileASCII("dense_points.pcd", *dense_points);
    pcl::io::savePCDFileASCII("sparse_points.pcd", *sparse_points);
    std::cout << "Saved " << dense_points->points.size() << " dense points to dense_points.pcd" << std::endl;
    std::cout << "Saved " << sparse_points->points.size() << " sparse points to sparse_points.pcd" << std::endl;
    while (!viewer1->wasStopped()) {
        viewer->spinOnce(100);
    	viewer1->spinOnce(100);
    	viewer2->spinOnce(100);
    	boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }
    // 保存密集点和稀疏点


    return 0;
}

运行效果

原始数据集如下图,可以看到稀疏和密集区较为明显
在这里插入图片描述
在这里插入图片描述
运行代码后可以看出点云数据被很好地分成了两部分
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
接下来就可以对不同稀疏度的数据进行分别处理了,还是十分方便的。

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PCL(Point Cloud Library)是一个开源的点云处理库用于处理和分析三维点云数据。在点云分割任务中,评价指标用于衡量算法的性能和准确。以下是几个常用的PCL点云分割评价指标: 1. 点云分割准确率(Segmentation Accuracy):该指标用于评估算法点云数据进行正确分割的能力。准确率可以通过计算正确分割的数与总数之比来得到。 2. 点云分割召回率(Segmentation Recall):该指标用于评估算法点云数据进行完整分割的能力。召回率可以通过计算正确分割的数与真实分割数之比来得到。 3. 平均欠分割误差(Under-segmentation Error):该指标用于评估算法点云数据进行分割的程。欠分割误差可以通过计算未正确分割的数与总数之比来得到。 4. 平均过分割误差(Over-segmentation Error):该指标用于评估算法点云数据进行不足分割的程。过分割误差可以通过计算错误分割的数与总数之比来得到。 5. 边界正确率(Boundary Precision):该指标用于评估算法点云数据中物体边界的准确。边界正确率可以通过计算正确分割的边界数与总边界数之比来得到。 6. 边界召回率(Boundary Recall):该指标用于评估算法点云数据中物体边界的完整性。边界召回率可以通过计算正确分割的边界数与真实边界数之比来得到。 以上是一些常见的PCL点云分割评价指标,可以根据具体任务和需求选择适合的指标进行评估。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值