PCL聚类 之 欧式聚类(最常用)

1. 欧式聚类原理概述

目标 :将点云中的点按 空间距离相近性 划分为不同的簇(cluster)。

数学上:通过 欧式距离 衡量点与点之间的相似性。

2、原理

点云

假设有一个点云:

欧氏距离

3、计算流程

  1. 初始化

    • 设置距离阈值 ϵ

    • 设置最小簇点数 Nmin⁡N_

    • 设置最大簇点数 Nmax⁡

  2. 遍历所有点

    若该点尚未被分配簇,则:

    • 将邻居点加入簇,同时继续搜索邻居的邻居(广度优先搜索 BFS 或队列)

    • 查找该点 ϵ 半径内的所有邻居点

    • 将该点加入簇

    • 创建新簇

  3. 簇过滤

    • 若簇大小 < Nmin⁡N_{\min}Nmin​ 或 > Nmax⁡N_{\max}Nmax​,则舍弃

    • 否则保存为有效簇

  4. 重复直到所有点被分簇

4、MAtlab 和PCL显示

PCL

cpp 复制代码
 
int  Connection_3d_models(pcl::PointCloud<pcl::PointXYZ>::Ptr  cloud, Connection_3d_Param &p, Connection_3d_Value &v, vector<pcl::PointCloud<pcl::PointXYZ>>& clouds)
{
	if (cloud->size()<1)
	{
		return -1;
	}
	pcl::PointIndices::Ptr inliner(new pcl::PointIndices);
	vector<pcl::PointIndices>ece_inlier;
	pcl::search::KdTree<pcl::PointXYZ>::Ptr  tree(new pcl::search::KdTree<pcl::PointXYZ>);
	pcl::EuclideanClusterExtraction<pcl::PointXYZ> ece;
	ece.setInputCloud(cloud);
	ece.setClusterTolerance(v.distance_3d_value);
	ece.setMinClusterSize(v.minClusterSize);
	ece.setMaxClusterSize(v.maxClusterSize);
	ece.setSearchMethod(tree);
	ece.extract(ece_inlier);
 
	for (int i = 0; i < ece_inlier.size(); i++)
	{
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_copy(new pcl::PointCloud<pcl::PointXYZ>);
		vector<int> ece_inlier_ext = ece_inlier[i].indices;
		pcl::copyPointCloud(*cloud, ece_inlier_ext, *cloud_copy);//按照索引提取点云数据
		clouds.push_back(*cloud_copy);
		std::string filename_result224 = "C:\\Users\\Albert\\Desktop\\Halcon2PCL\\classfiy\\"+to_string(i)+".pcd";
		pcl::io::savePCDFileBinaryCompressed(filename_result224, *cloud_copy);
	}
}

Matlab

cpp 复制代码
%% 生成点云
clc; clear;

% 第一簇
cluster1 = randn(50,3)*0.1 + [1 1 1];
% 第二簇
cluster2 = randn(50,3)*0.1 + [2 2 2];
% 第三簇
cluster3 = randn(50,3)*0.1 + [3 1 2];

% 合并点云
points = [cluster1; cluster2; cluster3];
N = size(points,1);

%% 欧式聚类参数
epsilon = 0.25;   % 距离阈值
minPts = 5;        % 最小簇大小

%% 初始化
unprocessed = true(N,1);
clusters = {};
cluster_id = 0;

%% 欧式聚类(BFS)
for i = 1:N
    if ~unprocessed(i)
        continue;
    end
    
    % 新簇
    cluster_id = cluster_id + 1;
    queue = i;
    unprocessed(i) = false;
    currentCluster = i;
    
    while ~isempty(queue)
        idx = queue(1);
        queue(1) = [];
        
        % 计算 idx 点与剩余点的距离
        dists = sqrt(sum((points - points(idx,:)).^2,2));
        
        neighbors = find(dists <= epsilon & unprocessed);
        
        % 标记邻居
        unprocessed(neighbors) = false;
        queue = [queue; neighbors];
        currentCluster = [currentCluster; neighbors];
    end
    
    % 保存簇
    if numel(currentCluster) >= minPts
        clusters{end+1} = currentCluster;
    end
end

%% 可视化
figure; hold on;
colors = lines(length(clusters));
for k = 1:length(clusters)
    pts = points(clusters{k},:);
    scatter3(pts(:,1), pts(:,2), pts(:,3), 50, colors(k,:), 'filled');
end
xlabel('X'); ylabel('Y'); zlabel('Z'); grid on; axis equal;
title('Euclidean Clustering 示例');

5、总结

欧式聚类简单高效、直观易用 ,是点云分割的首选,但对噪声和参数敏感,大规模点云和稀疏/复杂形状点云需结合空间索引或后处理。

优点(Strengths)

  1. 直观简单

    • 原理就是"距离近的点属于同一簇",容易理解、易于实现。

    • 不依赖复杂模型或概率分布。

  2. 高效(适合小/中型点云)

    • 对点数少或适中,基于 kd-tree 或空间索引,搜索半径邻居很快。

    • 算法复杂度接近 O(nlogn)(取决于邻居搜索结构)。

  3. 参数可控

    • 通过 距离阈值 ϵ最小/最大簇大小,可以精细控制簇划分。
  4. 常用、工程成熟

    • PCL(Point Cloud Library)、激光雷达处理、机器人视觉 中是默认首选的点云分割方法。
  5. 无模型假设

    • 不要求点云符合高斯分布或其他统计模型,适合各种形状点云。

2. 缺点(Weaknesses)

  1. 对噪声敏感

    • 孤立点或离群点可能形成单独小簇,需要额外滤波。

    • 误差点过多可能导致簇划分错误。

  2. 参数敏感

    • 距离阈值 ϵ\epsilonϵ 对结果影响很大:

      • 阈值太小 → 原本一个物体被分成多个簇

      • 阈值太大 → 不同物体被合并到同一簇

  3. 点云密度依赖

    • 点稀疏时,距离阈值需要放大,容易误聚

    • 点密集时,阈值太大可能把相邻物体连在一起

  4. 簇形状假设弱

    • 不考虑簇内部拓扑结构,只靠距离

    • 对长条形或环形簇可能表现不好,需要更多参数或后处理

  5. 计算复杂度高(大规模点云)

    • 如果没有空间索引(kd-tree/octree),邻居搜索为 O(n²)

    • 对百万级点云直接暴力计算不可行

项目 优点 缺点 适用场景
实现复杂度 简单,几行代码 对大点云需 kd-tree 小到中型点云快速实验
参数 (\epsilon)、minPts 可调 对阈值敏感 工业/实验需调参
对噪声 无假设,无模型 离群点影响明显 点云质量好时最佳
性能 小点云快,空间索引加速 百万点云需优化 Lidar 预处理或局部聚类
形状适应 任意点形状 长条、环状簇可能误划 常规物体聚类
相关推荐
所谓伊人,在水一方3332 小时前
【Python数据科学实战之路】第12章 | 无监督学习算法实战:聚类与降维的奥秘
python·sql·学习·算法·信息可视化·聚类
像素猎人2 小时前
数据结构之顺序表的插入+删除+查找+修改操作【主函数一步一输出,代码更加清晰直观】
数据结构·c++·算法
季明洵3 小时前
二叉树的最小深度、完全二叉树的节点个数、平衡二叉树、路径总和、从中序与后序遍历序列构造二叉树
java·数据结构·算法·leetcode·二叉树
飞Link3 小时前
深度解析 TSAD:时序数据异常分类与检测技术的全景指南
大数据·人工智能·机器学习·数据挖掘
想进个大厂3 小时前
代码随想录day63 64 65 66 图论08 09 10 11
c++·算法·图论
云泽8083 小时前
蓝桥杯算法精讲:双指针算法四大经典例题深度剖析
算法·职场和发展·蓝桥杯
小龙报3 小时前
【算法通关指南:算法基础篇】二分算法: 1.A-B 数对 2.烦恼的高考志愿
c语言·开发语言·数据结构·c++·vscode·算法·二分
yong99903 小时前
NNDA、PDA、JPDA、IMM数据关联算法MATLAB实现
开发语言·算法·matlab