Matlab三维离散点云的邻域点搜索(柱状邻域、球状邻域及KNN)

在计算三维点云的法向量、曲率、坡度等间接特征时,需要搜索点的邻域点。

某点邻域的选取多依据空间几何信息,从空间维数分为二维邻域和三维邻域,对应的有柱状邻域和球状邻域。

同时,邻域的选取可以通过限制邻近点的个数(KNN)或者限制邻域范围(柱状邻域和球状邻域)来实现。

柱状邻域点指以一点为中心,以r为半径的无限高、垂直圆柱范围内的点。

球状邻域点指以一点为中心,以r为半径的球体内所包含的点。

KNN指与一点最邻近的K个点。

具体代码如下:

function [idx,dist] = nbselect(data,part,varargin)
% 功能:选择不同邻域类型,返回邻域索引与距离
% 输入:data - 原始数据    part - 待检索数据
%       varargin - 球状、柱状邻域或KNN+半径或个数
%      ‘sph’ - 球状邻域
%      ‘cyl’ - 柱状邻域
%       ‘K’  - KNN 
% 输出:idx - 邻域索引 dist - 距离
% example: [sph,dist_sph] =  nbselect(data,part,'sph',r_sph);
if varargin{1} == 'sph'
    r_sph = varargin{2};
    [idx,dist] = rangesearch(data(:,1:3),part(:,1:3),r_sph,'Distance','euclidean','NSMethod','kdtree');      
elseif varargin{1} == 'cyl'
    r_cyl = varargin{2};
    [idx,dist] = rangesearch(data(:,1:2),part(:,1:2),r_cyl,'Distance','euclidean','NSMethod','kdtree');  
elseif varargin{1} == 'K'
    k = varargin{2};
    [idx,dist] = knnsearch(data(:,1:3),part(:,1:3),'Distance','euclidean','NSMethod','kdtree','K',k);  
end
end

为了检测邻域点获取的效果,通过一块ISPRS的LiDAR点云数据进行验证,结果如下:

懒得自己动手的朋友,测试数据与示例代码见:

Matlab建立KD树搜索三维点云的邻近点(柱状邻域、球状邻域与KNN)

getpointsXYZ.rar

相关文章见:

利用Matlab鼠标单击拾取三维点云可视化图像figure中的单个或多个点坐标信息

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
Matlab中实现变半径邻域搜索可以使用以下步骤: 1. 首先,确定搜索半径的初始值和最大值。 2. 然后,从初始搜索半径开始,对每个数据建立一个以该为中心、半径为搜索半径的圆形邻域。 3. 对于每个圆形邻域,计算其中所有数据对该圆心的距离的平均值和标准差。 4. 根据圆形邻域内数据的平均距离和标准差,确定是否需要调整搜索半径。如果平均距离大于一个给定的阈值,则将搜索半径增加一定比例;如果平均距离小于另一个给定的阈值,则将搜索半径减少一定比例。 5. 重复步骤2-4,直到搜索半径达到最大值或者满足特定的停止准则为止。 以下是一个简单的Matlab代码示例,实现了变半径邻域搜索: ``` % 数据矩阵 data = rand(100, 2); % 初始搜索半径和最大搜索半径 init_radius = 0.1; max_radius = 1.0; % 搜索半径调整比例 increase_ratio = 1.1; decrease_ratio = 0.9; % 停止准则 max_iterations = 100; min_points = 5; % 初始化搜索半径 radius = init_radius; % 开始搜索 for i = 1:max_iterations % 对每个数据建立圆形邻域 neighborhoods = cell(size(data, 1), 1); for j = 1:size(data, 1) neighborhoods{j} = data(sqrt(sum((data - repmat(data(j, :), size(data, 1), 1)).^2, 2)) <= radius, :); end % 计算每个圆形邻域内数据的平均距离和标准差 avg_distances = cellfun(@(x) mean(sqrt(sum((x - repmat(mean(x), size(x, 1), 1)).^2, 2))), neighborhoods); std_distances = cellfun(@(x) std(sqrt(sum((x - repmat(mean(x), size(x, 1), 1)).^2, 2))), neighborhoods); % 判断是否需要调整搜索半径 if all(avg_distances >= threshold1) && all(std_distances <= threshold2) break; elseif any(avg_distances < threshold3) radius = radius * decrease_ratio; elseif any(avg_distances > threshold4) radius = radius * increase_ratio; end % 检查搜索半径是否达到最大值 if radius > max_radius break; end end % 打印搜索结果 for i = 1:size(data, 1) if size(neighborhoods{i}, 1) >= min_points disp(['Data point ' num2str(i) ' has ' num2str(size(neighborhoods{i}, 1)) ' neighbors within radius ' num2str(radius)]); end end ``` 在这个示例代码中,我们使用了一个简单的停止准则,即当所有圆形邻域内数据的平均距离都大于一个给定的阈值并且所有圆形邻域内数据的距离标准差都小于另一个给定的阈值时,停止搜索。同时,我们还使用了一个最小数的限制,即只有那些圆形邻域内包含至少min_points个数据的数据才会被输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值