C#图片验证码破解

最近在做模拟web登陆的时候碰到了图片验证码,这个时候就需要对验证码进行破解。

  1  public   class  GetImageValue
  2      {
  3           // 设定图片RGB字符串
  4           string [] ArrayList  =   new   string []{
  5               " 00011100011111110110001111000001110000011100000111000001110000011100000111000001011000110111111100011100 " ,   // 0
  6               " 00111000111110001111100000011000000110000001100000011000000110000001100000011000000110001111111111111111 " ,   // 1
  7               " 01111100111111101000001100000011000000110000011000001100000110000011000001100000110000001111111111111111 " ,   // 2
  8               " 01111100111111111000001100000011000001100111100001111110000001110000001100000011100001111111111001111100 " ,   // 3
  9               " 00001100000111000001110000111100011011000110110010001100110011001111111110111111000011000000110000001100 " ,   // 4
 10               " 11111111111111111100000011000000110000001111100011111110000001110000001100000011100001111111111001111100 " ,   // 5
 11               " 00011110001111110110000101100000110000001101111011101111111000111100000101000001011000110110111100011110 " ,   // 6
 12               " 01111010001111110000000100000000000000110000011000000100000011000000100000011000000110000011000000110000 " ,   // 7
 13               " 00111110011111110110001101100011011100100011111000111110011001111100000111000001111000110111111100111110 " ,   // 8
 14               " 00011100011110110110001111000001110000011010001101111111001111010000000100000001010000110101110000111100 " ,   // 9
 15               " 00111000111111101000010010000011100000111000001110000011000000111000001110000011110001001111011000111000 " ,   // 10
 16               " 00001100011111000111110000001100000011000000110000001100000011000000110000001100000011000111110101111111 " ,   // 11
 17               " 11111000110111000000010000000110000001100000110000011000001100000110000011000000100000000101111011111110 " ,   // 12
 18               " 10111000111111100000001000000110000011001111000011110100000011100000011000000110000011101111110011111000 " ,   // 13
 19               " 00000110000011100000111000001110000101100011011000100110011001001111111111111111000001000000011000000110 " ,   // 14
 20               " 11111110111111101000000010000000100000001111000011110100000011100000011000000110000011101111110011111000 " ,   // 15
 21               " 00111100011111101100001011000000100000001011110011111110110001111000001110000011110001101111111000111100 " ,   // 16
 22               " 11101111111111110000001100000010000001100000010000001000000110000001000000110000001100000110000001100000 " ,   // 17
 23               " 01111100111111101100011011000110110001000111110001111100110011101000001110000011110001101101111001111100 " ,   // 18
 24               " 01111000111111101100011010000011100000111100011111111111011110110000001100000100100001101111110001111000 " ,   // 19
 25               " 00111100011111111100001110000001110000011110001101111111001101010000000000000011010000010111111000111100 " ,   // 20=9
 26               " 00111000111111001100011010000011100000011000001100000011100000111000001010000011110001101111010000101000 " ,   // 21=0
 27               " 00111000010111010110001111000001110000011110001101111111001111010000000100000011010000100111011000111100 " ,   // 22=9
 28               " 00000110000010100000111000010110001101100011011001000110011001101011101111111111000001100000011000000110 " ,   // 23=4
 29               " 00011110001011110110000101000000110000001101101011111101011000111100000110000001010000110101111000011110 " ,   // 24=6
 30               " 00111100011111101110001101000001110000011110001101111111001111010000000100000011000000110101101000111100 " ,   // 25=9
 31               " 11111000111100000000011000000100000000100000110000011000001100000110000001000000100000001111110011111110 "     // 26=2
 32          };
 33 
 34           ///   <summary>
 35           ///  获取图片验证码数字
 36           ///   </summary>
 37           ///   <returns></returns>
 38           public   string  GetImageValues()
 39          {
 40               string  url  =   " http://xxxx.xxxx/image " ;
 41              WebRequest myWebRequest  =  WebRequest.Create(url);
 42              WebResponse myWebResponse  =  myWebRequest.GetResponse();
 43              Stream ReceiveStream  =  myWebResponse.GetResponseStream();
 44              Bitmap map  =   new  Bitmap(ReceiveStream,  false );
 45              UnCodebase ucode  =   new  UnCodebase(map);
 46 
 47              ucode.GrayByPixels();  // 灰度处理
 48 
 49              Bitmap[] pics  =  ucode.readMap();
 50               int [] gray  =   new   int [ 4 ];
 51               for  ( int  j  =   0 ; j  <   4 ; j ++ )
 52              {
 53                  gray[j]  =  ucode.GetSingleDgGrayValue(pics[j]);
 54              }
 55               string [] arr  =   new   string [ 4 ];
 56               for  ( int  i  =   0 ; i  <   4 ; i ++ )
 57              {
 58                  arr[i]  =  ucode.GetSingleBmpCode(pics[i], gray[i]);
 59              }
 60               string  picnum  =  getPicnums(arr);
 61               return  picnum;
 62          }
 63 
 64           public   string  getPicnums( string [] arr)
 65          {
 66               string  Code  =   "" ;
 67               for  ( int  i  =   0 ; i  <   4 ; i ++ )
 68              {
 69                   string  code  =  arr[i];    // 得到代码串
 70 
 71                   for  ( int  arrayIndex  =   0 ; arrayIndex  <  ArrayList.Length; arrayIndex ++ )
 72                  {
 73                       // 逐点判断特征码是否相同,允许误差!
 74                       char  temp1, temp2;
 75                       int  point  =   0 ;
 76                       if  (ArrayList[arrayIndex].Equals(code))
 77                      {
 78                          point  =   0 ;
 79                           if  (arrayIndex  >   9 )
 80                          {
 81                               if  (arrayIndex  ==   20   ||  arrayIndex  ==   22   ||  arrayIndex  ==   25 )
 82                              {
 83                                  Code  =  Code  +   " 9 " ;
 84                              }
 85                               else   if  (arrayIndex  ==   21 )
 86                              {
 87                                  Code  =  Code  +   " 0 " ;
 88                              }
 89                               else   if  (arrayIndex  ==   23 )
 90                              {
 91                                  Code  =  Code  +   " 4 " ;
 92                              }
 93                               else   if  (arrayIndex  ==   24 )
 94                              {
 95                                  Code  =  Code  +   " 6 " ;
 96                              }
 97                               else   if  (arrayIndex  ==   26 )
 98                              {
 99                                  Code  =  Code  +   " 2 " ;
100                              }
101                               else
102                              {
103                                  Code  =  Code  +  (arrayIndex  -   10 ).ToString();
104                              }
105                          }
106                           else
107                          {
108                              Code  =  Code  +  arrayIndex.ToString();
109                          }
110                           break ;
111                      }
112                       else
113                      {
114                           // 将字符串数组,直接转为单个字符进行对比,并记录不相同的点
115                           for  ( int  Comparison  =   0 ; Comparison  <  code.Length; Comparison ++ )
116                          {
117                              temp1  =  arr[i][Comparison];
118                              temp2  =  ArrayList[arrayIndex][Comparison];
119                               if  (temp1  !=  temp2)
120                              {
121                                  point  =  point  +   1 ;
122                              }
123                          }
124                      }
125 
126                       // 当不相同点的值小于10的时候,也就是说误差点小于10的时候则直接等于此数字,否则将跳出循环继续对下一个特征码进行判断
127                       if  (point  <   10 )
128                      {
129                           if  (arrayIndex  >   9 )
130                          {
131                               if  (arrayIndex  ==   20   ||  arrayIndex  ==   22   ||  arrayIndex  ==   25 )
132                              {
133                                  Code  =  Code  +   " 9 " ;
134                              }
135                               else   if  (arrayIndex  ==   21 )
136                              {
137                                  Code  =  Code  +   " 0 " ;
138                              }
139                               else   if  (arrayIndex  ==   23 )
140                              {
141                                  Code  =  Code  +   " 4 " ;
142                              }
143                               else   if  (arrayIndex  ==   24 )
144                              {
145                                  Code  =  Code  +   " 6 " ;
146                              }
147                               else   if  (arrayIndex  ==   26 )
148                              {
149                                  Code  =  Code  +   " 2 " ;
150                              }
151                               else
152                              {
153                                  Code  =  Code  +  (arrayIndex  -   10 ).ToString();
154                              }
155                          }
156                           else
157                          {
158                              Code  =  Code  +  arrayIndex.ToString();
159                          }
160                           break ;
161                      }
162                  }
163              }
164               return  Code;
165          }
166 
167 
168  ------------------------- 图片处理类
169 
170 
171  class  UnCodebase
172      {
173           public  Bitmap bmpobj;
174           public  UnCodebase(Bitmap pic)
175          {
176              bmpobj  =   new  Bitmap(pic);     // 转换为Format32bppRgb
177          }
178 
179           /**/
180           ///   <summary>
181           ///  根据RGB,计算灰度值
182           ///   </summary>
183           ///   <param name="posClr"> Color值 </param>
184           ///   <returns> 灰度值,整型 </returns>
185           private   int  GetGrayNumColor(System.Drawing.Color posClr)
186          {
187               return  (posClr.R  *   19595   +  posClr.G  *   38469   +  posClr.B  *   7472 >>   16 ;
188          }
189 
190           /**/
191           ///   <summary>
192           ///  灰度转换,逐点方式
193           ///   </summary>
194           public   void  GrayByPixels()
195          {
196               for  ( int  i  =   0 ; i  <  bmpobj.Height; i ++ )
197              {
198                   for  ( int  j  =   0 ; j  <  bmpobj.Width; j ++ )
199                  {
200                       int  tmpValue  =  GetGrayNumColor(bmpobj.GetPixel(j, i));
201                      bmpobj.SetPixel(j, i, Color.FromArgb(tmpValue, tmpValue, tmpValue));
202                  }
203              }
204          }
205 
206           /**/
207           ///   <summary>
208           ///  去图形边框
209           ///   </summary>
210           ///   <param name="borderWidth"></param>
211           public   void  ClearPicBorder( int  borderWidth)
212          {
213               for  ( int  i  =   0 ; i  <  bmpobj.Height; i ++ )
214              {
215                   for  ( int  j  =   0 ; j  <  bmpobj.Width; j ++ )
216                  {
217                       if  (i  <  borderWidth  ||  j  <  borderWidth  ||  j  >  bmpobj.Width  -   1   -  borderWidth  ||  i  >  bmpobj.Height  -   1   -  borderWidth)
218                          bmpobj.SetPixel(j, i, Color.FromArgb( 255 255 255 ));
219                  }
220              }
221          }
222 
223           /**/
224           ///   <summary>
225           ///  灰度转换,逐行方式
226           ///   </summary>
227           public   void  GrayByLine()
228          {
229              Rectangle rec  =   new  Rectangle( 0 0 , bmpobj.Width, bmpobj.Height);
230              BitmapData bmpData  =  bmpobj.LockBits(rec, ImageLockMode.ReadWrite, bmpobj.PixelFormat); //  PixelFormat.Format32bppPArgb);
231               //     bmpData.PixelFormat = PixelFormat.Format24bppRgb;
232              IntPtr scan0  =  bmpData.Scan0;
233               int  len  =  bmpobj.Width  *  bmpobj.Height;
234               int [] pixels  =   new   int [len];
235              Marshal.Copy(scan0, pixels,  0 , len);
236 
237               // 对图片进行处理
238               int  GrayValue  =   0 ;
239               for  ( int  i  =   0 ; i  <  len; i ++ )
240              {
241                  GrayValue  =  GetGrayNumColor(Color.FromArgb(pixels[i]));
242                  pixels[i]  =  ( byte )(Color.FromArgb(GrayValue, GrayValue, GrayValue)).ToArgb();       // Color转byte
243              }
244 
245              bmpobj.UnlockBits(bmpData);
246          }
247 
248           /**/
249           ///   <summary>
250           ///  得到有效图形并调整为可平均分割的大小
251           ///   </summary>
252           ///   <param name="dgGrayValue"> 灰度背景分界值 </param>
253           ///   <param name="CharsCount"> 有效字符数 </param>
254           ///   <returns></returns>
255           public   void  GetPicValidByValue( int  dgGrayValue,  int  CharsCount)
256          {
257               int  posx1  =  bmpobj.Width;  int  posy1  =  bmpobj.Height;
258               int  posx2  =   0 int  posy2  =   0 ;
259               for  ( int  i  =   0 ; i  <  bmpobj.Height; i ++ )       // 找有效区
260              {
261                   for  ( int  j  =   0 ; j  <  bmpobj.Width; j ++ )
262                  {
263                       int  pixelValue  =  bmpobj.GetPixel(j, i).R;
264                       if  (pixelValue  <  dgGrayValue)      // 根据灰度值
265                      {
266                           if  (posx1  >  j) posx1  =  j;
267                           if  (posy1  >  i) posy1  =  i;
268 
269                           if  (posx2  <  j) posx2  =  j;
270                           if  (posy2  <  i) posy2  =  i;
271                      };
272                  };
273              };
274               //  确保能整除
275               int  Span  =  CharsCount  -  (posx2  -  posx1  +   1 %  CharsCount;    // 可整除的差额数
276               if  (Span  <  CharsCount)
277              {
278                   int  leftSpan  =  Span  /   2 ;     // 分配到左边的空列 ,如span为单数,则右边比左边大1
279                   if  (posx1  >  leftSpan)
280                      posx1  =  posx1  -  leftSpan;
281                   if  (posx2  +  Span  -  leftSpan  <  bmpobj.Width)
282                      posx2  =  posx2  +  Span  -  leftSpan;
283              }
284               // 复制新图
285              Rectangle cloneRect  =   new  Rectangle(posx1, posy1, posx2  -  posx1  +   1 , posy2  -  posy1  +   1 );
286              bmpobj  =  bmpobj.Clone(cloneRect, bmpobj.PixelFormat);
287          }
288 
289           /**/
290           ///   <summary>
291           ///  得到有效图形,图形为类变量
292           ///   </summary>
293           ///   <param name="dgGrayValue"> 灰度背景分界值 </param>
294           ///   <param name="CharsCount"> 有效字符数 </param>
295           ///   <returns></returns>
296           public   void  GetPicValidByValue( int  dgGrayValue)
297          {
298               int  posx1  =  bmpobj.Width;  int  posy1  =  bmpobj.Height;
299               int  posx2  =   0 int  posy2  =   0 ;
300               for  ( int  i  =   0 ; i  <  bmpobj.Height; i ++ )       // 找有效区
301              {
302                   for  ( int  j  =   0 ; j  <  bmpobj.Width; j ++ )
303                  {
304                       int  pixelValue  =  bmpobj.GetPixel(j, i).R;
305                       if  (pixelValue  <  dgGrayValue)      // 根据灰度值
306                      {
307                           if  (posx1  >  j) posx1  =  j;
308                           if  (posy1  >  i) posy1  =  i;
309 
310                           if  (posx2  <  j) posx2  =  j;
311                           if  (posy2  <  i) posy2  =  i;
312                      };
313                  };
314              };
315               // 复制新图
316              Rectangle cloneRect  =   new  Rectangle(posx1, posy1, posx2  -  posx1  +   1 , posy2  -  posy1  +   1 );
317              bmpobj  =  bmpobj.Clone(cloneRect, bmpobj.PixelFormat);
318          }
319 
320           /**/
321           ///   <summary>
322           ///  得到有效图形,图形由外面传入
323           ///   </summary>
324           ///   <param name="dgGrayValue"> 灰度背景分界值 </param>
325           ///   <param name="CharsCount"> 有效字符数 </param>
326           ///   <returns></returns>
327           public  Bitmap GetPicValidByValue(Bitmap singlepic,  int  dgGrayValue)
328          {
329               int  posx1  =  singlepic.Width;  int  posy1  =  singlepic.Height;
330               int  posx2  =   0 int  posy2  =   0 ;
331               for  ( int  i  =   0 ; i  <  singlepic.Height; i ++ )       // 找有效区
332              {
333                   for  ( int  j  =   0 ; j  <  singlepic.Width; j ++ )
334                  {
335                       int  pixelValue  =  singlepic.GetPixel(j, i).R;
336                       if  (pixelValue  <  dgGrayValue)      // 根据灰度值
337                      {
338                           if  (posx1  >  j) posx1  =  j;
339                           if  (posy1  >  i) posy1  =  i;
340 
341                           if  (posx2  <  j) posx2  =  j;
342                           if  (posy2  <  i) posy2  =  i;
343                      };
344                  };
345              };
346               // 复制新图
347              Rectangle cloneRect  =   new  Rectangle(posx1, posy1, posx2  -  posx1  +   1 , posy2  -  posy1  +   1 );
348               return  singlepic.Clone(cloneRect, singlepic.PixelFormat);
349          }
350 
351           /**/
352           ///   <summary>
353           ///  平均分割图片
354           ///   </summary>
355           ///   <param name="RowNum"> 水平上分割数 </param>
356           ///   <param name="ColNum"> 垂直上分割数 </param>
357           ///   <returns> 分割好的图片数组 </returns>
358           public  Bitmap[] GetSplitPics( int  RowNum,  int  ColNum)
359          {
360               if  (RowNum  ==   0   ||  ColNum  ==   0 )
361                   return   null ;
362               int  singW  =  bmpobj.Width  /  RowNum;
363               int  singH  =  bmpobj.Height  /  ColNum;
364              Bitmap[] PicArray  =   new  Bitmap[RowNum  *  ColNum];
365 
366              Rectangle cloneRect;
367               for  ( int  i  =   0 ; i  <  ColNum; i ++ )       // 找有效区
368              {
369                   for  ( int  j  =   0 ; j  <  RowNum; j ++ )
370                  {
371                      cloneRect  =   new  Rectangle(j  *  singW, i  *  singH, singW, singH);
372                      PicArray[i  *  RowNum  +  j]  =  bmpobj.Clone(cloneRect, bmpobj.PixelFormat); // 复制小块图
373                  }
374              }
375               return  PicArray;
376          }
377 
378 
379           public  Bitmap[] readMap()
380          {
381               string  str;
382              RectangleF[] block  =   new  RectangleF[ 4 ];
383              block[ 0 =   new  Rectangle( 7 3 8 13 );
384              block[ 1 =   new  Rectangle( 20 3 8 13 );
385              block[ 2 =   new  Rectangle( 33 3 8 13 );
386              block[ 3 =   new  Rectangle( 47 3 8 13 );
387               // 分别克隆图片的四个部分    
388              Bitmap[] s  =   new  Bitmap[ 4 ];
389              s[ 0 =  bmpobj.Clone(block[ 0 ], PixelFormat.DontCare);
390              s[ 1 =  bmpobj.Clone(block[ 1 ], PixelFormat.DontCare);
391              s[ 2 =  bmpobj.Clone(block[ 2 ], PixelFormat.DontCare);
392              s[ 3 =  bmpobj.Clone(block[ 3 ], PixelFormat.DontCare);
393               return  s;
394          }
395 
396           /**/
397           ///   <summary>
398           ///  返回灰度图片的点阵描述字串,1表示灰点,0表示背景
399           ///   </summary>
400           ///   <param name="singlepic"> 灰度图 </param>
401           ///   <param name="dgGrayValue"> 背前景灰色界限 </param>
402           ///   <returns></returns>
403           public   string  GetSingleBmpCode(Bitmap singlepic,  int  dgGrayValue)
404          {
405              Color piexl;
406               string  code  =   "" ;
407               for  ( int  posy  =   0 ; posy  <  singlepic.Height; posy ++ )
408                   for  ( int  posx  =   0 ; posx  <  singlepic.Width; posx ++ )
409                  {
410                      piexl  =  singlepic.GetPixel(posx, posy);
411                       if  (piexl.R  <  dgGrayValue)     //  Color.Black )
412                          code  =  code  +   " 1 " ;
413                       else
414                          code  =  code  +   " 0 " ;
415                  }
416               return  code;
417          }
418 
419           ///   <summary>
420           ///  得到单个灰度图像前景背景的临界值 最大类间方差法,yuanbao,2007.08
421           ///   </summary>
422           ///   <returns> 前景背景的临界值 </returns>
423           public   int  GetSingleDgGrayValue(Bitmap singlepic)
424          {
425               int [] pixelNum  =   new   int [ 256 ];            // 图象直方图,共256个点
426               int  n, n1, n2;
427               int  total;                               // total为总和,累计值
428               double  m1, m2, sum, csum, fmax, sb;      // sb为类间方差,fmax存储最大方差值
429               int  k, t, q;
430               int  threshValue  =   1 ;                       //  阈值
431               int  step  =   1 ;
432               // 生成直方图
433               for  ( int  i  =   0 ; i  <  singlepic.Width; i ++ )
434              {
435                   for  ( int  j  =   0 ; j  <  singlepic.Height; j ++ )
436                  {
437                       // 返回各个点的颜色,以RGB表示
438                      pixelNum[singlepic.GetPixel(i, j).R] ++ ;             // 相应的直方图加1
439                  }
440              }
441               // 直方图平滑化
442               for  (k  =   0 ; k  <=   255 ; k ++ )
443              {
444                  total  =   0 ;
445                   for  (t  =   - 2 ; t  <=   2 ; t ++ )               // 与附近2个灰度做平滑化,t值应取较小的值
446                  {
447                      q  =  k  +  t;
448                       if  (q  <   0 )                      // 越界处理
449                          q  =   0 ;
450                       if  (q  >   255 )
451                          q  =   255 ;
452                      total  =  total  +  pixelNum[q];     // total为总和,累计值
453                  }
454                  pixelNum[k]  =  ( int )(( float )total  /   5.0   +   0.5 );     // 平滑化,左边2个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值
455              }
456               // 求阈值
457              sum  =  csum  =   0.0 ;
458              n  =   0 ;
459               // 计算总的图象的点数和质量矩,为后面的计算做准备
460               for  (k  =   0 ; k  <=   255 ; k ++ )
461              {
462                  sum  +=  ( double )k  *  ( double )pixelNum[k];      // x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和
463                  n  +=  pixelNum[k];                        // n为图象总的点数,归一化后就是累积概率
464              }
465 
466              fmax  =   - 1.0 ;                           // 类间方差sb不可能为负,所以fmax初始值为-1不影响计算的进行
467              n1  =   0 ;
468               for  (k  =   0 ; k  <   256 ; k ++ )                   // 对每个灰度(从0到255)计算一次分割后的类间方差sb
469              {
470                  n1  +=  pixelNum[k];                 // n1为在当前阈值遍前景图象的点数
471                   if  (n1  ==   0 ) {  continue ; }             // 没有分出前景后景
472                  n2  =  n  -  n1;                         // n2为背景图象的点数
473                   if  (n2  ==   0 ) {  break ; }                // n2为0表示全部都是后景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环
474                  csum  +=  ( double )k  *  pixelNum[k];     // 前景的“灰度的值*其点数”的总和
475                  m1  =  csum  /  n1;                      // m1为前景的平均灰度
476                  m2  =  (sum  -  csum)  /  n2;                // m2为背景的平均灰度
477                  sb  =  ( double )n1  *  ( double )n2  *  (m1  -  m2)  *  (m1  -  m2);    // sb为类间方差
478                   if  (sb  >  fmax)                   // 如果算出的类间方差大于前一次算出的类间方差
479                  {
480                      fmax  =  sb;                     // fmax始终为最大类间方差(otsu)
481                      threshValue  =  k;               // 取最大类间方差时对应的灰度的k就是最佳阈值
482                  }
483              }
484               return  threshValue;
485          }
486 
487           ///   <summary>
488           ///  得到灰度图像前景背景的临界值 最大类间方差法,yuanbao,2007.08
489           ///   </summary>
490           ///   <returns> 前景背景的临界值 </returns>
491           public   int  GetDgGrayValue()
492          {
493               int [] pixelNum  =   new   int [ 256 ];            // 图象直方图,共256个点
494               int  n, n1, n2;
495               int  total;                               // total为总和,累计值
496               double  m1, m2, sum, csum, fmax, sb;      // sb为类间方差,fmax存储最大方差值
497               int  k, t, q;
498               int  threshValue  =   1 ;                       //  阈值
499               int  step  =   1 ;
500               // 生成直方图
501               for  ( int  i  =   0 ; i  <  bmpobj.Width; i ++ )
502              {
503                   for  ( int  j  =   0 ; j  <  bmpobj.Height; j ++ )
504                  {
505                       // 返回各个点的颜色,以RGB表示
506                      pixelNum[bmpobj.GetPixel(i, j).R] ++ ;             // 相应的直方图加1
507                  }
508              }
509               // 直方图平滑化
510               for  (k  =   0 ; k  <=   255 ; k ++ )
511              {
512                  total  =   0 ;
513                   for  (t  =   - 2 ; t  <=   2 ; t ++ )               // 与附近2个灰度做平滑化,t值应取较小的值
514                  {
515                      q  =  k  +  t;
516                       if  (q  <   0 )                      // 越界处理
517                          q  =   0 ;
518                       if  (q  >   255 )
519                          q  =   255 ;
520                      total  =  total  +  pixelNum[q];     // total为总和,累计值
521                  }
522                  pixelNum[k]  =  ( int )(( float )total  /   5.0   +   0.5 );     // 平滑化,左边2个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值
523              }
524               // 求阈值
525              sum  =  csum  =   0.0 ;
526              n  =   0 ;
527               // 计算总的图象的点数和质量矩,为后面的计算做准备
528               for  (k  =   0 ; k  <=   255 ; k ++ )
529              {
530                  sum  +=  ( double )k  *  ( double )pixelNum[k];      // x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和
531                  n  +=  pixelNum[k];                        // n为图象总的点数,归一化后就是累积概率
532              }
533 
534              fmax  =   - 1.0 ;                           // 类间方差sb不可能为负,所以fmax初始值为-1不影响计算的进行
535              n1  =   0 ;
536               for  (k  =   0 ; k  <   256 ; k ++ )                   // 对每个灰度(从0到255)计算一次分割后的类间方差sb
537              {
538                  n1  +=  pixelNum[k];                 // n1为在当前阈值遍前景图象的点数
539                   if  (n1  ==   0 ) {  continue ; }             // 没有分出前景后景
540                  n2  =  n  -  n1;                         // n2为背景图象的点数
541                   if  (n2  ==   0 ) {  break ; }                // n2为0表示全部都是后景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环
542                  csum  +=  ( double )k  *  pixelNum[k];     // 前景的“灰度的值*其点数”的总和
543                  m1  =  csum  /  n1;                      // m1为前景的平均灰度
544                  m2  =  (sum  -  csum)  /  n2;                // m2为背景的平均灰度
545                  sb  =  ( double )n1  *  ( double )n2  *  (m1  -  m2)  *  (m1  -  m2);    // sb为类间方差
546                   if  (sb  >  fmax)                   // 如果算出的类间方差大于前一次算出的类间方差
547                  {
548                      fmax  =  sb;                     // fmax始终为最大类间方差(otsu)
549                      threshValue  =  k;               // 取最大类间方差时对应的灰度的k就是最佳阈值
550                  }
551              }
552               return  threshValue;
553          }
554 
555      }
556 
557 

 

 

转载于:https://www.cnblogs.com/haik/archive/2010/04/28/1723113.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值