大津法求图像动态阈值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//实验室的师哥传的
uint8 auto_threshold(uint8 * mt9v03x_image, int width,int height)//uint8 *image, uint16 col, uint16 row
{
int colorarray[256] = {0};
int32_t tol_sumgray=0;
int32_t tol_colsum=0;
int32_t icp_colsum=0;
int32_t max_colasg=0;
int32_t icp_sumgray=0;
uint8 threshold = 0;

float exp1=0;
float exp2=0;
float copli_exp=0;
float crt_vari=0;

for(i = 0; i<256; i++)
colorarray[i] = 0;

for(i = 0; i < height; i++)
{
for(j = 0; j < width; j++)
{
colorarray[(int) mt9v03x_image[i * width + j]]++;
}
}

for(k=0; k<=255; k++)
{
tol_sumgray+=k*colorarray[k];
tol_colsum+=colorarray[k];
}

for(k=0; k<=254; k++)
{
icp_colsum+=colorarray[k];
max_colasg=tol_colsum-icp_colsum;
icp_sumgray+=k*colorarray[k];
exp1=(float)icp_sumgray/icp_colsum;
exp2=(float)(tol_sumgray-icp_sumgray)/max_colasg;
copli_exp=icp_colsum*max_colasg*(exp1-exp2)*(exp1-exp2);

if(copli_exp>crt_vari)
{
crt_vari=copli_exp;
threshold=k;
}
}
return (threshold+8);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//我写的……
#define GrayScale 256
#define col MT9V03X_W //宽 120
#define row MT9V03X_H //高 80

uint8 OTSU(void)
{
uint16 i,j;
uint8 img_row=row,img_col=col;
uint16 histogram[GrayScale]; //灰度直方图

//第一步:初始化灰度直方图
for(i=0; i<GrayScale; i++)
histogram[i]=0;

//第二步:统计每个灰度值出现得次数
for(i=0; i<img_row; i++)
for(j=0; j<img_col; j++)
++histogram[mt9v03x_image[i][j]];


//第三步: 获取最小最大灰度值
uint16 minGray,maxGray;
for(minGray=0;minGray<256&&histogram[minGray]==0;minGray++);
for(maxGray=255;maxGray>minGray&&histogram[maxGray]==0;maxGray--);

//第四步:分情况讨论
// 最大=最小,图像只有一种颜色
if(maxGray==minGray)
return maxGray;
//最大=最小+1,图像只有两种颜色
if(maxGray==minGray+1)
return minGray;

//第五步:统计[最小,最大]范围内的像素总数
uint16 PixelSum=0;
for(i=minGray; i<maxGray+1; i++)
PixelSum += histogram[i];

//第六步:统计[最小,最大]范围内的灰度值总数(灰度值*出现次数)
uint16 GraySum=0;
for(i=minGray; i<maxGray+1; i++)
GraySum += histogram[i]*i;


//第七步: 大津法优化
float w0; //前景像素点占整幅图像的百分比
float w1; //背景像素点占整幅图像的百分比
uint16 w0num; //前景像素点数
uint16 w1num; // 背景像素点数
uint16 u0gray; //前景灰度值
uint16 u1gray; //背景灰度值
float u0; //w0平均灰度
float u1; //w1平均灰度
float deltaTmp=0,deltaMax=-1;
uint8 th;

u0gray = u1gray = w0num = w1num = 0;
for(i=minGray; i<maxGray+1; i++)
{
w0num += histogram[i];
w1num = PixelSum-w0num;
w0 = w0num*1.0/PixelSum;
w1 = w1num*1.0/PixelSum;
u0gray += histogram[i]*i;
u1gray = GraySum-u0gray;
u0 = u0gray*1.0/w0num;
u1 = u1gray*1.0/w1num;
deltaTmp = (float)(w0 * w1 * (u0 - u1)*(u0 - u1));
//类间方差公式 g = w0 * w1 * (u0 - u1) ^ 2

//第八步:遍历最大类间方差(因为呈正态分布)
if(deltaTmp>deltaMax)
{
deltaMax = deltaTmp;
th = i;
}
}
return th;
}