[转]灰度图像的腐蚀算法和细化算法(C#代码)

本文转自:http://www.cnblogs.com/yuanbao/archive/2008/04/12/1149923.html

最近做一些图像处理,需要将图像中的一些像素过滤一下,有网友给提了个名词:腐蚀算法。我不是学图像学的,乍一听,觉得很神奇。后来从网上收集了一些VC代码,研究了一下,发现其它也就是那么回事。尤其是腐蚀算法,我在以前的验证码图片去噪声的文章中提到过,只是那是我不知叫什么名词,就从用途出发,叫做“根据周边点数去噪”。腐蚀的原理也一样,就是根据当前点的周边点数(如3X3的,周边就有8个点)来修改当前点的状态的。 
    代码是我从VC代码中转译过来的,注释都沿用了原作者的文字(别说是剽窃,^_^)。唯一改进的地方是,原代码功能只能处理0和255的二值灰度(搞不懂为什么这样,对于250、128这样的都不行,还不如弄成二值灰度,别弄256灰度了),我将之改成了能根据0~255中任意灰度划界的256灰度图像!
    以下是C#代码:

  1        /// <summary>
  2        /// 该函数用于对图像进行腐蚀运算。结构元素为水平方向或垂直方向的三个点,
  3        /// 中间点位于原点;或者由用户自己定义3×3的结构元素。
  4        /// </summary>
  5        /// <param name="dgGrayValue">前后景临界值</param>
  6        /// <param name="nMode">腐蚀方式:0表示水平方向,1垂直方向,2自定义结构元素。</param>
  7        /// <param name="structure"> 自定义的3×3结构元素</param>

  8        public void ErosionPic(int dgGrayValue, int nMode, bool[,] structure)
  9        {
 10            int lWidth = bmpobj.Width;
 11            int lHeight = bmpobj.Height;
 12            Bitmap newBmp = new Bitmap(lWidth, lHeight);
 13
 14            int i, j, n, m;            //循环变量
 15            Color pixel;    //像素颜色值
 16
 17            if (nMode == 0)
 18            {
 19                //使用水平方向的结构元素进行腐蚀
 20                // 由于使用1×3的结构元素,为防止越界,所以不处理最左边和最右边
 21                // 的两列像素
 22                for (j = 0; j < lHeight; j++)
 23                {
 24                    for (i = 1; i < lWidth - 1; i++)
 25                    {
 26                        //目标图像中的当前点先赋成黑色
 27                        newBmp.SetPixel(i, j, Color.Black);
 28
 29                        //如果源图像中当前点自身或者左右有一个点不是黑色,
 30                        //则将目标图像中的当前点赋成白色
 31                        if (bmpobj.GetPixel(i - 1, j).R > dgGrayValue ||
 32                            bmpobj.GetPixel(i, j).R > dgGrayValue ||
 33                            bmpobj.GetPixel(i + 1, j).R > dgGrayValue)
 34                            newBmp.SetPixel(i, j, Color.White);
 35                    }

 36                }

 37            }

 38            else if (nMode == 1)
 39            {
 40                //使用垂真方向的结构元素进行腐蚀
 41                // 由于使用3×1的结构元素,为防止越界,所以不处理最上边和最下边
 42                // 的两行像素
 43                for (j = 1; j < lHeight - 1; j++)
 44                {
 45                    for (i = 0; i < lWidth; i++)
 46                    {
 47                        //目标图像中的当前点先赋成黑色
 48                        newBmp.SetPixel(i, j, Color.Black);
 49
 50                        //如果源图像中当前点自身或者左右有一个点不是黑色,
 51                        //则将目标图像中的当前点赋成白色
 52                        if (bmpobj.GetPixel(i, j - 1).R > dgGrayValue ||
 53                            bmpobj.GetPixel(i, j).R > dgGrayValue ||
 54                            bmpobj.GetPixel(i, j + 1).R > dgGrayValue)
 55                            newBmp.SetPixel(i, j, Color.White);
 56                    }

 57                }

 58            }

 59            else
 60            {
 61                if (structure.Length != 9)  //检查自定义结构
 62                    return;
 63                //使用自定义的结构元素进行腐蚀
 64                // 由于使用3×3的结构元素,为防止越界,所以不处理最左边和最右边
 65                // 的两列像素和最上边和最下边的两列像素
 66                for (j = 1; j < lHeight - 1; j++)
 67                {
 68                    for (i = 1; i < lWidth - 1; i++)
 69                    {
 70                        //目标图像中的当前点先赋成黑色
 71                        newBmp.SetPixel(i, j, Color.Black);
 72                        //如果原图像中对应结构元素中为黑色的那些点中有一个不是黑色,
 73                        //则将目标图像中的当前点赋成白色
 74                        for (m = 0; m < 3; m++)
 75                        {
 76                            for (n = 0; n < 3; n++)
 77                            {
 78                                if (!structure[m, n])
 79                                    continue;
 80                                if (bmpobj.GetPixel(i + m - 1, j + n - 1).R > dgGrayValue)
 81                                {
 82                                    newBmp.SetPixel(i, j, Color.White);
 83                                    break;
 84                                }

 85                            }

 86                        }

 87                    }

 88                }

 89            }

 90
 91            bmpobj = newBmp;
 92        }

 93
 94
 95        /// <summary>
 96        /// 该函数用于对图像进行细化运算。要求目标图像为灰度图像
 97        /// </summary>
 98        /// <param name="dgGrayValue"></param>

 99        public void ThiningPic(int dgGrayValue)
100        {
101            int lWidth = bmpobj.Width;
102            int lHeight = bmpobj.Height;
103         //   Bitmap newBmp = new Bitmap(lWidth, lHeight);
104
105            bool bModified;            //脏标记    
106            int i, j, n, m;            //循环变量
107            Color pixel;    //像素颜色值
108
109            //四个条件
110            bool bCondition1;
111            bool bCondition2;
112            bool bCondition3;
113            bool bCondition4;
114
115            int nCount;    //计数器    
116            int[,] neighbour = new int[55];    //5×5相邻区域像素值
117
118
119
120            bModified = true;
121            while (bModified)
122            {
123                bModified = false;
124
125                //由于使用5×5的结构元素,为防止越界,所以不处理外围的几行和几列像素
126                for (j = 2; j < lHeight - 2; j++)
127                {
128                    for (i = 2; i < lWidth - 2; i++)
129                    {
130                        bCondition1 = false;
131                        bCondition2 = false;
132                        bCondition3 = false;
133                        bCondition4 = false;
134
135                        if (bmpobj.GetPixel(i, j).R > dgGrayValue)  
136                        {
137                            if(bmpobj.GetPixel(i, j).R<255)
138                                bmpobj.SetPixel(i, j, Color.White);
139                            continue;
140                        }

141
142                        //获得当前点相邻的5×5区域内像素值,白色用0代表,黑色用1代表
143                        for (m = 0; m < 5; m++)
144                        {
145                            for (n = 0; n < 5; n++)
146                            {
147                                neighbour[m, n] = bmpobj.GetPixel(i + m - 2, j + n - 2).R < dgGrayValue ? 1 : 0;
148                            }

149                        }

150
151                        //逐个判断条件。
152                        //判断2<=NZ(P1)<=6
153                        nCount = neighbour[11+ neighbour[12+ neighbour[13]
154                                + neighbour[21+ neighbour[23+
155                                +neighbour[31+ neighbour[32+ neighbour[33];
156                        if (nCount >= 2 && nCount <= 6)
157                        {
158                            bCondition1 = true;
159                        }

160
161                        //判断Z0(P1)=1
162                        nCount = 0;
163                        if (neighbour[12== 0 && neighbour[11== 1)
164                            nCount++;
165                        if (neighbour[11== 0 && neighbour[21== 1)
166                            nCount++;
167                        if (neighbour[21== 0 && neighbour[31== 1)
168                            nCount++;
169                        if (neighbour[31== 0 && neighbour[32== 1)
170                            nCount++;
171                        if (neighbour[32== 0 && neighbour[33== 1)
172                            nCount++;
173                        if (neighbour[33== 0 && neighbour[23== 1)
174                            nCount++;
175                        if (neighbour[23== 0 && neighbour[13== 1)
176                            nCount++;
177                        if (neighbour[13== 0 && neighbour[12== 1)
178                            nCount++;
179                        if (nCount == 1)
180                            bCondition2 = true;
181
182                        //判断P2*P4*P8=0 or Z0(p2)!=1
183                        if (neighbour[12* neighbour[21* neighbour[23== 0)
184                        {
185                            bCondition3 = true;
186                        }

187                        else
188                        {
189                            nCount = 0;
190                            if (neighbour[02== 0 && neighbour[01== 1)
191                                nCount++;
192                            if (neighbour[01== 0 && neighbour[11== 1)
193                                nCount++;
194                            if (neighbour[11== 0 && neighbour[21== 1)
195                                nCount++;
196                            if (neighbour[21== 0 && neighbour[22== 1)
197                                nCount++;
198                            if (neighbour[22== 0 && neighbour[23== 1)
199                                nCount++;
200                            if (neighbour[23== 0 && neighbour[13== 1)
201                                nCount++;
202                            if (neighbour[13== 0 && neighbour[03== 1)
203                                nCount++;
204                            if (neighbour[03== 0 && neighbour[02== 1)
205                                nCount++;
206                            if (nCount != 1)
207                                bCondition3 = true;
208                        }

209
210                        //判断P2*P4*P6=0 or Z0(p4)!=1
211                        if (neighbour[12* neighbour[21* neighbour[32== 0)
212                        {
213                            bCondition4 = true;
214                        }

215                        else
216                        {
217                            nCount = 0;
218                            if (neighbour[11== 0 && neighbour[10== 1)
219                                nCount++;
220                            if (neighbour[10== 0 && neighbour[20== 1)
221                                nCount++;
222                            if (neighbour[20== 0 && neighbour[30== 1)
223                                nCount++;
224                            if (neighbour[30== 0 && neighbour[31== 1)
225                                nCount++;
226                            if (neighbour[31== 0 && neighbour[32== 1)
227                                nCount++;
228                            if (neighbour[32== 0 && neighbour[22== 1)
229                                nCount++;
230                            if (neighbour[22== 0 && neighbour[12== 1)
231                                nCount++;
232                            if (neighbour[12== 0 && neighbour[11== 1)
233                                nCount++;
234                            if (nCount != 1)
235                                bCondition4 = true;
236                        }

237
238                        if (bCondition1 && bCondition2 && bCondition3 && bCondition4)
239                        {
240                            bmpobj.SetPixel(i, j, Color.White);
241                            bModified = true;
242                        }

243                        else
244                        {
245                            bmpobj.SetPixel(i, j, Color.Black);
246                        }

247                    }

248                }

249            }

250            // 复制细化后的图像
251        //    bmpobj = newBmp;
252        }

253
原文地址:https://www.cnblogs.com/freeliver54/p/1315239.html