联通算法

处理图片噪点最好的方式联通算法。这里贴出四联通跟八联通的代码实现c#

四联通:

Dictionary<float, List<Point>> FourConnections(float[,] data)
    {
        //一种标记的点的个数
        Dictionary<float, List<Point>> dic_label_p = new Dictionary<float, List<Point>>();
        //标记
        int label = 1;
        for (int y = 0; y < data.GetLength(0); y++)
        {
            for (int x = 0; x < data.GetLength(1); x++)
            {
                //如果该数据不为0
                if (data[y, x] != 0)
                {
                    List<float> ContainsLabel = new List<float>();
                    #region 第一行
                    if (y == 0)//第一行只看左边
                    {
                        //第一行第一列,如果不为0,那么填入标记
                        if (x == 0)
                        {
                            data[y, x] = label;
                            label++;
                        }
                        //第一行,非第一列
                        else
                        {
                            //如果该列的左侧数据不为0,那么该数据标记填充为左侧的标记
                            if (data[y, x - 1] != 0)
                            {
                                data[y, x] = data[y, x - 1];
                            }
                            //否则,填充自增标记
                            else
                            {
                                data[y, x] = label;
                                label++;
                            }
                        }
                    }
                    #endregion
                    #region 非第一行
                    else
                    {
                        if (x == 0)//最左边  --->不可能出现衔接情况
                        {
                            /*分析上和右上*/
                            //如果上方数据不为0,则该数据填充上方数据的标记
                            if (data[y - 1, x] != 0)
                            {
                                data[y, x] = data[y - 1, x];
                            }
                            //都为0,则填充自增标记
                            else
                            {
                                data[y, x] = label;
                                label++;
                            }
                        }
                        else//中间    --->可能出现衔接情况
                        {
                            //重新实例化需要改变的标记
                            ContainsLabel = new List<float>();
                            /*分析左上、上和右上*/
                            //上方数据不为0(中间数据),直接填充上方标记
                            if (data[y - 1, x] != 0)
                            {
                                data[y, x] = data[y - 1, x];
                                if (data[y, x - 1] != 0)
                                {
                                    if (data[y - 1, x] != data[y, x - 1])
                                    {
                                        ContainsLabel.Add(data[y, x - 1]);
                                    }
                                }
                            }
                            //上方数据为0
                            else
                            {
                                //左侧不为0,则填充左侧标记
                                if (data[y, x - 1] != 0)
                                {
                                    data[y, x] = data[y, x - 1];
                                }
                                //左侧为0,则填充自增标记
                                else
                                {
                                    data[y, x] = label;
                                    label++;
                                }
                            }
                        }
                    }
                    #endregion

                    //如果当前字典不存在该标记,那么创建该标记的Key
                    if (!dic_label_p.ContainsKey(data[y, x]))
                    {
                        dic_label_p.Add(data[y, x], new List<Point>());
                    }
                    //添加当前标记的点位
                    dic_label_p[data[y, x]].Add(new Point(x, y));

                    //备份需要更改标记的位置
                    List<Point> NeedChangedPoints = new List<Point>();
                    //如果有需要更改的标记
                    for (int i = 0; i < ContainsLabel.Count; i++)
                    {
                        for (int pcount = 0; pcount < dic_label_p[ContainsLabel[i]].Count;)
                        {
                            Point p = dic_label_p[ContainsLabel[i]][pcount];
                            NeedChangedPoints.Add(p);
                            data[p.Y, p.X] = data[y, x];
                            dic_label_p[ContainsLabel[i]].Remove(p);
                            dic_label_p[data[y, x]].Add(p);
                        }
                        dic_label_p.Remove(ContainsLabel[i]);
                    }
                }
            }
        }
        return dic_label_p;
    }

八联通

Dictionary<float, List<Point>> CalConnections(float[,] data)
    {
        //一种标记的点的个数
        Dictionary<float, List<Point>> dic_label_p = new Dictionary<float, List<Point>>();
        //标记
        int label = 1;
        for (int y = 0; y < data.GetLength(0); y++)
        {
            for (int x = 0; x < data.GetLength(1); x++)
            {
                //如果该数据不为0
                if (data[y, x] != 0)
                {
                    List<float> ContainsLabel = new List<float>();
                    #region 第一行
                    if (y == 0)//第一行只看左边
                    {
                        //第一行第一列,如果不为0,那么填入标记
                        if (x == 0)
                        {
                            data[y, x] = label;
                            label++;
                        }
                        //第一行,非第一列
                        else
                        {
                            //如果该列的左侧数据不为0,那么该数据标记填充为左侧的标记
                            if (data[y, x - 1] != 0)
                            {
                                data[y, x] = data[y, x - 1];
                            }
                            //否则,填充自增标记
                            else
                            {
                                data[y, x] = label;
                                label++;
                            }
                        }
                    }
                    #endregion
                    #region 非第一行
                    else
                    {
                        if (x == 0)//最左边  --->不可能出现衔接情况
                        {
                            /*分析上和右上*/
                            //如果上方数据不为0,则该数据填充上方数据的标记
                            if (data[y - 1, x] != 0)
                            {
                                data[y, x] = data[y - 1, x];
                            }
                            //上方数据为0,右上方数据不为0,则该数据填充右上方数据的标记
                            else if (data[y - 1, x + 1] != 0)
                            {
                                data[y, x] = data[y - 1, x + 1];
                            }
                            //都为0,则填充自增标记
                            else
                            {
                                data[y, x] = label;
                                label++;
                            }
                        }
                        else if (x == data.GetLength(1) - 1)//最右边   --->不可能出现衔接情况
                        {
                            /*分析左上和上*/
                            //如果左上数据不为0,则则该数据填充左上方数据的标记
                            if (data[y - 1, x - 1] != 0)
                            {
                                data[y, x] = data[y - 1, x - 1];
                            }
                            //左上方数据为0,上方数据不为0,则该数据填充上方数据的标记
                            else if (data[y - 1, x] != 0)
                            {
                                data[y, x] = data[y - 1, x];
                            }
                            //左上和上都为0
                            else
                            {
                                //如果左侧数据不为0,则该数据填充左侧数据的标记
                                if (data[y, x - 1] != 0)
                                {
                                    data[y, x] = data[y, x - 1];
                                }
                                //否则填充自增标记
                                else
                                {
                                    data[y, x] = label;
                                    label++;
                                }
                            }
                        }
                        else//中间    --->可能出现衔接情况
                        {
                            //重新实例化需要改变的标记
                            ContainsLabel = new List<float>();
                            /*分析左上、上和右上*/
                            //上方数据不为0(中间数据),直接填充上方标记
                            if (data[y - 1, x] != 0)
                            {
                                data[y, x] = data[y - 1, x];
                            }
                            //上方数据为0
                            else
                            {
                                //左上和右上都不为0,填充左上标记
                                if (data[y - 1, x - 1] != 0 && data[y - 1, x + 1] != 0)
                                {
                                    data[y, x] = data[y - 1, x - 1];
                                    //如果右上和左上数据标记不同,则右上标记需要更改
                                    if (data[y - 1, x + 1] != data[y - 1, x - 1])
                                    {
                                        ContainsLabel.Add(data[y - 1, x + 1]);
                                    }
                                }
                                //左上为0,右上不为0
                                else if (data[y - 1, x - 1] == 0 && data[y - 1, x + 1] != 0)
                                {
                                    //左侧不为0,则填充左侧标记
                                    if (data[y, x - 1] != 0)
                                    {
                                        data[y, x] = data[y, x - 1];
                                        //如果左侧和右上标记不同,,则右上标记需要更改
                                        if (data[y - 1, x + 1] != data[y, x - 1])
                                        {
                                            ContainsLabel.Add(data[y - 1, x + 1]);
                                        }
                                    }
                                    //左侧为0,则直接填充右上标记
                                    else
                                    {
                                        data[y, x] = data[y - 1, x + 1];
                                    }
                                }
                                //左上不为0,右上为0,填充左上标记
                                else if (data[y - 1, x - 1] != 0 && data[y - 1, x + 1] == 0)
                                {
                                    data[y, x] = data[y - 1, x - 1];
                                }
                                //左上和右上都为0
                                else if (data[y - 1, x - 1] == 0 && data[y - 1, x + 1] == 0)
                                {
                                    //如果左侧不为0,则填充左侧标记
                                    if (data[y, x - 1] != 0)
                                    {
                                        data[y, x] = data[y, x - 1];
                                    }
                                    //否则填充自增标记
                                    else
                                    {
                                        data[y, x] = label;
                                        label++;
                                    }

                                }
                            }

                        }
                    }
                    #endregion

                    //如果当前字典不存在该标记,那么创建该标记的Key
                    if (!dic_label_p.ContainsKey(data[y, x]))
                    {
                        dic_label_p.Add(data[y, x], new List<Point>());
                    }
                    //添加当前标记的点位
                    dic_label_p[data[y, x]].Add(new Point(x, y));

                    //备份需要更改标记的位置
                    List<Point> NeedChangedPoints = new List<Point>();
                    //如果有需要更改的标记
                    for (int i = 0; i < ContainsLabel.Count; i++)
                    {
                        for (int pcount = 0; pcount < dic_label_p[ContainsLabel[i]].Count;)
                        {
                            Point p = dic_label_p[ContainsLabel[i]][pcount];
                            NeedChangedPoints.Add(p);
                            data[p.Y, p.X] = data[y, x];
                            dic_label_p[ContainsLabel[i]].Remove(p);
                            dic_label_p[data[y, x]].Add(p);
                        }
                        dic_label_p.Remove(ContainsLabel[i]);
                    }
                }
            }
        }
        return dic_label_p;
    }
时间: 2024-11-28 16:38:08

联通算法的相关文章

迷宫城堡 -- 强联通分量

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10908    Accepted Submission(s): 4887 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A

HDU 1269 迷宫城堡 【强联通分量(模版题)】

知识讲解: 在代码里我们是围绕 low 和 dfn 来进行DFS,所以我们务必明白 low 和 dfn 是干什么的? 有什么用,这样才能掌握他. 1.  dfn[]  遍历到这个点的时间 2.  low[]  遍历到这个所能连接到的最短时间,说明那个最短时间可以遍历带他,他也可以走到那个最短时间. 3.  我们每次出栈的点就是一个强联通分量(这里建议观看一下课件里面的Tarjan求强联通算法的模拟过程). #include<cstdio> #include<cstdlib> #in

证码识别--type1

?从最简单的开始.主要是研究通用的方法.整理通用的框架和思路,最后整理超越之上的价值. 思路,主要是两个部分:图像的分割和图像的识别.这里的分割,可能是分割到字符的程度,也可能是分割到笔画的程度. 对于type1来说 其分割还是比较简单的,这种程度的验证码识别,就要达到95%以上才可以. 一.图像分析 可以看出来,图像中有孤立的干扰点的,这些点,通过8联通算法,是很好去掉的 有一定的效果,再进一步去掉在竖直方向孤立的点 目前这个结果算是比较干净的了 二.投影计算 通过看字符的特点,里面加了一些单

51nod 1076 2条不相交的路径 无向图强联通分量 trajan算法

1076 2条不相交的路径 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 给出一个无向图G的顶点V和边E.进行Q次查询,查询从G的某个顶点V[s]到另一个顶点V[t],是否存在2条不相交的路径.(两条路径不经过相同的边) (注,无向图中不存在重边,也就是说确定起点和终点,他们之间最多只有1条路) Input 第1行:2个数M N,中间用空格分开,M是顶点的数量,N是边的数量.(2 <= M <= 25000, 1 <= N <=

POJ 2186-Popular Cows (图论-强联通分量Korasaju算法)

题目链接:http://poj.org/problem?id=2186 题目大意:有n头牛和m对关系, 每一对关系有两个数(a, b)代表a牛认为b牛是“受欢迎”的,且这种关系具有传递性, 如果a牛认为b牛“受欢迎”, b牛认为c牛“受欢迎”, 那么a牛也认为c牛“受欢迎”. 现在想知道有多少头牛受除他本身外其他所有牛的欢迎? 解题思路:如果有两头或者多头牛受除他本身外其他所有牛的欢迎, 那么在这两头或者多头牛之中, 任意一头牛也受两头或者多头牛中别的牛的欢迎, 即这两头或者多头牛同属于一个强联

强联通块tarjan算法

http://poj.org/problem?id=1236第一问:需要几个学校存在软件,才能通过传递,使得所有的学校都有软件 用tarjan算法求出强联通分量后,将每个联通分量缩成一个点,那么问题1的答案就是入度为0的点的个数 为什么?入度为0的点,肯定不能通过其他学校传送软件给他,所以他必须存在一份软件第二问:需要加几条边,才能使得图强联通 缩点后,a为所有入度为0的点的个数,b为所有出度为0的点的个数,那么答案就是max(a,b) 1 #include <stdio.h> 2 #incl

POJ 3352-Road Construction (图论-双边联通分支算法)

题目大意:一个图,要求你加入最少的边,使得最后得到的图为一个边双连通分支.所谓的边双连通分支,即不存在桥的连通分支(题目保证数据中任意两点都联通). 解题思路:先用tarjan算法进行缩点建立DAG图, 然后再进行寻找度为1的点有个数x, 那么需要添加的边即为(x+1)/ 2; 起初这样写, 一直WA,然后发现下面两个数据,发现并不能过. #include <stdio.h> #include <set> #include <vector> #include <s

强联通分量之kosaraju算法

首先定义:强联通分量是有向图G=(V, E)的最大结点集合,满足该集合中的任意一对结点v和u,路径vu和uv同时存在. kosaraju算法用来寻找强联通分量.对于图G,它首先随便找个结点dfs,求出每个节点最后一次访问的时间戳f(x),然后我们建立反图Gt,接着根据倒序的时间戳来dfs每个节点,每次dfs到的结点集合就是一个强联通分量.事实上这个算法的思想和拓扑排序类似. 我们来证明它(注意这里面的图指原图,而不是反图): 引理:对于G中的两个强联通分量C和C',若点u属于C,点v属于C',且

tarjan算法求强联通分量

昨天学到了一个新的算法tarjan算法,感觉最近都没有怎么学习了...(最近有个感悟啊,就是学习一定的通过实践来进步的. 现在才明白为什么高中的时候老师强调一定要刷题,当然刷完题目之后的总结也非常地重要! 这个tarjan算法用来求强联通分量,在网上看了几篇blog,然后做了一个题目,感觉这个算法很nice啊... 如果没有学这个算法, 我肯定会想直接dfs吧orz... dfs看看是不是每个点能到达连通分量的其他点,好像这样非常麻烦啊,还要记录这个点从哪里来的...这样一想,好像直接dfs我做