2021-7-21的时候博主已经写过部分点云去噪的介绍及部分滤波matlab写法,在新开的博客中补充博主在写双边滤波时的想法,21号的贴子链接:
2021-7-21-点云去噪(中值、高斯、均值、SOR滤波),及matlab的代码撰写_~追风筝的猫的博客-CSDN博客
双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、局部的特点。双边滤波器的好处是可以做边缘保存。
将双边滤波应用到点云中,其算法流程如下:
%% 双边滤波
clear all
%% 生成带噪声的点云
gv = 0:0.01:1;
[X,Y] = meshgrid(gv,gv);
% X(:)的意思是把矩阵转换为一行
p = [X(:),Y(:),0.5*ones(numel(X),1)];
% 生成噪声,随机生成500个噪声点
noise = rand(500, 3);
% 合并,p的矩阵为n*3
p = [p;noise];
clear X Y noise gv
% pcshow(p)
%% 计算法向量
% r半径搜索,单位m
r = 1;
% 搜索得到全部的r内临近点
[idx,d] = rangesearch(p,p,r,'Distance','euclidean','NSMethod','kdtree');
% 可以通过pcnormals实现法向量的提取,这个是matlab2019b函数自带的法向量计算函数
% p = pointCloud(p); % p需要先转换成matlab读取的格式
% vec = pcnormals(p); % 这样就可以计算法向量,是通过最邻近点计算的,默认是8个临近点
% p = p.Location; % p还原数组格式
% Reig为按照圆搜索邻近点计算法向量,博主自写的函数。
[~,~,~,~,~,vec] = Reig(p, r);
% 权重因子
% sum_w = 0;
% sum_pr = 0;
% pd为每个点到其邻近点的影响因子
pd = r;
% 每个点到临近点法式的影响因子
% pn = 0.5;
% 循环计算每个点的权重
for i = 1:length(p(:,1))
% 权重因子
sum_w = 0;
sum_pr = 0;
% 提取当前点
a = p(i,:);
% 得到当前点r范围内的点
curp = idx(i,:);
% cell转换为数组mat
curp = cell2mat(curp);
% 第一个索引是自己,所以去除
curp = curp(:,2:end);
% 求取临近点距离标准差
didx = d(i,:);
didx = cell2mat(didx);
didx = didx(:,2:end);
pn = std(didx);
% 搜索索引点
idxpoint = p(curp,:);
% 循环领域内的点
for j = 1:length(curp)
% 领域点的当前点
b = idxpoint(j,:);
% 空间权重之一
dd = norm(b-a);
% 空间权重之二
dn = dot(b-a,vec(i,:));
%
w = exp(-dd^2/(2*pd^2))*exp(-dn^2/(2*pn^2));
%
sum_pr = sum_pr + w * dn;
%
sum_w = sum_w + w;
end
qp = sum_pr/sum_w;
p1(i,:) = p(i,:) + qp * vec(i,:);
end
% qp = sum_pr/sum_w;
% % 平滑数据处理
% for i = 1:length(p(:,1))
% p1(i,:) = p(i,:) + qp * vec(i,:);
% end
pcshow(p1)
下图是生成的带噪声的数据:
经过双边滤波过后:
似乎效果不太好??或许是某一个步骤写错了?难以得到验证
也有可能是因为双边滤波也是平滑数据,而不是去除噪声点。
在代码中有Reig函数,是通过圆的范围计算特征值的,可以根据博主以下的代码进行改进:
Matlab计算点云法向量和曲率-2021-11-21_~追风筝的猫的博客-CSDN博客_matlab点云求法向量
用matlab写出来运行要很久来着,这是由于在matlab中写了双循环,循环全部的点,循环临近点。
后续博主出完部分特征计算的教程后,再整理双边滤波成function上传。