1. 区域生长聚类概述
目标 :根据点云的局部连续性,将点云分成若干簇(cluster)。
-
不仅考虑 欧式距离 ,还考虑 法向一致性 或 曲率平滑性。
-
常用于 曲面分割、地形点云、物体分割。

2、原理
输入点云

核心思想
-
选择种子点 s0,开始一个新簇Ck
-
检查邻居点 N(s0):
-
距离条件:∥pi−pj∥<ϵd
-
法向一致性:cos−1(∣ni⋅nj∣)<θmax
-
曲率条件(可选):∣κi−κj∣<κth
-
-
满足条件的邻居加入簇,并作为新的种子点继续生长
-
迭代直到簇不再生长
-
选择下一个未分配的点作为种子,开始新簇
数学描述
假设簇 Ck已有点集合 {pk1,...,pkm},考虑邻居点 pj
距离约束

法向一致性

-
点 pj 与簇内至少一个点法向差异小于阈值
-
保证曲面平滑生长
曲率约束(可选

区域生长公式总结

3. 区域生长算法步骤
-
初始化
-
点云已计算法向量 ni
-
设置阈值 ϵd、θmax、κth
-
-
选择种子点 s0s_0s0
- 通常选曲率最小或随机点
-
生长簇
-
将s0 放入队列
-
遍历队列内每个点,检查邻居是否满足距离、法向、曲率条件
-
满足条件 → 加入簇并入队
-
-
簇完成
-
队列为空 → 该簇完成
-
选择下一个未分配点作为种子,重复步骤 2
-
-
簇后处理(可选)
-
去掉过小簇
-
平滑簇边界
-
4、PCL 和Matlab 显示
Mablab 显示
这个是网上抄的有问题
cpp
clc; clear;
%% 生成示例点云 (3个平面簇)
[X,Y] = meshgrid(0:0.1:1, 0:0.1:1);
Z1 = 0*X; % 平面1
Z2 = 1 + 0*X; % 平面2
Z3 = X; % 平面3倾斜
pts = [X(:), Y(:), Z1(:);
X(:), Y(:), Z2(:);
X(:), Y(:), Z3(:)];
N = size(pts,1);
%% 假设法向量
normals = zeros(N,3);
normals(1:numel(X(:)),:) = repmat([0 0 1], numel(X(:)),1);
normals(numel(X(:))+1:2*numel(X(:)),:) = repmat([0 0 1], numel(X(:)),1);
normals(2*numel(X(:))+1:end,:) = repmat([0 0 1], numel(X(:)),1);
%% 区域生长参数
epsilon_d = 0.15;
theta_max = deg2rad(10); % 最大法向夹角 10 度
%% 初始化
unprocessed = true(N,1);
clusters = {};
cluster_id = 0;
%% 区域生长
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((pts - pts(idx,:)).^2,2));
neighbors = find(dists <= epsilon_d & unprocessed);
% 法向一致性
cos_angle = abs(normals(neighbors,:) * normals(idx,:)');
neighbors = neighbors(cos_angle > cos(theta_max));
% 加入簇
unprocessed(neighbors) = false;
queue = [queue; neighbors];
currentCluster = [currentCluster; neighbors];
end
clusters{end+1} = currentCluster;
end
%% 可视化
figure; hold on; grid on; axis equal;
colors = lines(length(clusters));
for k = 1:length(clusters)
pts_k = pts(clusters{k},:);
scatter3(pts_k(:,1), pts_k(:,2), pts_k(:,3), 50, colors(k,:), 'filled');
end
xlabel('X'); ylabel('Y'); zlabel('Z');
title('点云区域生长聚类示例');
PCL
cpp
int Regional_Growth_Clustering(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, Connection_3d_Value &v, vector<pcl::PointIndices>&ece_inlier)
{
if (cloud->size()<1)
{
return -1;
}
// 计算法向量
pcl::PointCloud<pcl::Normal>::Ptr normal(new pcl::PointCloud<pcl::Normal>);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> nor_Omp;
nor_Omp.setInputCloud(cloud);
nor_Omp.setRadiusSearch(v.normal_Radius);
nor_Omp.setNumberOfThreads(10);
nor_Omp.setSearchMethod(tree);
nor_Omp.compute(*normal);
// 法向量和曲率的 区域生长分类
pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal>rg;
rg.setInputCloud(cloud);
rg.setInputNormals(normal);
rg.setSearchMethod(tree);// 搜索方法 搜索树
rg.setNumberOfNeighbours(v.rg_Neighbours_Number); // 领域搜索点的个数
rg.setMinClusterSize(v.minClusterSize);
rg.setMaxClusterSize(v.maxClusterSize);
rg.setCurvatureThreshold(v.rg_Curvature_Threshold); // 设置曲率的阈值
rg.setSmoothnessThreshold(v.rg_SmoothnessThreshold); // 设置平滑度 法线插值阈值
rg.extract(ece_inlier);
}

4、总结
优点:
-
考虑 局部曲面连续性 → 分割平滑曲面效果好
-
可处理 非均匀密度 点云
-
可以结合 法向和曲率 → 提高鲁棒性
缺点:
-
参数依赖明显:ϵd、θmax
-
对噪声敏感,离群点可能成为小簇
-
对大规模点云,遍历邻居可能耗时(需 kd-tree 加速)