灰度化图像常见的阈值分割算法

1.OTSU算法。

 关于最大类间方差法(otsu)的性能:

类间方差法对噪音和目标大小十分敏感,它仅对类间方差为单峰的图像产生较好的分割效果。
当目标与背景的大小比例悬殊时,类间方差准则函数可能呈现双峰或多峰,此时效果不好,但是类间方差法是用时最少的。
 1     public int Otsu(Bitmap map)
 2         {
 3             int nThreshold = 0;
 4 
 5             BitmapData mapData = map.LockBits(new Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadWrite, map.PixelFormat);
 6             double[] nHistogram = new double[256];         //灰度直方图  
 7             double[] dVariance = new double[256];          //类间方差  
 8             int N = map.Height * map.Width;           //总像素数  
 9             for (int i = 0; i < 256; i++)
10             {
11                 nHistogram[i] = 0.0;
12                 dVariance[i] = 0.0;
13             }
14             unsafe
15             {
16                 byte* ptr = (byte*)(mapData.Scan0);
17                 for (int i = 0; i < map.Height; i++)
18                 {
19                     ptr = (byte*)mapData.Scan0 + i * mapData.Stride;
20                     for (int j = 0; j < map.Width; j++)
21                     {
22                         nHistogram[(*ptr)]++;     //建立直方图  
23                         ptr = ptr + 3;
24                     }
25                 }
26             }
27             map.UnlockBits(mapData);
28             double Pa = 0.0;      //背景出现概率  
29             double Pb = 0.0;      //目标出现概率  
30             double Wa = 0.0;      //背景平均灰度值  
31             double Wb = 0.0;      //目标平均灰度值  
32             double W0 = 0.0;      //全局平均灰度值  
33             double dData1 = 0.0, dData2 = 0.0;
34             for (int i = 0; i < 256; i++)     //计算全局平均灰度  
35             {
36                 nHistogram[i] /= N;
37                 W0 += i * nHistogram[i];
38             }
39             for (int i = 0; i < 256; i++)     //对每个灰度值计算类间方差  
40             {
41                 Pa += nHistogram[i];
42                 Pb = 1 - Pa;
43                 dData1 += i * nHistogram[i];
44                 dData2 = W0 - dData1;
45                 Wa = dData1 / Pa;
46                 Wb = dData2 / Pb;
47                 dVariance[i] = (Pa * Pb * Math.Pow((Wb - Wa), 2));
48             }
49             //遍历每个方差,求取类间最大方差所对应的灰度值  
50             double temp = 0.0;
51             for (int i = 0; i < 256; i++)
52             {
53                 if (dVariance[i] > temp)
54                 {
55                     temp = dVariance[i];
56                     nThreshold = i;
57                 }
58             }
59             return nThreshold;
60         }
View Code

2.一维交叉熵值法

 1  public int LiLee(Bitmap map)
 2         {
 3             int nThreshold = 0;
 4 
 5             BitmapData mapData = map.LockBits(new Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadWrite, map.PixelFormat);
 6 
 7             double[] dHistogram = new double[256];         //灰度直方图  
 8             double[] dEntropy = new double[256];           //每个像素的交叉熵  
 9             int N = map.Height * map.Width;           //总像素数  
10             for (int i = 0; i < 256; i++)
11             {
12                 dHistogram[i] = 0.0;
13                 dEntropy[i] = 0.0;
14             }
15             unsafe
16             {
17                 byte* ptr = (byte*)(mapData.Scan0);
18                 for (int i = 0; i < map.Height; i++)
19                 {
20                     ptr = (byte*)mapData.Scan0 + i * mapData.Stride;
21                     for (int j = 0; j < map.Width; j++)
22                     {
23                         dHistogram[(*ptr)]++;     //建立直方图  
24                         ptr = ptr + 3;
25                     }
26                 }
27             }
28             map.UnlockBits(mapData);
29 
30             double Pa = 0.0;      //区域1平均灰度值  
31             double Pb = 0.0;      //区域2平均灰度值  
32             double P0 = 0.0;      //全局平均灰度值  
33             double Wa = 0.0;      //第一部分熵  
34             double Wb = 0.0;      //第二部分的熵  
35             double dData1 = 0.0, dData2 = 0.0;  //中间值  
36             double dData3 = 0.0, dData4 = 0.0;  //中间值  
37 
38             for (int i = 0; i < 256; i++)     //计算全局平均灰度  
39             {
40                 dHistogram[i] /= N;
41                 P0 += i * dHistogram[i];
42             }
43 
44             for (int i = 0; i < 256; i++)
45             {
46                 Wa = Wb = dData1 = dData2 = dData3 = dData4 = Pa = Pb = 0.0;
47                 for (int j = 0; j < 256; j++)
48                 {
49                     if (j <= i)
50                     {
51                         dData1 += dHistogram[j];
52                         dData2 += j * dHistogram[j];
53                     }
54                     else
55                     {
56                         dData3 += dHistogram[j];
57                         dData4 += j * dHistogram[j];
58                     }
59                 }
60                 Pa = dData2 / dData1;
61                 Pb = dData4 / dData3;
62                 for (int j = 0; j < 256; j++)
63                 {
64                     if (j <= i)
65                     {
66                         if ((Pa != 0) && (dHistogram[j] != 0))
67                         {
68                             double d1 = Math.Log(dHistogram[j] / Pa);
69                             Wa += j * dHistogram[j] * d1 / Math.Log(2);
70                         }
71                     }
72                     else
73                     {
74                         if ((Pb != 0) && (dHistogram[j] != 0))
75                         {
76                             double d2 = Math.Log(dHistogram[j] / Pb);
77                             Wb += j * dHistogram[j] * d2 / Math.Log(2);
78                         }
79                     }
80                 }
81                 dEntropy[i] = Wa + Wb;
82             }
83             //遍历熵值,求取最小交叉熵所对应的灰度值  
84             double temp = dEntropy[0];
85             for (int i = 1; i < 256; i++)
86             {
87                 if (dEntropy[i] < temp)
88                 {
89                     temp = dEntropy[i];
90                     nThreshold = i;
91                 }
92             }
93 
94             return nThreshold;
95         }
View Code

3.二维OTSU算法

  1  public int TwoOtsu(Bitmap map)
  2         {
  3             int nThreshold = 0;
  4             Bitmap mapClone = (Bitmap)map.Clone();
  5             BitmapData mapData = map.LockBits(new Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadWrite, map.PixelFormat);
  6 
  7             double[,] dHistogram = new double[256, 256];        //建立二维灰度直方图  
  8             double dTrMatrix = 0.0;             //离散矩阵的迹  
  9             int N = map.Height * map.Width;               //总像素数  
 10             for (int i = 0; i < 256; i++)
 11             {
 12                 for (int j = 0; j < 256; j++)
 13                     dHistogram[i, j] = 0.0;      //初始化变量  
 14             }
 15             unsafe
 16             {
 17                 byte* ptr = (byte*)mapData.Scan0;
 18                 for (int i = 0; i < map.Height; i++)
 19                 {
 20                     ptr = (byte*)mapData.Scan0 + i * mapData.Stride;
 21                     for (int j = 0; j < map.Width; j++)
 22                     {
 23                         int nData1 = *ptr;  //当前的灰度值  
 24                         int nData2 = 0;
 25                         int nData3 = 0;         //注意9个值相加可能超过一个字节 
 26                         for (int m = i - 1; m <= i + 1; m++)
 27                         {
 28                             for (int n = j - 1; n <= j + 1; n++)
 29                             {
 30                                 if ((m >= 0) && (m < map.Height) && (n >= 0) && (n < map.Width))
 31                                 {
 32                                     int a = mapClone.GetPixel(m, n).R;
 33                                     nData3 += a;//当前的灰度值 
 34                                 };
 35                             }
 36                         }
 37                         nData2 = nData3 / 9;        //对于越界的索引值进行补零,邻域均值  
 38                         dHistogram[nData1, nData2]++;
 39                         ptr = ptr + 3;
 40                     }
 41                 }
 42             }
 43             map.UnlockBits(mapData);
 44             for (int i = 0; i < 256; i++)
 45                 for (int j = 0; j < 256; j++)
 46                     dHistogram[i, j] /= N;  //得到归一化的概率分布  
 47 
 48             double Pai = 0.0;      //目标区均值矢量i分量  
 49             double Paj = 0.0;      //目标区均值矢量j分量  
 50             double Pbi = 0.0;      //背景区均值矢量i分量  
 51             double Pbj = 0.0;      //背景区均值矢量j分量  
 52             double Pti = 0.0;      //全局均值矢量i分量  
 53             double Ptj = 0.0;      //全局均值矢量j分量  
 54             double W0 = 0.0;       //目标区的联合概率密度  
 55             double W1 = 0.0;       //背景区的联合概率密度  
 56             double dData1 = 0.0;
 57             double dData2 = 0.0;
 58             double dData3 = 0.0;
 59             double dData4 = 0.0;   //中间变量  
 60             int nThreshold_s = 0;
 61             int nThreshold_t = 0;
 62             double temp = 0.0;     //寻求最大值  
 63             for (int i = 0; i < 256; i++)
 64             {
 65                 for (int j = 0; j < 256; j++)
 66                 {
 67                     Pti += i * dHistogram[i, j];
 68                     Ptj += j * dHistogram[i, j];
 69                 }
 70             }
 71             for (int i = 0; i < 256; i++)
 72             {
 73                 for (int j = 0; j < 256; j++)
 74                 {
 75                     W0 += dHistogram[i, j];
 76                     dData1 += i * dHistogram[i, j];
 77                     dData2 += j * dHistogram[i, j];
 78 
 79                     W1 = 1 - W0;
 80                     dData3 = Pti - dData1;
 81                     dData4 = Ptj - dData2;
 82                     /*          W1=dData3=dData4=0.0;   //对内循环的数据进行初始化 
 83                                 for(int s=i+1; s<256; s++) 
 84                                 { 
 85                                     for(int t=j+1; t<256; t++) 
 86                                     { 
 87                                         W1 += dHistogram[s][t]; 
 88                                         dData3 += s*dHistogram[s][t];  //方法2 
 89                                         dData4 += t*dHistogram[s][t];  //也可以增加循环进行计算 
 90                                     } 
 91                                 }*/
 92 
 93                     Pai = dData1 / W0;
 94                     Paj = dData2 / W0;
 95                     Pbi = dData3 / W1;
 96                     Pbj = dData4 / W1;   // 得到两个均值向量,用4个分量表示  
 97                     dTrMatrix = ((W0 * Pti - dData1) * (W0 * Pti - dData1) + (W0 * Ptj - dData1) * (W0 * Ptj - dData2)) / (W0 * W1);
 98                     if (dTrMatrix > temp)
 99                     {
100                         temp = dTrMatrix;
101                         nThreshold_s = i;
102                         nThreshold_t = j;
103                     }
104                 }
105             }
106             nThreshold = nThreshold_t;   //返回结果中的灰度值  
107 
108             return nThreshold;
109         }
View Code

资料:http://blog.csdn.net/likezhaobin/article/details/6915755

       http://baike.baidu.com/link?url=8Q8FeK6oRIcLVQM2Ef84k21ar8UOqz30c7CIIuiy4Q68LnehylUsBDLSbERB5ygRDVPaSUDsmOWOmCR2qjp-oa#7

原文地址:https://www.cnblogs.com/mandel/p/3597975.html