基于高度和曲率的点云分割:将点云数据分为冠层和盆点

这段代码使用 MATLAB 将点云数据分割为两类:冠层和盆点。通过设置高度阈值和曲率阈值,将满足条件的点标记为冠层或盆点。最后,使用不同的颜色可视化结果。

%% **********获取点云数据************
[fileName,pathName] = uigetfile('*.txt','Input Data-File'); % 选择要进行计算的三维点云数据文件路径

if isempty(fileName) || length(fileName) == 1
    fprintf('未选择点云文件!\n');
    return;
end

data = load([pathName,fileName]); % 加载.txt点云数据
xyz = data(:, 1:3);
xyz_f = [xyz(:,1),xyz(:,2),-xyz(:,3)];
pc = pointCloud(xyz_f); % 创建点云对象
disp('读取点云成功!')

% 设置高度阈值和曲率阈值
height_threshold = 2.5; % 根据您的点云数据进行适当调整
curvature_threshold = 0.1; % 根据您的点云数据进行适当调整

% 提取点云数据中的Z坐标
Z = xyz_f(:, 3);

% 计算高度差
height_diff = Z - min(Z);

% 计算滤波阈值
filter_threshold = height_threshold;

% 计算点云数据的曲率
curvatures = computeCurvature(pc);

% 创建标记矩阵,用于记录每个点的分类结果
labels = zeros(size(xyz_f, 1), 1);

% 标记冠层和盆点
labels(height_diff > filter_threshold & curvatures > curvature_threshold) = 1; % 标记为冠层
labels(height_diff <= filter_threshold | curvatures <= curvature_threshold) = -1; % 标记为盆点

% 可选:可视化结果
figure;
scatter3(xyz_f(labels == 1, 1), xyz_f(labels == 1, 2), xyz_f(labels == 1, 3), 'r', 'filled'); % 以红色显示冠层点云
hold on;
scatter3(xyz_f(labels == -1, 1), xyz_f(labels == -1, 2), xyz_f(labels == -1, 3), 'b', 'filled'); % 以蓝色显示盆点云
xlabel('X');
ylabel('Y');
zlabel('Z');
title('Curved Point Cloud Segmentation');

% 曲率计算函数
function curvatures = computeCurvature(pc)
    % pc: 点云对象

    % 计算最近邻点索引
    k = 20; % 选择一个合适的K值
    kdtree = KDTreeSearcher(pc.Location);
    indices = knnsearch(kdtree, pc.Location, 'K', k);

    % 计算法线
    normals = [];
    for i = 1:size(pc.Location, 1)
        points = pc.Location(indices(i, :), :);
        [~, normal] = fitPlaneToPoints(points, pc.Location(i, :));
        normals = [normals; normal];
    end

    % 计算曲率
    [~, curvatures] = pcfitplane(pc, 'Normal', normals);
end

% 拟合平面到一组点
function [plane, normal] = fitPlaneToPoints(points, refPoint)
    % points: 一组点的坐标,每行表示一个点
    % refPoint: 参考点的坐标,用于确定法线方向

    % 计算点云坐标的中心点
    center = mean(points, 1);

    % 将点云坐标沿参考点到中心点的方向平移
    translatedPoints = bsxfun(@minus, points, (center - refPoint));

    % 使用奇异值分解(SVD)计算最小二乘拟合平面的法线
    [~, ~, V] = svd(translatedPoints, 'econ');
    normal = V(:, end)';

    % 构造拟合的平面
    plane = [normal, -dot(normal, refPoint)];
end

代码说明:

  1. 获取点云数据: 代码首先从用户指定的 txt 文件中读取点云数据,并创建点云对象。
  2. 设置阈值: 设定高度阈值和曲率阈值,用于判断点云数据属于冠层还是盆点。
  3. 计算高度差和曲率: 代码计算每个点的Z坐标和高度差,以及使用 computeCurvature 函数计算每个点的曲率。
  4. 标记冠层和盆点: 根据设置的阈值,将每个点标记为冠层或盆点。
  5. 可视化结果: 最后,使用不同的颜色可视化冠层和盆点。

注意:

  • 高度阈值和曲率阈值需要根据实际情况进行调整。
  • 该代码使用简单的阈值判断方法,对于复杂场景可能需要更高级的算法。
  • 代码中包含了 computeCurvaturefitPlaneToPoints 两个函数,用于计算曲率和拟合平面。

应用场景:

该代码适用于对点云数据进行简单分割的应用场景,例如对树木点云数据进行冠层和盆点的划分。

下一步:

  • 可以尝试使用更高级的算法,例如基于机器学习的方法,进行点云分割。
  • 可以根据实际应用场景,对代码进行优化和调整,例如增加其他特征信息,提高分割精度。
MATLAB 点云分割:将点云数据分为冠层和盆点

原文地址: https://www.cveoy.top/t/topic/S0P 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录