1. 欧式聚类原理概述
目标 :将点云中的点按 空间距离相近性 划分为不同的簇(cluster)。
数学上:通过 欧式距离 衡量点与点之间的相似性。

2、原理
点云
假设有一个点云:

欧氏距离

3、计算流程
-
初始化:
-
设置距离阈值 ϵ
-
设置最小簇点数 NminN_
-
设置最大簇点数 Nmax
-
-
遍历所有点:
若该点尚未被分配簇,则:
-
将邻居点加入簇,同时继续搜索邻居的邻居(广度优先搜索 BFS 或队列)
-
查找该点 ϵ 半径内的所有邻居点
-
将该点加入簇
-
创建新簇
-
-
簇过滤:
-
若簇大小 < NminN_{\min}Nmin 或 > NmaxN_{\max}Nmax,则舍弃
-
否则保存为有效簇
-
-
重复直到所有点被分簇

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)
-
直观简单
-
原理就是"距离近的点属于同一簇",容易理解、易于实现。
-
不依赖复杂模型或概率分布。
-
-
高效(适合小/中型点云)
-
对点数少或适中,基于 kd-tree 或空间索引,搜索半径邻居很快。
-
算法复杂度接近 O(nlogn)(取决于邻居搜索结构)。
-
-
参数可控
- 通过 距离阈值 ϵ 和 最小/最大簇大小,可以精细控制簇划分。
-
常用、工程成熟
- 在 PCL(Point Cloud Library)、激光雷达处理、机器人视觉 中是默认首选的点云分割方法。
-
无模型假设
- 不要求点云符合高斯分布或其他统计模型,适合各种形状点云。
2. 缺点(Weaknesses)
-
对噪声敏感
-
孤立点或离群点可能形成单独小簇,需要额外滤波。
-
误差点过多可能导致簇划分错误。
-
-
参数敏感
-
距离阈值 ϵ\epsilonϵ 对结果影响很大:
-
阈值太小 → 原本一个物体被分成多个簇
-
阈值太大 → 不同物体被合并到同一簇
-
-
-
点云密度依赖
-
点稀疏时,距离阈值需要放大,容易误聚
-
点密集时,阈值太大可能把相邻物体连在一起
-
-
簇形状假设弱
-
不考虑簇内部拓扑结构,只靠距离
-
对长条形或环形簇可能表现不好,需要更多参数或后处理
-
-
计算复杂度高(大规模点云)
-
如果没有空间索引(kd-tree/octree),邻居搜索为 O(n²)
-
对百万级点云直接暴力计算不可行
-
| 项目 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 实现复杂度 | 简单,几行代码 | 对大点云需 kd-tree | 小到中型点云快速实验 |
| 参数 | (\epsilon)、minPts 可调 | 对阈值敏感 | 工业/实验需调参 |
| 对噪声 | 无假设,无模型 | 离群点影响明显 | 点云质量好时最佳 |
| 性能 | 小点云快,空间索引加速 | 百万点云需优化 | Lidar 预处理或局部聚类 |
| 形状适应 | 任意点形状 | 长条、环状簇可能误划 | 常规物体聚类 |