点云DBSCAN聚类C++实现

本文介绍了一种基于点云的DBSCAN聚类算法实现,该算法具备抗噪能力,并能在非均匀密度环境下进行有效聚类。通过示例代码展示了如何使用PCL库实现点云数据的DBSCAN聚类过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1
我懒得说原理了,dbscan和欧式聚类原理很接近,不过具备抗噪能力,可以参考硕士论文《基于 DBSCAN 聚类算法的研究》和《针对非均匀密度环境的DBSCAN自适应聚类算法的研究》。
2
特别注意的是:dbscan认为密度可达的点即为一个簇,这也是dbscan聚类的核心思想。根据密度可达的定义,在聚类过程中,除了第一个和最后一个点之外(可以为核心对象或者边界对象),其余点必须是核心对象才可以。
3
对照欧式聚类,参考了代码,改写了点云dbscan算法。
show the codes

// 依赖项:pcl1.9.1
//时间:2021.06.25
//功能:实现点云dbscan聚类
#pragma once

#include <iostream>
#include<string>
#include<vector>

#include<pcl/io/pcd_io.h>
#include<pcl/point_cloud.h>
#include<pcl/point_types.h>
#include<pcl/kdtree/kdtree_flann.h>
#include<pcl/visualization/cloud_viewer.h>

typedef pcl::PointXYZ pointT;
typedef pcl::PointCloud<pointT> cloud;

bool dbscan(const cloud::Ptr& cloud_in, std::vector<std::vector<int>> &clusters_index, const double& r, const int& size)
{
    if (!cloud_in->size())
        return false;
    //LOG()
    pcl::KdTreeFLANN<pointT> tree;
    tree.setInputCloud(cloud_in);
    std::vector<bool> cloud_processed(cloud_in->size(), false);

    for (size_t i = 0; i < cloud_in->points.size(); ++i)
    {
        if (cloud_processed[i])
        {
            continue;
        }

        std::vector<int>seed_queue;
        //检查近邻数是否大于给定的size(判断是否是核心对象)
        std::vector<int> indices_cloud;
        std::vector<float> dists_cloud;
        if (tree.radiusSearch(cloud_in->points[i], r, indices_cloud, dists_cloud) >= size)
        {
            seed_queue.push_back(i);
            cloud_processed[i] = true;
        }
        else
        {
            //cloud_processed[i] = true;
            continue;
        }

        int seed_index = 0;
        while (seed_index < seed_queue.size())
        {
            std::vector<int> indices;
            std::vector<float> dists;
            if (tree.radiusSearch(cloud_in->points[seed_queue[seed_index]], r, indices, dists) < size)//函数返回值为近邻数量
            {
                //cloud_processed[i] = true;//不满足<size可能是边界点,也可能是簇的一部分,不能标记为已处理
                ++seed_index;
                continue;
            }
            for (size_t j = 0; j < indices.size(); ++j)
            {
                if (cloud_processed[indices[j]])
                {
                    continue;
                }
                seed_queue.push_back(indices[j]);
                cloud_processed[indices[j]] = true;
            }
            ++seed_index;                
        }
        clusters_index.push_back(seed_queue);               
      
    }
   // std::cout << clusters_index.size() << std::endl;

    if (clusters_index.size())
        return true;
    else
        return false;
}

int main()
{
    cloud::Ptr cloud_in(new cloud);
    std::vector<std::vector<int>> clusters_index;
    pcl::io::loadPCDFile<pcl::PointXYZ>("2.pcd", *cloud_in);
    dbscan(cloud_in, clusters_index, 0.1, 10);
    std::cout << clusters_index.size() << std::endl;
    pcl::PointCloud<pcl::PointXYZI> visual_cloud;
    visual_cloud.width = cloud_in->size();
    visual_cloud.height = 1;
    visual_cloud.resize(cloud_in->size());
    for (size_t i = 0; i < clusters_index.size(); ++i)
    {
        for (size_t j = 0; j < clusters_index[i].size(); ++j)
        {
            visual_cloud.points[clusters_index[i][j]].x = cloud_in->points[clusters_index[i][j]].x;
            visual_cloud.points[clusters_index[i][j]].y = cloud_in->points[clusters_index[i][j]].y;
            visual_cloud.points[clusters_index[i][j]].z = cloud_in->points[clusters_index[i][j]].z;
            visual_cloud.points[clusters_index[i][j]].intensity = 20*(i+100);
            //std::cout << clusters_index[i][j] << std::endl;

        }
       // std::cout << clusters_index[i].size() << std::endl;

    }
    
    pcl::visualization::CloudViewer viewer("DBSCAN cloud viewer.");
    viewer.showCloud(visual_cloud.makeShared());
    while (!viewer.wasStopped())
    {
    }
    pcl::io::savePCDFile("dbscan.pcd", visual_cloud,true);
    std::cout << "Hello World!\n";
}

4
实验结果:
在这里插入图片描述

### Point Cloud DBSCAN Clustering Implementation in C++ For implementing DBSCAN (Density-Based Spatial Clustering of Applications with Noise) on point clouds using C++, several libraries and resources can be utilized to facilitate this process. One prominent library is PCL (Point Cloud Library), which offers extensive support for various operations involving point cloud data, including clustering algorithms like DBSCAN. #### Utilizing the Point Cloud Library (PCL) The PCL provides a robust framework specifically designed for handling large datasets such as those encountered when working with LiDAR scans or other types of 3D sensor inputs. Within PCL, there exists an implementation of the DBSCAN algorithm that can directly operate over point cloud structures without requiring manual coding from scratch[^1]. Here’s how one might use PCL's built-in functionality: ```cpp #include <pcl/point_cloud.h> #include <pcl/kdtree/kdtree_flann.h> #include <pcl/features/normal_3d.h> #include <pcl/filters/passthrough.h> #include <pcl/segmentation/sac_segmentation.h> #include <pcl/io/pcd_io.h> #include <pcl/visualization/cloud_viewer.h> #include <pcl/console/time.h> // Assuming 'cloud' contains your input point cloud. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // Create search tree object used by DBSCAN pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>); tree->setInputCloud(cloud); std::vector<pcl::PointIndices> cluster_indices; pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec; ec.setClusterTolerance(0.02); // 2cm distance threshold between points within clusters ec.setMinPointsPerCluster(100); // Minimum number of points required per cluster ec.setMaxClusterSize(25000); // Maximum size limit for each detected cluster ec.setSearchMethod(tree); ec.setInputCloud(cloud); ec.extract(cluster_indices); ``` This code snippet demonstrates setting up parameters necessary for performing DBSCAN-based segmentation tasks efficiently while leveraging pre-built functionalities provided by PCL. In addition to exploring implementations through specialized libraries like PCL, researchers often publish their work at conferences mentioned earlier [^2], where novel approaches towards improving existing methods may also provide valuable insights into more advanced techniques beyond standard applications found within general-purpose software packages.
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值