灰阶分割又称阈值操作, 是灰阶图像到二值图像的转换,区分对象和背景的操作,典型应用扫描文本图像的文本识别。是很多操作的基础,如细化、矢量化、形态学操作等。
阈值的选择是核心内容,灰阶直方图是根本工具。
1. 使用边缘像素。 边缘像素是指对象和背景之间的像素,由于采样问题,背景像素包含对象和背景像素,因此边缘像素的直方图会比较规整等反应对象和背景的分布。
思想:用拉普拉斯算子卷积图像,类似相当于提取边缘 。拉普拉斯算子计算后的图像像素加大的15%建立直方图,由此直方图选择阈值。
1 void thr_lap (IMAGE im)
2 {
3 float ** Lap;
4 int i, j, t, v;
5 unsigned char *p;
6
7 /* Compute the Laplacian of 'im' */
8 Lap = f2d (im->info->nr, im->info->nc);
9 Laplacian (im, Lap);
10
11 /* Find the high 85% of the Laplacian values */
12 fhist (Lap, hist, im->info->nr, im->info->nc);
13 hi_pct (hist, 2048, (long)im->info->nr*(long)im->info->nc, PCT, &v);
14
15 /* Construct histogram of the grey levels of hi Laplacian pixels */
16 peaks (im, hist, Lap, v, &t);
17
18 fprintf (stderr, "Threshold is %d ", t);
19
20 /* Threshold */
21 for (i=0; i<im->info->nr; i++)
22 for (j=0; j<im->info->nc; j++)
23 if (im->data[i][j] < t)
24 im->data[i][j] = 0;
25 else
26 im->data[i][j] = 255;
27 }
28
29 /* Return the level marking the high 85% of pixels */
30 void hi_pct (int *hist, int NH, long N, float pct, int *val)
31 {
32 int i,j=0, m;
33
34 *val = -1;
35 m = (pct/100.0) * N;
36 for (i=0; i<NH; i++)
37 {
38 j += hist[i];
39 if (j>=m)
40 {
41 *val = i;
42 break;
43 }
44 }
45 if (*val < 0) printf ("BAD HISTOGRAM in 'hi_pct'. ");
46 }
47
48 /* Construct a histogram of a float matrix */
49 void fhist (float **data, int *hist, int nr, int nc)
50 {
51 int i,j;
52
53 for (i=0; i<2048; i++) hist[i] = 0;
54 for (i=0; i<nr; i++)
55 for (j=0; j<nc; j++)
56 hist[(int)(data[i][j])] += 1;
57 }
58
59 void Laplacian (IMAGE input, float **output)
60 {
61 int i,j;
62
63 for (i=1; i<input->info->nr-1; i++)
64 for (j=1; j<input->info->nc-1; j++)
65 output[i][j] = pix_lap (input, i, j);
66 }
67
68 float pix_lap (IMAGE im, int r, int c)
69 {
70 int k=0, i,j;
71
72 /*
73 k = (int)im->data[r-1][c]+(int)im->data[r+1][c] +
74 (int)im->data[r][c-1]+(int)im->data[r][c-1];
75 k = k-(int)im->data[r][c]*4;
76 */
77 for (i= -1; i<=1; i++)
78 for (j= -1; j<=1; j++)
79 if (i!=0 || j!=0)
80 k += im->data[i+r][j+c];
81 k = k - 8*(int)im->data[r][c];
82 if (k<=0) return 0.0;
83 return (float)k/8.0;
84 }
85
86 void peaks (IMAGE im, int *hist, float **lap, int lval, int *t)
87 {
88 int N, i,j,k;
89
90 for (i=0; i<256; i++) hist[i] = 0;
91 *t = -1;
92
93 /* Find the histogram */
94 N = im->info->nc*im->info->nr;
95
96 for (i=0; i<im->info->nr; i++)
97 for (j=0; j<im->info->nc; j++)
98 if (lap[i][j] >= lval)
99 hist[im->data[i][j]] += 1;
100
101 /* Find the first peak */
102 j = 0;
103 for (i=0; i<256; i++)
104 if (hist[i] > hist[j]) j = i;
105
106 /* Find the second peak */
107 k = 0;
108 for (i=0; i<256; i++)
109 if (i>0 && hist[i-1]<=hist[i] && i<255 && hist[i+1]<=hist[i])
110 if ((k-j)*(k-j)*hist[k] < (i-j)*(i-j)*hist[i]) k = i;
111
112 *t = j;
113 if (j<k)
114 {
115 for (i=j; i<k; i++)
116 if (hist[i] < hist[*t]) *t = i;
117 } else {
118 for (i=k; i<j; i++)
119 if (hist[i] < hist[*t]) *t = i;
120 }
121 }
122 ……
123 int main (int argc, char** argv )
124 {
125 IMAGE x;
126 char name[128];
127 float max1=0.0f, max2=0.0f;
128
129 // Try to read an image
130 printf ("Enter path to the image file to be processed: ");
131 scanf ("%s", name);
132 printf ("Opening file '%s' ", name);
133 x = get_image(name);
134
135 if(x)
136 {
137 display_image (x);
138 thr_lap (x);
139 display_image (x);
140 save_image (x, "thrlap.jpg");
141 }
142 return 0;
143 }
2 {
3 float ** Lap;
4 int i, j, t, v;
5 unsigned char *p;
6
7 /* Compute the Laplacian of 'im' */
8 Lap = f2d (im->info->nr, im->info->nc);
9 Laplacian (im, Lap);
10
11 /* Find the high 85% of the Laplacian values */
12 fhist (Lap, hist, im->info->nr, im->info->nc);
13 hi_pct (hist, 2048, (long)im->info->nr*(long)im->info->nc, PCT, &v);
14
15 /* Construct histogram of the grey levels of hi Laplacian pixels */
16 peaks (im, hist, Lap, v, &t);
17
18 fprintf (stderr, "Threshold is %d ", t);
19
20 /* Threshold */
21 for (i=0; i<im->info->nr; i++)
22 for (j=0; j<im->info->nc; j++)
23 if (im->data[i][j] < t)
24 im->data[i][j] = 0;
25 else
26 im->data[i][j] = 255;
27 }
28
29 /* Return the level marking the high 85% of pixels */
30 void hi_pct (int *hist, int NH, long N, float pct, int *val)
31 {
32 int i,j=0, m;
33
34 *val = -1;
35 m = (pct/100.0) * N;
36 for (i=0; i<NH; i++)
37 {
38 j += hist[i];
39 if (j>=m)
40 {
41 *val = i;
42 break;
43 }
44 }
45 if (*val < 0) printf ("BAD HISTOGRAM in 'hi_pct'. ");
46 }
47
48 /* Construct a histogram of a float matrix */
49 void fhist (float **data, int *hist, int nr, int nc)
50 {
51 int i,j;
52
53 for (i=0; i<2048; i++) hist[i] = 0;
54 for (i=0; i<nr; i++)
55 for (j=0; j<nc; j++)
56 hist[(int)(data[i][j])] += 1;
57 }
58
59 void Laplacian (IMAGE input, float **output)
60 {
61 int i,j;
62
63 for (i=1; i<input->info->nr-1; i++)
64 for (j=1; j<input->info->nc-1; j++)
65 output[i][j] = pix_lap (input, i, j);
66 }
67
68 float pix_lap (IMAGE im, int r, int c)
69 {
70 int k=0, i,j;
71
72 /*
73 k = (int)im->data[r-1][c]+(int)im->data[r+1][c] +
74 (int)im->data[r][c-1]+(int)im->data[r][c-1];
75 k = k-(int)im->data[r][c]*4;
76 */
77 for (i= -1; i<=1; i++)
78 for (j= -1; j<=1; j++)
79 if (i!=0 || j!=0)
80 k += im->data[i+r][j+c];
81 k = k - 8*(int)im->data[r][c];
82 if (k<=0) return 0.0;
83 return (float)k/8.0;
84 }
85
86 void peaks (IMAGE im, int *hist, float **lap, int lval, int *t)
87 {
88 int N, i,j,k;
89
90 for (i=0; i<256; i++) hist[i] = 0;
91 *t = -1;
92
93 /* Find the histogram */
94 N = im->info->nc*im->info->nr;
95
96 for (i=0; i<im->info->nr; i++)
97 for (j=0; j<im->info->nc; j++)
98 if (lap[i][j] >= lval)
99 hist[im->data[i][j]] += 1;
100
101 /* Find the first peak */
102 j = 0;
103 for (i=0; i<256; i++)
104 if (hist[i] > hist[j]) j = i;
105
106 /* Find the second peak */
107 k = 0;
108 for (i=0; i<256; i++)
109 if (i>0 && hist[i-1]<=hist[i] && i<255 && hist[i+1]<=hist[i])
110 if ((k-j)*(k-j)*hist[k] < (i-j)*(i-j)*hist[i]) k = i;
111
112 *t = j;
113 if (j<k)
114 {
115 for (i=j; i<k; i++)
116 if (hist[i] < hist[*t]) *t = i;
117 } else {
118 for (i=k; i<j; i++)
119 if (hist[i] < hist[*t]) *t = i;
120 }
121 }
122 ……
123 int main (int argc, char** argv )
124 {
125 IMAGE x;
126 char name[128];
127 float max1=0.0f, max2=0.0f;
128
129 // Try to read an image
130 printf ("Enter path to the image file to be processed: ");
131 scanf ("%s", name);
132 printf ("Opening file '%s' ", name);
133 x = get_image(name);
134
135 if(x)
136 {
137 display_image (x);
138 thr_lap (x);
139 display_image (x);
140 save_image (x, "thrlap.jpg");
141 }
142 return 0;
143 }
2.迭代选择法。以灰阶均值为初值划分两类灰阶,再分别求每一类的均值t0,t1,由这两个均值再求平均得一个新的阈值,又重新划分两类灰阶,重复这个步骤,知道阈值没有变化为止。
3.最小化组间方差和总体方差的比之。
4. 熵entropy,系统的丰富度。熵越小,系统约有组织性;vice versa.最大化H=Hblack+Hwhite的t就是分割阈值。
……
5.移动平均法。 最后n个像素的平均值。
0, gi<sum/N*85%
V={
255, 其他
1 void thrdd (IMAGE im)
2 {
3 int NC, row, col, inc;
4 float mean, s, sum;
5 unsigned char *p;
6 long N, i;
7
8 N = (long)im->info->nc * (long)im->info->nr;
9 NC = im->info->nc;
10 s = (int)(float)(NC/Navg);
11 sum = 127*s;
12
13 row = col = 0;
14 p = &(im->data[0][0]);
15 inc = 1;
16
17 for (i=0; i<N-1; i++)
18 {
19 if (col >= NC)
20 {
21 col = NC-1; row++;
22 p = &(im->data[row][col]);
23 inc = -1;
24 } else if (col < 0)
25 {
26 col = 0;
27 row++;
28 p = &(im->data[row][col]);
29 inc = 1;
30 }
31
32 /* Estimate the mean of the last NC/8 pixels. */
33 sum = sum - sum/s + *p;
34 mean = sum/s;
35 if (*p < mean*(100-pct)/100.0) *p = 0;
36 else *p = 255;
37 p += inc;
38 col += inc;
39 }
2 {
3 int NC, row, col, inc;
4 float mean, s, sum;
5 unsigned char *p;
6 long N, i;
7
8 N = (long)im->info->nc * (long)im->info->nr;
9 NC = im->info->nc;
10 s = (int)(float)(NC/Navg);
11 sum = 127*s;
12
13 row = col = 0;
14 p = &(im->data[0][0]);
15 inc = 1;
16
17 for (i=0; i<N-1; i++)
18 {
19 if (col >= NC)
20 {
21 col = NC-1; row++;
22 p = &(im->data[row][col]);
23 inc = -1;
24 } else if (col < 0)
25 {
26 col = 0;
27 row++;
28 p = &(im->data[row][col]);
29 inc = 1;
30 }
31
32 /* Estimate the mean of the last NC/8 pixels. */
33 sum = sum - sum/s + *p;
34 mean = sum/s;
35 if (*p < mean*(100-pct)/100.0) *p = 0;
36 else *p = 255;
37 p += inc;
38 col += inc;
39 }
40 }
6.聚类
7.松弛法