1 简介
在一段曲线中,存在着许多的特征点,但是这些特征点分布不均匀,有的地方非常密集,有的地方又很松散。如下图所示,是一个牙齿模型的.stl文件的某一截面,可以看到这个截面的上下部分的特征点十分密集,中间位置十分松散,当我们需要提取它的轮廓进行拟合时不是很方便,所以我们需要去除冗余的一些特征点。
2 算法实现思路
采用Dougla-Peucker算法 算法具体思路如下
- 设置残差ϵ;(也就是去除冗余点的精度,ϵ越小精度越高,去除的冗余点的数量也越少;)
- 用一条直线连接路径的首尾(图中P1,P8)
- 计算首尾点之间的所有路径点到这条直线的距离,并找到最大距离max以及对应的路径点(图中P5);
- 如果max<ϵ,则说明这个首尾P1 P8可以代表这段曲线的特征,去除首尾点之间的所有路径点,这段曲线处理完毕;
- 如果max>ϵ,则说明这个首尾P1 P8并不能完全体现这段曲线的特征,需要细分;在max对应的路径点P5处将当前路径一分为二,回到步骤2,重新进行;
- 直到所有的路径线处理完毕,就此完成冗余路径点地去除。
3 matlab程序
function result = DouglasPeuckerAO(Points,epsilon)
%Points 路径数组 N×2
%epsilon 残差
%作者 天才小傲傲
p1 = Points(1,:);
p2 = Points(end,:);
%判断数组首尾点是否相同 相同则尾点向前取一个 首尾点不能相同
if p1==p2
p2=Points(end-1,:);
end
distanceList = zeros(length(Points),1);
for i = 2:length(Points)-1
pointTemp = Points(i,:);
distanceTemp = pointLineDistance(p1,p2,pointTemp);
distanceList(i) = distanceTemp;
end
[MAX,index] = max(distanceList);
if MAX < epsilon
result = [p1;p2];
else
recResult1 = DouglasPeuckerAO(Points(1:index,:),epsilon);
recResult2 = DouglasPeuckerAO(Points(index:end,:),epsilon);
result = [recResult1(1:length(recResult1)-1,:);
recResult2(1:length(recResult2),:)];
end
end
function result=pointLineDistance(Q1,Q2,P)
%采用的3维空间向量叉积的方法求点到直线的最短距离 如果是2维向量,需要补全第三维度
if length(Q1)==2
Q1(end+1)=0;
Q2(end+1)=0;
P(end+1)=0;
end
result=norm(cross(Q2-Q1,P-Q1))/norm(Q2-Q1);
end
5 效果展示
5.1 ϵ取0.1
5.1 ϵ取0.01
如果对你有帮助的话,请点赞哦哈哈