代碼是我從VC代碼中轉譯過來的,註釋都沿用了原作者的文字(別說是剽竊,^_^)。唯一改進的地方是,原代碼功能只能處理0和255的二值灰度(搞不懂爲什麼這樣,對於250、128這樣的都不行,還不如弄成二值灰度,別弄256灰度了),我將之改成了能根據0~255中任意灰度劃界的256灰度圖像!
以下是C#代碼:
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