MATLAB Delaunay算法提取离散点边界的方法

所属分类: 软件编程 / C 语言 阅读数: 85
收藏 0 赞 0 分享

最近在项目进行中遇到要提取离散点边界的问题,像我这样的对于matlab不是特别熟练的朋友一开始肯定摸不着头脑,到底选用哪种算法可以有效地提取到所有已知点的轮廓线呢。本人经过大量的文献搜索及代码实验找到了几个效果比较好的轮廓提取代码,在这里做个总结,并且希望能够对遇到同样问题的朋友有所启发。

关于离散点边界提取的三种方法:

1.Convhull 离散点集获得边界

2.Alpha Shape算法检测边缘点

3.Delaunay 三角剖分算法

前两种方法在之前的博客中已经做了总结这里就不展开了,现在主要介绍第三种算法。

该算法的总体思路如下:

1、利用 delaunay 函数,对所有数据点进行 Delaunay 三角剖分处理,delaunay 函数的返回值是一个 N * 3 的矩阵,其中 N 为剖分出的三角形个数,3 为每个三角形的三个端点的序号。

2、根据 triangles 矩阵,提取出所有 delaunay 三角剖分时所连接的边,依次扫描 triangles 矩阵的每一行,将 delaunay 三角剖分时所连接的边添加到一个新的矩阵中,最后构成一个 M * 2 的矩阵,其中 M 是一共所连接的边的条数。

3、显然,最小凸多边形上的边应该仅在以上矩阵中出现一次,因此,将以上矩阵中那些出现次数超过一次的边全部去掉,最后保留的便是最小凸多边形的边。

4、根据最小凸多边形的边,很容易得到构成最小凸多边形的结点的顺序,从而解决问题。

输入参数 points 是一个 2 * P 矩阵, P 为数据点的个数,第一行是这些数据点对应的 x 坐标,第二行是对应的 y 坐标;输出参数 polygon 是一个 2 * Q 矩阵, Q 为凸多边形的顶点个数(首尾相连),第一行是这些顶点对应的 x 坐标,第二行是对应的 y 坐标。代码实现如下:

function polygon = minimal_convex_polygon(points)
 % 进行 delaunay 三角剖分,将所有连接了的边保存在矩阵 lines 中
 triangles = sort(delaunay(points(1, :), points(2, :)), 2);
 lines = zeros(size(triangles, 1) * 3, 2);
 for i = 1:size(triangles, 1)
 lines(3 * i - 2,:) = [triangles(i, 1), triangles(i, 2)];
 lines(3 * i - 1,:) = [triangles(i, 1), triangles(i, 3)];
 lines(3 * i,:) = [triangles(i, 2), triangles(i, 3)];
 end
 % 去掉 lines 中出现次数超过一次的边
 [~, IA] = unique(lines, 'rows');
 lines = setdiff(lines(IA, :), lines(setdiff(1:size(lines, 1), IA), :), 'rows');
 % 跟踪 lines 中的数据点,将凸多边形的顶点编号保存在 seqs 中
 seqs = zeros(size(lines, 1) + 1,1);
 seqs(1:2) = lines(1, :);
 lines(1, :) = [];
 for i = 3:size(seqs)
 pos = find(lines == seqs(i - 1));
 row = rem(pos - 1, size(lines, 1)) + 1;
 col = ceil(pos / size(lines, 1));
 seqs(i) = lines(row, 3 - col);
 lines(row, :) = [];
 end
 % 根据 seqs , 得到凸多边形顶点坐标
 polygon = points(:, seqs);
end

定义了实现函数,下面进行调用:

plot(Pp(1,:),Pp(2,:), '*r', 'LineWidth', 4);  % Pp第一行为x坐标,第二行为y坐标
polygon = minimal_convex_polygon(Pp);
hold on;
plot(polygon(1, :), polygon(2, :), 'LineWidth', 2);

效果图片我还不会添加进来,有兴趣的朋友可以试一试。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

C++中四种对象生存期和作用域以及static的用法总结分析

以下是对C++中四种对象生存期和作用域以及static的用法进行了详细的介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

C++嵌套类与局部类详细解析

从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类之外的作用域使用该类名时,需要加名字限定
收藏 0 赞 0 分享

C++空类详解

以下是对C++中的空类进行了详细的介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

C++之友元:友元函数和友元类详解

友元是一种允许非类成员函数访问类的非公有成员的一种机制。可以把一个函数指定为类的友元,也可以把整个类指定为另一个类的友元
收藏 0 赞 0 分享

C++中返回指向函数的指针示例

int (*ff(int)) (int *,int);表示:ff(int)是一个函数,带有一个int型的形参,该函数返回int (*) (int *,int),它是一个指向函数的指针,所指向的函数返回int型并带有两个分别是Int*和int型的形参
收藏 0 赞 0 分享

C数据结构之单链表详细示例分析

以下是对C语言中的单链表进行了详细的分析介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

C数据结构之双链表详细示例分析

以下是对c语言中的双链表进行了详细的分析介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

浅析如何在c语言中调用Linux脚本

如何在c语言中调用Linux脚本呢?下面小编就为大家详细的介绍一下吧!需要的朋友可以过来参考下
收藏 0 赞 0 分享

深入解析unsigned int 和 int

以下是对unsigned int和int进行了详细的分析介绍,需要的朋友可以过来参考下
收藏 0 赞 0 分享

浅谈C++中的string 类型占几个字节

本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节
收藏 0 赞 0 分享
查看更多