改进Zhang Suen细化算法的C#实现

本文主要实现了改进Zhang Suen细化算法的C#实现,相关论文 :“牟少敏,杜海洋,苏平,查绪恒,陈光艺.一种改进的快速并行细化算法[J].微电子学与计算机,2013,(第1期)” 。这篇论文中关于Zhang Suen细化算法的描述,貌似存在问题。本文的算法中的意思是两次标记的点迭代后同时删除。而zhang快速算法,是分为两步删除边界点的。第一步迭代之后,已经做标记的点就需要删除了。如果两步可以放在一起删除的话,为什么不在一次迭代中将几个条件一起判断呢

一:Zhang-Suen细化算法介绍

Zhang-Suen细化算法通常是一个迭代算法,整个迭代过程分为两步:

Step One:循环所有前景像素点,对符合如下条件的像素点标记为删除:

1.      2 <= N(p1) <=6

2.      S(P1) = 1

3.      P2 * P4 * P6 = 0

4.      P4 * P6 * P8 = 0

其中N(p1)表示跟P1相邻的8个像素点中,为前景像素点的个数

S(P1)表示从P2 ~ P9 ~ P2像素中出现0~1的累计次数,其中0表示背景,1表示前景

完整的P1 ~P9的像素位置与举例如下:

 

其中 N(p1) = 4, S(P1) = 3, P2*P4*P6=0*0*0=0, P4*P6*P8=0*0*1=0, 不符合条件,无需标记为删除。

Step Two:跟Step One很类似,条件1、2完全一致,只是条件3、4稍微不同,满足如下条件的像素P1则标记为删除,条件如下:

1.      2 <= N(p1) <=6

2.      S(P1) = 1

3.      P2 * P4 * P8 = 0

4.      P2 * P6 * P8 = 0

循环上述两步骤,直到两步中都没有像素被标记为删除为止,输出的结果即为二值图像细化后的骨架。

 

二:代码实现步骤

        #region 改进 Zhang-Suen algorithm

        public Bitmap zhang_thinimage_improve(Bitmap bmp)
        {
            int imgWidth = bmp.Width;
            int imgHeight = bmp.Height;
            byte[,] BinaryArray = new byte[imgHeight, imgWidth];
            int depth = Bitmap.GetPixelFormatSize(bmp.PixelFormat);
            if (depth != 1)//判断位深度 
            {
                int threshold = 0;
                BinaryArray = ToBinaryArray(bmp, out threshold);
            }
            else
            {
                BinaryArray = BinaryBitmapToBinaryArray(bmp);
            }
            int[] Zhangmude = new int[9];
            //int deletecount = 0;
            List<Point> deletelist = new List<Point>();
            while (true)
            {
                for (int y = 1; y < imgHeight-1; y++)
                {
                    for (int x = 1; x < imgWidth-2; x++)
                    {
                        if (BinaryArray[y, x] == 0)
                        {
                            Zhangmude[0] = 1;
                            if (BinaryArray[y - 1, x] == 0) Zhangmude[1] = 1;
                            else Zhangmude[1] = 0;
                            if (BinaryArray[y - 1, x + 1] == 0) Zhangmude[2] = 1;
                            else Zhangmude[2] = 0;
                            if (BinaryArray[y, x + 1] == 0) Zhangmude[3] = 1;
                            else Zhangmude[3] = 0;
                            if (BinaryArray[y + 1, x + 1] == 0) Zhangmude[4] = 1;
                            else Zhangmude[4] = 0;
                            if (BinaryArray[y + 1, x] == 0) Zhangmude[5] = 1;
                            else Zhangmude[5] = 0;
                            if (BinaryArray[y + 1, x - 1] == 0) Zhangmude[6] = 1;
                            else Zhangmude[6] = 0;
                            if (BinaryArray[y, x - 1] == 0) Zhangmude[7] = 1;
                            else Zhangmude[7] = 0;
                            if (BinaryArray[y - 1, x - 1] == 0) Zhangmude[8] = 1;
                            else Zhangmude[8] = 0;
                            int whitepointtotal = 0;
                            for (int k = 1; k < 9; k++)
                            {
                                //得到1的个数
                                whitepointtotal = whitepointtotal + Zhangmude[k];
                            }
                            if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
                            {
                                //得到01的个数
                                int ap = 0;
                                if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
                                if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
                                if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
                                if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
                                if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
                                if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
                                if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
                                if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
                                //计算bp
                                int bp = 0;
                                bp += Zhangmude[1];
                                bp += Zhangmude[2] << 1;
                                bp += Zhangmude[3] << 2;
                                bp += Zhangmude[4] << 3;
                                bp += Zhangmude[5] << 4;
                                bp += Zhangmude[6] << 5;
                                bp += Zhangmude[7] << 6;
                                bp += Zhangmude[8] << 7;
                                if (ap == 1 || bp == 65 || bp == 5 || bp == 20 || bp == 80 || bp == 13 || bp == 22 || bp == 52 || bp == 133 || bp == 141 || bp == 54)
                                {
                                    if ((Zhangmude[1] * Zhangmude[3] * Zhangmude[5] == 0) && (Zhangmude[3] * Zhangmude[5] * Zhangmude[7] == 0))
                                    {
                                        deletelist.Add(new Point(y, x));
                                    }
                                }
                            }
                        }
                    }
                }
                if (deletelist.Count() == 0) break;
                foreach (var deleteItem in deletelist)
                {
                    BinaryArray[deleteItem.X, deleteItem.Y] = 255;
                }
                deletelist.Clear();
                for (int y = 1; y < imgHeight-1; y++)
                {
                    for (int x = 1; x < imgWidth-1; x++)
                    {
                        if (BinaryArray[y, x] == 0)
                        {
                            Zhangmude[0] = 1;
                            if (BinaryArray[y - 1, x] == 0) Zhangmude[1] = 1;
                            else Zhangmude[1] = 0;
                            if (BinaryArray[y - 1, x + 1] == 0) Zhangmude[2] = 1;
                            else Zhangmude[2] = 0;
                            if (BinaryArray[y, x + 1] == 0) Zhangmude[3] = 1;
                            else Zhangmude[3] = 0;
                            if (BinaryArray[y + 1, x + 1] == 0) Zhangmude[4] = 1;
                            else Zhangmude[4] = 0;
                            if (BinaryArray[y + 1, x] == 0) Zhangmude[5] = 1;
                            else Zhangmude[5] = 0;
                            if (BinaryArray[y + 1, x - 1] == 0) Zhangmude[6] = 1;
                            else Zhangmude[6] = 0;
                            if (BinaryArray[y, x - 1] == 0) Zhangmude[7] = 1;
                            else Zhangmude[7] = 0;
                            if (BinaryArray[y - 1, x - 1] == 0) Zhangmude[8] = 1;
                            else Zhangmude[8] = 0;
                            int whitepointtotal = 0;
                            for (int k = 1; k < 9; k++)
                            {
                                //得到1的个数
                                whitepointtotal = whitepointtotal + Zhangmude[k];
                            }
                            if ((whitepointtotal >= 2) && (whitepointtotal <= 6))
                            {
                                //得到01的个数
                                int ap = 0;
                                if ((Zhangmude[1] == 0) && (Zhangmude[2] == 1)) ap++;
                                if ((Zhangmude[2] == 0) && (Zhangmude[3] == 1)) ap++;
                                if ((Zhangmude[3] == 0) && (Zhangmude[4] == 1)) ap++;
                                if ((Zhangmude[4] == 0) && (Zhangmude[5] == 1)) ap++;
                                if ((Zhangmude[5] == 0) && (Zhangmude[6] == 1)) ap++;
                                if ((Zhangmude[6] == 0) && (Zhangmude[7] == 1)) ap++;
                                if ((Zhangmude[7] == 0) && (Zhangmude[8] == 1)) ap++;
                                if ((Zhangmude[8] == 0) && (Zhangmude[1] == 1)) ap++;
                                //计算bp
                                int bp = 0;
                                bp += Zhangmude[1];
                                bp += Zhangmude[2] << 1;
                                bp += Zhangmude[3] << 2;
                                bp += Zhangmude[4] << 3;
                                bp += Zhangmude[5] << 4;
                                bp += Zhangmude[6] << 5;
                                bp += Zhangmude[7] << 6;
                                bp += Zhangmude[8] << 7;
                                if (ap == 1 || bp == 65 || bp == 5 || bp == 20 || bp == 80 || bp == 13 || bp == 22 || bp == 52 || bp == 133 || bp == 141 || bp == 54)
                                {
                                    if ((Zhangmude[1] * Zhangmude[3] * Zhangmude[7] == 0) && (Zhangmude[1] * Zhangmude[5] * Zhangmude[7] == 0))
                                    {
                                        deletelist.Add(new Point(y, x));
                                    }
                                }
                            }
                        }
                    }
                }
                if (deletelist.Count() == 0) break;
                foreach (var deleteItem in deletelist)
                {
                    BinaryArray[deleteItem.X, deleteItem.Y] = 255;
                }
                deletelist.Clear();
            }
            Bitmap dstBmp = BinaryArrayToBinaryBitmap(BinaryArray);
            return dstBmp;

        }

        #endregion

 

还有一个问题需要注意,找到要删除的点之后不能立即删除,而是把找到的点做标记,等第一步全部遍历完之后才删除标记的点。同样第二步也是这样。

 

下面是实验结果:

  

 

 


本文借鉴了两篇博客,下面是原文地址:

https://blog.csdn.net/u011941438/article/details/54628836

https://blog.csdn.net/jia20003/article/details/52142992

 

posted @ 2018-12-25 11:38  微光-倾城  阅读(2098)  评论(0编辑  收藏  举报