通过"并查集"进行图像的连通区域实现

并查集是个什么概念也是通过刷题刷到的,然后就稍微了解了下
小白记录并查集自己实现图像连通区域问题

完整代码放在最后面

并查集可以自己谷歌,目前有点被搞得头晕

在图像里面经常性的需要用连通区域这个概念,尤其是对图像分割,跟踪以及一些需要用到图像基本处理的地方,不过使用OpenCV的话很简单,一个API解决一切问题findContours,不过既然遇到了,就更应该去了解下更底层的东西以及原理性的东西吧!

可能对于连通区域用DFS更好理解吧,DFS:简单点理解就是不撞南墙不回头的那种算法

搞了一下午,被弄得头有点晕了,先记录下来,等清醒了再来理一理思路

- 首先自己生成简单的连通图像


此处有两个白色的连通区域,目的是将他们分割出来
生成图像的代码

Mat Image = Mat::zeros(500, 500, CV_8UC1);
Mat gray(200, 200, CV_8UC1);
gray.setTo(255);
gray.copyTo(Image(Rect(100, 100, 200, 200)));
Image(Rect(0, 0, 10, 20)).setTo(255);

- 然后需要生成的分割图为


总共分为三个区域的连通区域,其实这个有点像是图像分割了,在图像中加个KMeans的话或许就可以了,不过Kmeans原理也不难,有写过这样的博客,转这里

- 如何才能生成上面的图像呢,就是并查集算法了

class Solution {public:int director[4][2] = { {0,-1},{-1,0},{0,1},{1,0} };map<int, int> m;int find(int x){auto it = m.find(x);if (it == m.end()){m[x] = x;}if (m[x] != x){m[x] = find(m[x]);}return m[x];}void con_union(int x, int y){m[find(y)] = find(x);}void solve(vector<vector<int>>& board){int row = board.size();if (row == 0) return;int col = board[0].size();int total_num = row * col;for (int i = 0; i < row; ++i){for (int j = 0; j < col; ++j){if (board[i][j] == 255){   for (int k = 0; k < 4; ++k){int ROW = i + director[k][0];int COL = j + director[k][1];if (ROW >= 0 && ROW < row && COL >= 0 && COL < col && board[ROW][COL] == 255){con_union(i*col + j, ROW*col + COL);}}}}}}
};

这里是主要的并查集算法,主要的原理,还是通过find函数进行操作的,对每个坐标位置进行他们之间连通邻点的根值做索引,通过根值进行连通区域的分割操作

先记录下来,完整代码在这里

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>using namespace std;
using namespace cv;class Solution {public:int director[4][2] = { {0,-1},{-1,0},{0,1},{1,0} };map<int, int> m;int findx(int x){auto it = m.find(x);if (it == m.end()){m[x] = x;}if (m[x] != x){m[x] = findx(m[x]);}return m[x];}void con_union(int x, int y){m[findx(y)] = findx(x);}void solve(vector<vector<int>>& board){int row = board.size();if (row == 0) return;int col = board[0].size();int total_num = row * col;for (int i = 0; i < row; ++i){for (int j = 0; j < col; ++j){if (board[i][j] == 255){   for (int k = 0; k < 4; ++k){int ROW = i + director[k][0];int COL = j + director[k][1];if (ROW >= 0 && ROW < row && COL >= 0 && COL < col && board[ROW][COL] == 255){con_union(i*col + j, ROW*col + COL);}}}}}//set<int> s;  // 连通区域的数量//int index = 0;//for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)//{// index++;//    s.insert(it->second);//}//cout << "index=" << index << endl;//cout << "s.size=" << s.size() << endl;//int s_size = s.size();//vector<int> V(s_size, 0);//int v_begin = 0;//for (set<int>::iterator s_it = s.begin(); s_it != s.end(); s_it++)//{//   V[v_begin++] = *s_it;//  cout << *s_it << endl;//}vector<int> V_1;for (map<int, int>::iterator it = m.begin(); it != m.end(); it++){int temp = it->second;if (V_1.empty()){V_1.push_back(temp);}else{if (find(V_1.begin(), V_1.end(), temp) == V_1.end()){V_1.push_back(temp);}}}int s_size = V_1.size();map<int,int>::iterator it = m.begin();for (int i = 0; i < row; ++i){for (int j = 0; j < col; ++j){int flag_index = i * col + j;if (it->first == flag_index){for (int l = 0; l < s_size; l++){if (m[flag_index] == V_1[l]){board[i][j] = l + 1;}}it++;}}}}
};int main(int argc, char* argv[])
{Mat Image = Mat::zeros(500, 500, CV_8UC1);Mat gray(200, 200, CV_8UC1);gray.setTo(255);imshow("gray", gray);gray.copyTo(Image(Rect(100, 100, 200, 200)));Image(Rect(0, 0, 10, 20)).setTo(255);imshow("Image", Image);vector<vector<int>> board(Image.rows, vector<int>(Image.cols));for (int row = 0; row < Image.rows; ++row){for (int col = 0; col < Image.cols; ++col){board[row][col] = (int)Image.at<uchar>(row, col);}}Solution s;s.solve(board);// 辅助颜色层Vec3b ColorTab[] ={Vec3b(0, 0, 255),Vec3b(0, 255, 0),Vec3b(255, 0, 0),Vec3b(0, 255, 255),Vec3b(255, 0, 255),Vec3b(255, 255, 0)};Mat result;cvtColor(Image, result, COLOR_GRAY2BGR);for (int row = 0; row < Image.rows; ++row){for (int col = 0; col < Image.cols; ++col){result.at<Vec3b>(row, col) = ColorTab[board[row][col]];}}imshow("....", result);waitKey(0);return 0;
}

不过有些代码肯定是多余的,自行做相应的删减操作吧!

最后有个问题,不知道是不是程序没有释放内存空间还是自己电脑的编译器有问题,前面跑几次还可以,后面总是跑不出来!我也不知道为什么,小白在这里让大佬们解释下呀,感激不尽!


2020-05-28:
重新审了一遍代码:终于知道问题出在了哪里,一个边界越界的问题,vector数组没有先判断下标再去索引相应的值

if (board[ROW][COL] == 255 && ROW >= 0 && ROW < row && COL >= 0 && COL < col)

就这个地方,现在重新改过来了,代码一点问题都没有
这也说明写代码要好好考虑下界限的问题了!!!

后面有时间更新下DFS的连通区域算法!!!

欢迎指正批评!!!
欢迎关注微信公众号–木木夕算法笔记,与博主交流!

通过并查集进行图像的连通区域实现相关推荐

  1. java并查集判断是否是连通图_并查集-判断图的连通

    首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比如随意给你两个点,让你判断它们是否连通,或者问你整幅图一共有几个连通分 ...

  2. matlab 求图像的连通区域的圆度并可视化

    代码 %% 圆度的计算 % 圆形需要是白色的,背景是黑色的,可以根据需要确定是否对图像进行反向 clc clear;close all; % %读取源图像 I = imread('1.bmp'); % ...

  3. Rumor CodeForces - 893C(并查集基本操作:维护连通块最值)

    题目链接 PS:这题也可以用dfs搜连通块,一遍搜一遍记录连通块的最值. AC代码: #include <iostream> #include <cstring> #inclu ...

  4. 模板 31 : 并查集(围棋棋子连通)

    围棋的棋子有黑色和白色两种,相同颜色的棋子如果是上下或左右相邻的,则称这两个棋子是连通的,直接或间接连通的棋子称为一块棋. •现在,不断给出N个落棋子的信息(颜色.横坐标.纵坐标),问棋盘上有多少块棋 ...

  5. 连通图的判断(并查集, DFS, BFS)

    首先要明确什么是连通图??? 连通图:对于一个图来说,图中的任意一个点都能访问到所有的点,则说明该图连通 很明显,如果要判断一个图是否连通,则必须要从任意一个搜索一遍,判断是否到达了所有的点,则很快会 ...

  6. Graph Destruction 并查集,图论(500)

    题意 : 给一n个点m条边的无向图,问逐渐删去1-n点及它们的边,分别输出当前剩下多少个连通区域 思路 : 求连通块,想到了并查集,但并查集是增边,这里是减边,只要倒序考虑问题即可,那么问题转换为 : ...

  7. LeetCode 1697. 检查边长度限制的路径是否存在(排序+并查集)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个 n 个点组成的无向图边集 edgeList ,其中 edgeList[i] = [ui, vi, disi] 表示点 ui 和点 vi 之间有一 ...

  8. LeetCode 685. 冗余连接 II(并查集)

    1. 题目 在本问题中,有根树指满足以下条件的有向图.该树只有一个根节点,所有其他节点都是该根节点的后继. 每一个节点只有一个父节点,除了根节点没有父节点. 输入一个有向图,该图由一个有着N个节点 ( ...

  9. LeetCode 886. 可能的二分法(着色DFS/BFS/拓展并查集)

    文章目录 1. 题目 2. 解题 2.1 DFS 2.2 BFS 2.3 并查集 1. 题目 给定一组 N 人(编号为 1, 2, -, N), 我们想把每个人分进任意大小的两组. 每个人都可能不喜欢 ...

最新文章

  1. R语言可视化包ggplot2绘制分组的条形图(bar plot、柱状图)实战:多变量柱状图
  2. 架空输电线路运行规程_架空输电线路导、地线安全系数的规定
  3. 每秒5百亿亿次!Meta祭出元宇宙巨兽,联手英伟达打造全球最强超算
  4. 壕!电子科大计算机学院助理教授年薪50万起步, 100万安家费+150万科研启动金!...
  5. linux 查看内核属性,怎么查看linux操作系统
  6. css对齐 挖坑~
  7. 三维模型格式总结整理
  8. IMX6ULL 学习bug记载
  9. 【SQL】关于SQL Server的性能优化——基础内容
  10. Windows打印机驱动开发
  11. python网络游戏脚本_用Python写一个游戏脚本,你会吗?
  12. Postfix部署【2】传输代理
  13. 微信小程序注册/登陆,若依后台获取token
  14. 一本专门学习PyQt5 GUI 的编程书
  15. 深度ip转换器手机版app_一键清理全能版app下载-一键清理全能版app手机版 v1.0.0...
  16. 常见的http请求返回数字的含义
  17. python定义字符串变量有两种常用方式_Python 1基础语法二(标识符、关键字、变量和字符串)...
  18. mysql中depart_mysql实训
  19. U盘病毒克星-USBKiller 2.2 特别版(可升级病毒库)
  20. 【总结】成骨细胞培养经验、常见问题以及培养方法

热门文章

  1. 【自用】Jupyter Notebook好看主题的设置
  2. 【互联网网站】v2ex.com
  3. 谈制定有效测试策略的重要性
  4. 01_ElasticSearch学习笔记
  5. oracle复习笔记之索引
  6. 知乎精华:生活中有哪些行为是高情商的表现?
  7. 谈谈Java与C#的区别
  8. vscode对json加注释
  9. 手把手带你给你的Linux驱动程序加入platform结构体
  10. Jitsi视频会议部署(一):总结