[转]灰度图像的腐蚀算法和细化算法(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[5, 5]; //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[1, 1] + neighbour[1, 2] + neighbour[1, 3]
154
+ neighbour[2, 1] + neighbour[2, 3] +
155
+neighbour[3, 1] + neighbour[3, 2] + neighbour[3, 3];
156
if (nCount >= 2 && nCount <= 6)
157
{
158
bCondition1 = true;
159
}
160
161
//判断Z0(P1)=1
162
nCount = 0;
163
if (neighbour[1, 2] == 0 && neighbour[1, 1] == 1)
164
nCount++;
165
if (neighbour[1, 1] == 0 && neighbour[2, 1] == 1)
166
nCount++;
167
if (neighbour[2, 1] == 0 && neighbour[3, 1] == 1)
168
nCount++;
169
if (neighbour[3, 1] == 0 && neighbour[3, 2] == 1)
170
nCount++;
171
if (neighbour[3, 2] == 0 && neighbour[3, 3] == 1)
172
nCount++;
173
if (neighbour[3, 3] == 0 && neighbour[2, 3] == 1)
174
nCount++;
175
if (neighbour[2, 3] == 0 && neighbour[1, 3] == 1)
176
nCount++;
177
if (neighbour[1, 3] == 0 && neighbour[1, 2] == 1)
178
nCount++;
179
if (nCount == 1)
180
bCondition2 = true;
181
182
//判断P2*P4*P8=0 or Z0(p2)!=1
183
if (neighbour[1, 2] * neighbour[2, 1] * neighbour[2, 3] == 0)
184
{
185
bCondition3 = true;
186
}
187
else
188
{
189
nCount = 0;
190
if (neighbour[0, 2] == 0 && neighbour[0, 1] == 1)
191
nCount++;
192
if (neighbour[0, 1] == 0 && neighbour[1, 1] == 1)
193
nCount++;
194
if (neighbour[1, 1] == 0 && neighbour[2, 1] == 1)
195
nCount++;
196
if (neighbour[2, 1] == 0 && neighbour[2, 2] == 1)
197
nCount++;
198
if (neighbour[2, 2] == 0 && neighbour[2, 3] == 1)
199
nCount++;
200
if (neighbour[2, 3] == 0 && neighbour[1, 3] == 1)
201
nCount++;
202
if (neighbour[1, 3] == 0 && neighbour[0, 3] == 1)
203
nCount++;
204
if (neighbour[0, 3] == 0 && neighbour[0, 2] == 1)
205
nCount++;
206
if (nCount != 1)
207
bCondition3 = true;
208
}
209
210
//判断P2*P4*P6=0 or Z0(p4)!=1
211
if (neighbour[1, 2] * neighbour[2, 1] * neighbour[3, 2] == 0)
212
{
213
bCondition4 = true;
214
}
215
else
216
{
217
nCount = 0;
218
if (neighbour[1, 1] == 0 && neighbour[1, 0] == 1)
219
nCount++;
220
if (neighbour[1, 0] == 0 && neighbour[2, 0] == 1)
221
nCount++;
222
if (neighbour[2, 0] == 0 && neighbour[3, 0] == 1)
223
nCount++;
224
if (neighbour[3, 0] == 0 && neighbour[3, 1] == 1)
225
nCount++;
226
if (neighbour[3, 1] == 0 && neighbour[3, 2] == 1)
227
nCount++;
228
if (neighbour[3, 2] == 0 && neighbour[2, 2] == 1)
229
nCount++;
230
if (neighbour[2, 2] == 0 && neighbour[1, 2] == 1)
231
nCount++;
232
if (neighbour[1, 2] == 0 && neighbour[1, 1] == 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
/// <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
else60
{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[5, 5]; //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)<=6153
nCount = neighbour[1, 1] + neighbour[1, 2] + neighbour[1, 3]154
+ neighbour[2, 1] + neighbour[2, 3] +155
+neighbour[3, 1] + neighbour[3, 2] + neighbour[3, 3];156
if (nCount >= 2 && nCount <= 6)157
{158
bCondition1 = true;159
}160

161
//判断Z0(P1)=1162
nCount = 0;163
if (neighbour[1, 2] == 0 && neighbour[1, 1] == 1)164
nCount++;165
if (neighbour[1, 1] == 0 && neighbour[2, 1] == 1)166
nCount++;167
if (neighbour[2, 1] == 0 && neighbour[3, 1] == 1)168
nCount++;169
if (neighbour[3, 1] == 0 && neighbour[3, 2] == 1)170
nCount++;171
if (neighbour[3, 2] == 0 && neighbour[3, 3] == 1)172
nCount++;173
if (neighbour[3, 3] == 0 && neighbour[2, 3] == 1)174
nCount++;175
if (neighbour[2, 3] == 0 && neighbour[1, 3] == 1)176
nCount++;177
if (neighbour[1, 3] == 0 && neighbour[1, 2] == 1)178
nCount++;179
if (nCount == 1)180
bCondition2 = true;181

182
//判断P2*P4*P8=0 or Z0(p2)!=1183
if (neighbour[1, 2] * neighbour[2, 1] * neighbour[2, 3] == 0)184
{185
bCondition3 = true;186
}187
else188
{189
nCount = 0;190
if (neighbour[0, 2] == 0 && neighbour[0, 1] == 1)191
nCount++;192
if (neighbour[0, 1] == 0 && neighbour[1, 1] == 1)193
nCount++;194
if (neighbour[1, 1] == 0 && neighbour[2, 1] == 1)195
nCount++;196
if (neighbour[2, 1] == 0 && neighbour[2, 2] == 1)197
nCount++;198
if (neighbour[2, 2] == 0 && neighbour[2, 3] == 1)199
nCount++;200
if (neighbour[2, 3] == 0 && neighbour[1, 3] == 1)201
nCount++;202
if (neighbour[1, 3] == 0 && neighbour[0, 3] == 1)203
nCount++;204
if (neighbour[0, 3] == 0 && neighbour[0, 2] == 1)205
nCount++;206
if (nCount != 1)207
bCondition3 = true;208
}209

210
//判断P2*P4*P6=0 or Z0(p4)!=1211
if (neighbour[1, 2] * neighbour[2, 1] * neighbour[3, 2] == 0)212
{213
bCondition4 = true;214
}215
else216
{217
nCount = 0;218
if (neighbour[1, 1] == 0 && neighbour[1, 0] == 1)219
nCount++;220
if (neighbour[1, 0] == 0 && neighbour[2, 0] == 1)221
nCount++;222
if (neighbour[2, 0] == 0 && neighbour[3, 0] == 1)223
nCount++;224
if (neighbour[3, 0] == 0 && neighbour[3, 1] == 1)225
nCount++;226
if (neighbour[3, 1] == 0 && neighbour[3, 2] == 1)227
nCount++;228
if (neighbour[3, 2] == 0 && neighbour[2, 2] == 1)229
nCount++;230
if (neighbour[2, 2] == 0 && neighbour[1, 2] == 1)231
nCount++;232
if (neighbour[1, 2] == 0 && neighbour[1, 1] == 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
else244
{245
bmpobj.SetPixel(i, j, Color.Black);246
}247
}248
}249
}250
// 复制细化后的图像251
// bmpobj = newBmp;252
}253

posted on 2008-10-20 17:02 freeliver54 阅读(1729) 评论(3) 收藏 举报


浙公网安备 33010602011771号