寻找连通域
来源:互联网 发布:淘宝钓鱼竿专卖 编辑:程序博客网 时间:2024/06/05 08:34
http://www.mrluoyi.com/blog/2012/03/connected-domain/#respond
寻找一副二值图像中的连通域。全图遍历+DFS深度优先搜索。
示例输入:
5 5
0 0 0 0 1
0 1 1 0 1
0 1 0 0 1
1 1 1 0 1
1 1 0 0 1
示例输出:
The number of connected domains is: 2
Connected domains are labeled as below:
0 0 0 0 2
0 3 3 0 2
0 3 0 0 2
3 3 3 0 2
3 3 0 0 2
第一种办法比较直观,是递归的办法,代码如下:
#include<stdio.h>//by Yi Luo (03/08/2012)#define max 500int I[max][max];int n, m;// size = n*m int num = 0;const int direction[][2]={{1,0},{0,-1},{0,1},{-1,0}};bool check(int x, int y){ if (x >= 0 && x < n && y >= 0 && y < m && I[x][y] == 1) { return true; }else { return false; }}bool DFS(int x, int y, int label){ if (1 != I[x][y]) { return false; }else { I[x][y] = label; for (int i = 0; i < 4; i++) { if (check(x + direction[i][0], y + direction[i][1])) { DFS(x + direction[i][0], y + direction[i][1], label); } } }return true;}int main(void){ scanf("%d%d", &n, &m); for (int i = 0; i < n; ++i) { for (int j=0; j< m; j++) { scanf("%d", &I[i][j]); } } int label = 2; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (DFS(i, j, label)) { label++; } } } num = label - 2; printf("\n\nThe number of connected domains is: %d\n", num); printf("Connected domains are labeled as below:\n\n"); for (int i = 0; i < n; ++i) { for (int j=0; j< m; j++) { printf("%d ", I[i][j]); } printf("\n"); } getchar(); getchar(); return 0;}
刚刚又学到了一种新的办法,就是直接扫描的办法,比较巧妙。对于四领域的情况,主要是考察每个前景点的左边、上边两个点的情况:
1、如果左边和上边都有标记过的前景点,则选择二者标号更小的作为当前点的标记,并将之前所有的大号改成小号;
2、如果只有左边是标记过的点,则将当前点和其左边点标号一致;
3、如果只有上边是标记过的点,则和上面的点标号一致;
4、如果左边和上边都没有标记过的点,则当前前景点新开一个标号。
代码如下:
#include<stdio.h>//by Yi Luo (03/09/2012)#define size 500int I[size][size];//二值图像矩阵 int n, m, min, max;// size = n*m int num = 0;//连通域数目 bool check(int x, int y){ if (x >= 0 && x <= n && y >= 0 && y <= m && I[x][y] != 0) { return true; }else { return false; }}int main(void){ scanf("%d%d", &n, &m); for (int i = 0; i < n; ++i) { for (int j=0; j< m; j++) { scanf("%d", &I[i][j]); } //读入二值图像矩阵 } int label = 1; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (check(i, j))//如果当前位置是合法前景 { if (check(i, j-1)) { if (check(i-1, j))//如果该点的左面、上面均是标注过的前景 { min = I[i-1][j]; max = I[i][j-1]; if (max < min) { min = I[i][j-1]; max = I[i-1][j]; for (int t = j; t >= 0; t--) { for (int w = i; w >=0; w--) { if (I[w][t] == max) { I[w][t] = min; } } } label--; } I[i][j] = min; } else //如果只有该点的左面是标注过的前景 { I[i][j] = I[i][j-1]; } } else if (check(i-1, j)) //如果只有该点的上面是标注过的前景 { I[i][j] = I[i-1][j]; } else //如果该点的左面,上面都不是标注过的前景 { label ++; I[i][j] = label; } } } } num = label - 1; printf("\n\nThe number of connected domains is: %d\n", num); printf("Connected domains are labeled as below:\n\n"); for (int i = 0; i < n; ++i) { for (int j=0; j< m; j++) { printf("%d ", I[i][j]); } //输出新的标注结果 printf("\n"); } getchar(); getchar(); return 0;}
- 寻找连通域
- matlab寻找最大连通域
- 如何寻找连通域的重心
- 如何寻找连通域的重心
- 寻找八连通区域
- 皮肤检测与克服光线影响的连通域寻找
- 皮肤检测与克服光线影响的连通域寻找
- 皮肤检测与克服光线影响的连通域寻找
- 皮肤检测与克服光线影响的连通域寻找
- 寻找强连通分支C语言
- [算法]寻找能与所有顶点连通的顶点
- 寻找有向无环图中的强连通分支C++
- 寻找有向图的强连通分支
- dfs hdu 1241 寻找连通分量的个数
- 深复制浅复制实践:寻找所有连通子图
- 图论——寻找无向连通图割点算法
- Tarjan算法寻找有向图的强连通分量
- opencv实现连通域
- !!!Constant Expression (From MSDN)
- symbian 内存检测
- ABAP行转化为列(转)
- linux为gpio构建的使用方法
- 如何序列化Control等复杂类型对象
- 寻找连通域
- Visual C++ 6.0 插件系列介绍
- apache:the requested operation has failed
- Oracle查询动、静态参数
- VIM常用命令
- Javascript -- 易错点
- BufferedReader和inputstream和Scanner的解释和比较
- html5废弃的元素和属性
- java.sql.Types