颜色聚类
1 public static class KmeansColor
2 {
3 /*
4 * 聚类函数主体。
5 * 针对一维 double 数组。指定聚类数目 k。
6 * 将数据聚成 k 类。
7 */
8 public static Color[][] cluster(Color[] p, int k)
9 {
10 int intRunCount = 0;
11 start:
12 intRunCount++;
13 // 存放聚类旧的聚类中心
14 Color[] c = new Color[k];
15 // 存放新计算的聚类中心
16 Color[] nc = new Color[k];
17 // 存放放回结果
18 Color[][] g;
19 // 初始化聚类中心
20 // 经典方法是随机选取 k 个
21 // 本例中采用前 k 个作为聚类中心
22 // 聚类中心的选取不影响最终结果
23 Random r = new Random();
24
25 int intValue = -16777216 / k;
26 for (int i = 0; i < k; i++)
27 {
28 c[i] = Color.FromArgb(r.Next(1, 255), r.Next(1, 255), r.Next(1, 255));
29 }
30 // 循环聚类,更新聚类中心
31 // 到聚类中心不变为止
32 while (true)
33 {
34 // 根据聚类中心将元素分类
35 g = group(p, c);
36 // 计算分类后的聚类中心
37 for (int i = 0; i < g.Length; i++)
38 {
39 nc[i] = center(g[i]);
40 }
41 // 如果聚类中心不同
42 if (!equal(nc, c))
43 {
44 // 为下一次聚类准备
45 c = nc;
46 nc = new Color[k];
47 }
48 else // 聚类结束
49 {
50 foreach (var item in g)
51 {
52 if (intRunCount < 10000 && item.Length <= 50)
53 {
54 goto start;
55 }
56 }
57 break;
58 }
59 }
60 // 返回聚类结果
61 return g;
62 }
63 /*
64 * 聚类中心函数
65 * 简单的一维聚类返回其算数平均值
66 * 可扩展
67 */
68 public static Color center(Color[] p)
69 {
70 if (p.Length <= 0)
71 {
72 Random r = new Random();
73 return Color.FromArgb(r.Next(1, 255), r.Next(1, 255), r.Next(1, 255));
74 }
75 int intSumR = 0, intSumG = 0, intSumB = 0;
76 foreach (var item in p)
77 {
78 intSumR += item.R;
79 intSumG += item.G;
80 intSumB += item.B;
81 }
82 int intLength = p.Length;
83 return Color.FromArgb(intSumR / intLength, intSumG / intLength, intSumB / intLength);
84 }
85 /*
86 * 给定 double 型数组 p 和聚类中心 c。
87 * 根据 c 将 p 中元素聚类。返回二维数组。
88 * 存放各组元素。
89 */
90 public static Color[][] group(Color[] p, Color[] c)
91 {
92 // 中间变量,用来分组标记
93 int[] gi = new int[p.Length];
94 // 考察每一个元素 pi 同聚类中心 cj 的距离
95 // pi 与 cj 的距离最小则归为 j 类
96 for (int i = 0; i < p.Length; i++)
97 {
98 // 存放距离
99 double[] d = new double[c.Length];
100 // 计算到每个聚类中心的距离
101 for (int j = 0; j < c.Length; j++)
102 {
103 d[j] = distance(p[i], c[j]);
104 }
105 // 找出最小距离
106 int ci = min(d);
107 // 标记属于哪一组
108 gi[i] = ci;
109 }
110 // 存放分组结果
111 Color[][] g = new Color[c.Length][];
112 // 遍历每个聚类中心,分组
113 for (int i = 0; i < c.Length; i++)
114 {
115 // 中间变量,记录聚类后每一组的大小
116 int s = 0;
117 // 计算每一组的长度
118 for (int j = 0; j < gi.Length; j++)
119 if (gi[j] == i)
120 s++;
121 // 存储每一组的成员
122 g[i] = new Color[s];
123 s = 0;
124 // 根据分组标记将各元素归位
125 for (int j = 0; j < gi.Length; j++)
126 if (gi[j] == i)
127 {
128 g[i][s] = p[j];
129 s++;
130 }
131 }
132 // 返回分组结果
133 return g;
134 }
135
136 /*
137 * 计算两个点之间的距离, 这里采用最简单得一维欧氏距离, 可扩展。
138 */
139 public static double distance(Color x, Color y)
140 {
141
142 return Math.Sqrt(Math.Pow(x.R - y.R, 2) + Math.Pow(x.G - y.G, 2) + Math.Pow(x.B - y.B, 2));
143 // return Math.Abs(x.R - y.R) + Math.Abs(x.G - y.G) + Math.Abs(x.B - y.B);
144 }
145
146 /*
147 * 返回给定 double 数组各元素之和。
148 */
149 public static double sum(double[] p)
150 {
151 double sum = 0.0;
152 for (int i = 0; i < p.Length; i++)
153 sum += p[i];
154 return sum;
155 }
156
157 /*
158 * 给定 double 类型数组,返回最小值得下标。
159 */
160 public static int min(double[] p)
161 {
162 int i = 0;
163 double m = p[0];
164 for (int j = 1; j < p.Length; j++)
165 {
166 if (p[j] < m)
167 {
168 i = j;
169 m = p[j];
170 }
171 }
172 return i;
173 }
174
175 /*
176 * 判断两个 double 数组是否相等。 长度一样且对应位置值相同返回真。
177 */
178 public static bool equal(Color[] a, Color[] b)
179 {
180 if (a.Length != b.Length)
181 return false;
182 else
183 {
184 for (int i = 0; i < a.Length; i++)
185 {
186 if (a[i].Name != b[i].Name)
187 return false;
188 }
189 }
190 return true;
191 }
192 }
常用函数
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Drawing;
6 using AForge.Imaging.Filters;
7 using AForge.Imaging;
8 using AForge.Math.Geometry;
9 using System.Drawing.Imaging;
10 using AForge;
11 using System.IO;
12 using System.Text.RegularExpressions;
13 using AForge.Math;
14
15 namespace RecogniseCode
16 {
17 /*
18 * 配置文件描述:
19 * 0:去边框 1:颜色去除;2:灰度;3:二值化;4:去噪;5:标记;6:投影检测
20 * -----------------------
21 * 01:边框宽度 上,右,下,左
22 * -----------------------
23 * 11:目标颜色,|分割,12:阈值,13:替换颜色
24 * -----------------------
25 * 21:灰度参数
26 * -----------------------
27 * 31:二值化参数
28 * -----------------------
29 * 41:去噪参数
30 * -----------------------
31 * 51:标记最小大小
32 * 52:是否检查宽度合并
33 * 53:检查宽度合并最大宽度
34 * 54:是否左右旋转以找到最小宽度图片
35 * -----------------------
36 * 61:是否谷底检查
37 * 62:谷底检查最大高度
38 * 63:是否超宽检查
39 * 64:超宽检查最大宽度
40 */
41 public class Code2Text
42 {
43 private CodeType m_codeType;
44 private string m_strModePath;
45 private XMLSourceHelp m_xml;
46 /// <summary>
47 /// 功能描述:构造函数
48 /// 作 者:huangzh
49 /// 创建日期:2016-09-01 15:21:27
50 /// 任务编号:
51 /// </summary>
52 /// <param name="codeType">验证码类型</param>
53 /// <param name="strModePath">验证码识别模板文件夹路径</param>
54 public Code2Text(CodeType codeType, string strModePath)
55 {
56 m_codeType = codeType;
57 m_strModePath = strModePath;
58 if (!Directory.Exists(strModePath))
59 {
60 throw new Exception("验证码识别模板文件夹路径不存在");
61 }
62 string strConfigPath = Path.Combine(m_strModePath, "config.xml");
63 if (!File.Exists(strConfigPath))
64 throw new Exception("识别模板配置文件不存在");
65 m_xml = new XMLSourceHelp(strConfigPath);
66 }
67
68 /// <summary>
69 /// 功能描述:识别验证码结果
70 /// 作 者:huangzh
71 /// 创建日期:2016-09-01 16:25:45
72 /// 任务编号:
73 /// </summary>
74 /// <param name="bit">bit</param>
75 /// <returns>返回值</returns>
76 public string GetCodeText(Bitmap bit)
77 {
78 switch (m_codeType)
79 {
80 case CodeType.Tianjin:
81 return GetTianJin(bit);
82 case CodeType.LiaoNing:
83 return GetLiaoNing(bit);
84 case CodeType.JiangSu:
85 return GetJiangSu(bit);
86 case CodeType.JiangXi:
87 return GetJiangXi(bit);
88 case CodeType.ChongQing:
89 return GetChongQing(bit);
90 case CodeType.NingXia:
91 return GetNingXia(bit);
92 case CodeType.XinJiang:
93 return GetXinJiang(bit);
94 case CodeType.TianYanCha:
95 return GetTianYanCha(bit);
96 case CodeType.BeiJing:
97 return GetBeiJing(bit);
98 case CodeType.QingHai:
99 return GetQingHai(bit);
100 case CodeType.ShanXi:
101 return GetShanXi(bit);
102 case CodeType.HeiLongJiang:
103 return GetHeiLongJiang(bit);
104 default: return "";
105 }
106 }
107
108 #region 具体验证码识别
109 /// <summary>
110 /// 功能描述:获取天津验证码结果
111 /// 作 者:huangzh
112 /// 创建日期:2016-09-01 16:26:00
113 /// 任务编号:
114 /// </summary>
115 /// <param name="bitImage">bitImage</param>
116 /// <returns>识别结果,如果为空,则为识别失败</returns>
117 private string GetTianJin(Bitmap bitImage)
118 {
119 //颜色去除
120 bitImage = ClearColor(bitImage);
121
122 //灰度
123 bitImage = HuiDu(bitImage);
124
125 //二值化
126 bitImage = ErZhi(bitImage);
127
128 //反转
129 bitImage = ColorFanZhuan(bitImage);
130
131 //去噪
132 bitImage = QuZao(bitImage);
133
134 //标记识别
135 List<string> lstChar = GetImageChar(GetLianTongImage(bitImage));
136 string strNum1 = string.Empty;
137 string strYun = string.Empty;
138 string strNum2 = string.Empty;
139 foreach (string strItem in lstChar)
140 {
141 if (Regex.IsMatch(strItem, @"\d+"))
142 {
143 if (string.IsNullOrEmpty(strYun))
144 {
145 strNum1 += strItem;
146 }
147 else
148 {
149 strNum2 += strItem;
150 }
151 }
152 else if (Regex.IsMatch(strItem, @"\+|\-|\#"))
153 {
154 if (string.IsNullOrEmpty(strYun))
155 {
156 strYun = strItem;
157 }
158 }
159 else if (Regex.IsMatch(strItem, @"\="))
160 {
161
162 }
163 }
164
165 if (!string.IsNullOrEmpty(strNum1) && !string.IsNullOrEmpty(strYun) && !string.IsNullOrEmpty(strNum2))
166 {
167 int intNum1 = int.Parse(strNum1);
168 int intNum2 = int.Parse(strNum2);
169 switch (strYun)
170 {
171 case "+": return (intNum1 + intNum2).ToString();
172 case "-": return (intNum1 - intNum2).ToString();
173 case "#": return (intNum1 * intNum2).ToString();
174 default: return string.Empty;
175 }
176 }
177 return string.Empty;
178 }
179
180 /// <summary>
181 /// 功能描述:获取辽宁验证码结果
182 /// 作 者:huangzh
183 /// 创建日期:2016-09-02 09:30:56
184 /// 任务编号:
185 /// </summary>
186 /// <param name="bitImage">bitImage</param>
187 /// <returns>返回值</returns>
188 private string GetLiaoNing(Bitmap bitImage)
189 {
190 //灰度
191 bitImage = HuiDu(bitImage);
192
193 //二值化
194 bitImage = ErZhi(bitImage);
195
196 //去噪
197 bitImage = QuZao(bitImage);
198
199 //标记识别
200 List<string> lstChar = GetImageChar(GetLianTongImage(bitImage));
201
202 return string.Join("", lstChar);
203 }
204
205 /// <summary>
206 /// 功能描述:获取江苏验证码结果
207 /// 作 者:huangzh
208 /// 创建日期:2016-09-02 09:35:09
209 /// 任务编号:
210 /// </summary>
211 /// <param name="bitImage">bitImage</param>
212 /// <returns>返回值</returns>
213 private string GetJiangSu(Bitmap bitImage)
214 {
215 //灰度
216 bitImage = HuiDu(bitImage);
217
218 //二值化
219 bitImage = ErZhi(bitImage);
220
221 //反转
222 bitImage = ColorFanZhuan(bitImage);
223
224 //去噪
225 bitImage = QuZao(bitImage);
226
227 //毛边
228 bitImage = ClearMaoBian(bitImage);
229
230 //反转
231 bitImage = ColorFanZhuan(bitImage);
232
233 //毛边
234 bitImage = ClearMaoBian(bitImage);
235
236 //反转
237 bitImage = ColorFanZhuan(bitImage);
238
239 //标记识别
240 List<string> lstChar = GetImageChar(GetLianTongImage(bitImage));
241
242 return string.Join("", lstChar);
243 }
244
245 /// <summary>
246 /// 功能描述:获取江西验证码结果
247 /// 作 者:huangzh
248 /// 创建日期:2016-09-02 10:18:13
249 /// 任务编号:
250 /// </summary>
251 /// <param name="bitImage">bitImage</param>
252 /// <returns>返回值</returns>
253 private string GetJiangXi(Bitmap bitImage)
254 {
255 //灰度
256 bitImage = HuiDu(bitImage);
257
258 //二值化
259 bitImage = ErZhi(bitImage);
260
261 //反转
262 bitImage = ColorFanZhuan(bitImage);
263
264 //去噪
265 bitImage = QuZao(bitImage);
266
267 //标记识别
268 List<string> lstChar = GetImageChar(GetLianTongImage(bitImage));
269 string strNum1 = string.Empty;
270 string strYun = string.Empty;
271 string strNum2 = string.Empty;
272 foreach (string strItem in lstChar)
273 {
274 if (Regex.IsMatch(strItem, @"\d+"))
275 {
276 if (string.IsNullOrEmpty(strYun))
277 {
278 strNum1 += strItem;
279 }
280 else
281 {
282 strNum2 += strItem;
283 }
284 }
285 else if (Regex.IsMatch(strItem, @"\+|\-|\#"))
286 {
287 if (string.IsNullOrEmpty(strYun))
288 {
289 strYun = strItem;
290 }
291 }
292 else if (Regex.IsMatch(strItem, @"\="))
293 {
294
295 }
296 }
297
298 if (!string.IsNullOrEmpty(strNum1) && !string.IsNullOrEmpty(strYun) && !string.IsNullOrEmpty(strNum2))
299 {
300 int intNum1 = int.Parse(strNum1);
301 int intNum2 = int.Parse(strNum2);
302 switch (strYun)
303 {
304 case "+": return (intNum1 + intNum2).ToString();
305 case "-": return (intNum1 - intNum2).ToString();
306 case "#": return (intNum1 * intNum2).ToString();
307 default: return string.Empty;
308 }
309 }
310 return string.Empty;
311 }
312
313 /// <summary>
314 /// 功能描述:获取重庆验证码结果
315 /// 作 者:huangzh
316 /// 创建日期:2016-09-02 10:30:53
317 /// 任务编号:
318 /// </summary>
319 /// <param name="bitImage">bitImage</param>
320 /// <returns>返回值</returns>
321 private string GetChongQing(Bitmap bitImage)
322 {
323 //灰度
324 bitImage = HuiDu(bitImage);
325
326 //二值化
327 bitImage = ErZhi(bitImage);
328
329 //反转
330 bitImage = ColorFanZhuan(bitImage);
331
332 //去噪
333 bitImage = QuZao(bitImage);
334
335 //毛边
336 bitImage = ClearMaoBian(bitImage);
337
338 //标记识别
339 List<string> lstChar = GetImageChar(GetLianTongImage(bitImage));
340 string strNum1 = string.Empty;
341 string strYun = string.Empty;
342 string strNum2 = string.Empty;
343 foreach (string strItem in lstChar)
344 {
345 if (Regex.IsMatch(strItem, @"\d+"))
346 {
347 if (string.IsNullOrEmpty(strYun))
348 {
349 strNum1 += strItem;
350 }
351 else
352 {
353 strNum2 += strItem;
354 }
355 }
356 else if (Regex.IsMatch(strItem, @"\+|\-|\#"))
357 {
358 if (string.IsNullOrEmpty(strYun))
359 {
360 strYun = strItem;
361 }
362 }
363 else if (Regex.IsMatch(strItem, @"\="))
364 {
365
366 }
367 }
368
369 if (!string.IsNullOrEmpty(strNum1) && !string.IsNullOrEmpty(strYun) && !string.IsNullOrEmpty(strNum2))
370 {
371 int intNum1 = int.Parse(strNum1);
372 int intNum2 = int.Parse(strNum2);
373 switch (strYun)
374 {
375 case "+": return (intNum1 + intNum2).ToString();
376 case "-": return (intNum1 - intNum2).ToString();
377 case "#": return (intNum1 * intNum2).ToString();
378 default: return string.Empty;
379 }
380 }
381 return string.Empty;
382 }
383
384 /// <summary>
385 /// 功能描述:获取宁夏验证码结果
386 /// 作 者:huangzh
387 /// 创建日期:2016-09-02 10:41:18
388 /// 任务编号:
389 /// </summary>
390 /// <param name="bitImage">bitImage</param>
391 /// <returns>返回值</returns>
392 private string GetNingXia(Bitmap bitImage)
393 {
394 //灰度
395 bitImage = HuiDu(bitImage);
396
397 //二值化
398 bitImage = ErZhi(bitImage);
399
400 //反转
401 bitImage = ColorFanZhuan(bitImage);
402
403 //去噪
404 bitImage = QuZao(bitImage);
405
406 //标记识别
407 List<string> lstChar = GetImageChar(GetLianTongImage(bitImage));
408 string strNum1 = string.Empty;
409 string strYun = string.Empty;
410 string strNum2 = string.Empty;
411 foreach (string strItem in lstChar)
412 {
413 if (Regex.IsMatch(strItem, @"\d+"))
414 {
415 if (string.IsNullOrEmpty(strYun))
416 {
417 strNum1 += strItem;
418 }
419 else
420 {
421 strNum2 += strItem;
422 }
423 }
424 else if (Regex.IsMatch(strItem, @"\+|\-|\#"))
425 {
426 if (string.IsNullOrEmpty(strYun))
427 {
428 strYun = strItem;
429 }
430 }
431 else if (Regex.IsMatch(strItem, @"\="))
432 {
433
434 }
435 }
436
437 if (!string.IsNullOrEmpty(strNum1) && !string.IsNullOrEmpty(strYun) && !string.IsNullOrEmpty(strNum2))
438 {
439 int intNum1 = int.Parse(strNum1);
440 int intNum2 = int.Parse(strNum2);
441 switch (strYun)
442 {
443 case "+": return (intNum1 + intNum2).ToString();
444 case "-": return (intNum1 - intNum2).ToString();
445 case "#": return (intNum1 * intNum2).ToString();
446 default: return string.Empty;
447 }
448 }
449 return string.Empty;
450 }
451
452 /// <summary>
453 /// 功能描述:获取新疆验证码结果
454 /// 作 者:huangzh
455 /// 创建日期:2016-09-02 10:46:09
456 /// 任务编号:
457 /// </summary>
458 /// <param name="bitImage">bitImage</param>
459 /// <returns>返回值</returns>
460 private string GetXinJiang(Bitmap bitImage)
461 {
462 //灰度
463 bitImage = HuiDu(bitImage);
464
465 //二值化
466 bitImage = ErZhi(bitImage);
467
468 //反转
469 bitImage = ColorFanZhuan(bitImage);
470
471 //去噪
472 bitImage = QuZao(bitImage);
473
474 List<Bitmap> lstBits = GetLianTongImage(bitImage);
475
476
477 //int intWidth = int.Parse(m_xml.ConvertIdToName("maxWidth", "-1"));
478 //for (int i = 0; i < lstBits.Count; i++)
479 //{
480 // Bitmap bit = lstBits[i];
481 // int intMinWidth = GetMinBitmap(bit).Width;
482 // if (intMinWidth >= intWidth + 2)
483 // {
484 // Bitmap bit1 = bit.Clone(new Rectangle(0, 0, intWidth, bit.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
485 // Bitmap bit2 = bit.Clone(new Rectangle(intWidth, 0, bit.Width - intWidth, bit.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
486 // lstBits.RemoveAt(i);
487 // lstBits.Insert(i, bit2);
488 // lstBits.Insert(i, bit1);
489 // break;
490 // }
491 //}
492
493 //标记识别
494 List<string> lstChar = GetImageChar(lstBits);
495 string strNum1 = string.Empty;
496 string strYun = string.Empty;
497 string strNum2 = string.Empty;
498 foreach (string strItem in lstChar)
499 {
500 if (Regex.IsMatch(strItem, @"\d+"))
501 {
502 if (string.IsNullOrEmpty(strYun))
503 {
504 strNum1 += strItem;
505 }
506 else
507 {
508 strNum2 += strItem;
509 }
510 }
511 else if (Regex.IsMatch(strItem, @"\+|\-|\#"))
512 {
513 if (string.IsNullOrEmpty(strYun))
514 {
515 strYun = strItem;
516 }
517 }
518 else if (Regex.IsMatch(strItem, @"\="))
519 {
520 break;
521 }
522 }
523
524 if (!string.IsNullOrEmpty(strNum1) && !string.IsNullOrEmpty(strYun) && !string.IsNullOrEmpty(strNum2))
525 {
526 int intNum1 = int.Parse(strNum1);
527 int intNum2 = int.Parse(strNum2);
528 switch (strYun)
529 {
530 case "+": return (intNum1 + intNum2).ToString();
531 case "-": return (intNum1 - intNum2).ToString();
532 case "#": return (intNum1 * intNum2).ToString();
533 default: return string.Empty;
534 }
535 }
536 return string.Empty;
537 }
538
539
540
541 /// <summary>
542 /// 功能描述:获取天眼查验证码结果
543 /// 作 者:huangzh
544 /// 创建日期:2016-09-06 12:28:32
545 /// 任务编号:
546 /// </summary>
547 /// <param name="bitImage">bitImage</param>
548 /// <returns>返回值</returns>
549 private string GetTianYanCha(Bitmap bitImage)
550 {
551 bitImage = ClearBroder(bitImage);
552 bitImage = HuiDu(bitImage);
553 bitImage = ErZhi(bitImage);
554 bitImage = ColorFanZhuan(bitImage);
555 bitImage = QuZao(bitImage);
556 List<Bitmap> lstImages = GetLianTongImage(bitImage);
557 List<string> lstChar = GetImageChar(lstImages);
558 return string.Join("", lstChar);
559 }
560
561 /// <summary>
562 /// 功能描述:获取北京验证码结果
563 /// 作 者:huangzh
564 /// 创建日期:2016-09-07 16:14:42
565 /// 任务编号:
566 /// </summary>
567 /// <param name="bitImage">bitImage</param>
568 /// <returns>返回值</returns>
569 private string GetBeiJing(Bitmap bitImage)
570 {
571 bitImage = ClearColor(bitImage);
572
573 //灰度
574 bitImage = HuiDu(bitImage);
575
576 //二值化
577 bitImage = ErZhi(bitImage);
578
579 //反转
580 bitImage = ColorFanZhuan(bitImage);
581
582 //去噪
583 bitImage = QuZao(bitImage);
584
585 //标记识别
586 List<string> lstChar = GetImageChar(GetLianTongImage(bitImage));
587 string strNum1 = string.Empty;
588 string strYun = string.Empty;
589 string strNum2 = string.Empty;
590 foreach (string strItem in lstChar)
591 {
592 if (strItem == "$")
593 continue;
594 if (Regex.IsMatch(strItem, @"\d+"))
595 {
596 if (string.IsNullOrEmpty(strYun))
597 {
598 if (string.IsNullOrEmpty(strNum1))
599 strNum1 = strItem;
600 else if (strItem != "1")
601 strNum1 = strItem;
602 }
603 else
604 {
605 if (string.IsNullOrEmpty(strNum2))
606 {
607 strNum2 = strItem;
608 if (strItem != "1")
609 break;
610 }
611 else if (strItem != "1")
612 strNum2 = strItem;
613 }
614 }
615 else if (Regex.IsMatch(strItem, @"\+|\-|\#"))
616 {
617 if (string.IsNullOrEmpty(strYun))
618 {
619 strYun = strItem;
620 }
621 }
622 else if (Regex.IsMatch(strItem, @"\="))
623 {
624 break;
625 }
626 }
627
628 if (!string.IsNullOrEmpty(strNum1) && !string.IsNullOrEmpty(strYun) && !string.IsNullOrEmpty(strNum2))
629 {
630 int intNum1 = int.Parse(strNum1);
631 int intNum2 = int.Parse(strNum2);
632 switch (strYun)
633 {
634 case "+": return (intNum1 + intNum2).ToString();
635 case "-": return (intNum1 - intNum2).ToString();
636 case "#": return (intNum1 * intNum2).ToString();
637 default: return string.Empty;
638 }
639 }
640 return string.Empty;
641 }
642
643 /// <summary>
644 /// 功能描述:获取青海验证码结果
645 /// 作 者:huangzh
646 /// 创建日期:2016-09-08 17:20:13
647 /// 任务编号:
648 /// </summary>
649 /// <param name="bitImage">bitImage</param>
650 /// <returns>返回值</returns>
651 private string GetQingHai(Bitmap bitImage)
652 {
653 Bitmap bitBase = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
654 bitImage = ClearColor(bitImage);
655
656 //灰度
657 bitImage = HuiDu(bitImage);
658
659 //二值化
660 bitImage = ErZhi(bitImage);
661
662 //反转
663 bitImage = ColorFanZhuan(bitImage);
664
665 //去噪
666 bitImage = QuZao(bitImage);
667
668 List<Bitmap> lstImages = GetTouYingImages(bitImage, bitBase);
669 //for (int i = 0; i < lstImages.Count; i++)
670 //{
671 // lstImages[i].Save("d:\\" + i + ".jpg");
672 //}
673 //标记识别
674 List<string> lstChar = GetImageChar(lstImages);
675 string strNum1 = string.Empty;
676 string strYun = string.Empty;
677 string strNum2 = string.Empty;
678 foreach (string strItem in lstChar)
679 {
680 if (strItem == "$")
681 continue;
682 if (Regex.IsMatch(strItem, @"\d+"))
683 {
684 if (string.IsNullOrEmpty(strYun))
685 {
686 strNum1 += strItem;
687 }
688 else
689 {
690 strNum2 = strItem;
691 }
692 }
693 else if (Regex.IsMatch(strItem, @"\+|\-|\#|\%"))
694 {
695 if (string.IsNullOrEmpty(strYun))
696 {
697 strYun = strItem;
698 }
699 }
700 else if (Regex.IsMatch(strItem, @"\="))
701 {
702 break;
703 }
704 }
705
706 if (!string.IsNullOrEmpty(strNum1) && !string.IsNullOrEmpty(strYun) && !string.IsNullOrEmpty(strNum2))
707 {
708 int intNum1 = int.Parse(strNum1);
709 int intNum2 = int.Parse(strNum2);
710 switch (strYun)
711 {
712 case "+": return (intNum1 + intNum2).ToString();
713 case "-": return (intNum1 - intNum2).ToString();
714 case "#": return (intNum1 * intNum2).ToString();
715 case "%": return (intNum1 / intNum2).ToString();
716 default: return string.Empty;
717 }
718 }
719 return string.Empty;
720 }
721
722 /// <summary>
723 /// 功能描述:获取山西识别结果
724 /// 作 者:huangzh
725 /// 创建日期:2016-09-09 12:14:46
726 /// 任务编号:
727 /// </summary>
728 /// <param name="bitImage">bitImage</param>
729 /// <returns>返回值</returns>
730 private string GetShanXi(Bitmap bitImage)
731 {
732 Bitmap bitBase = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
733 bitImage = ClearColor(bitImage);
734
735 //灰度
736 bitImage = HuiDu(bitImage);
737
738 //二值化
739 bitImage = ErZhi(bitImage);
740
741 //反转
742 bitImage = ColorFanZhuan(bitImage);
743
744 //去噪
745 bitImage = QuZao(bitImage);
746
747 List<Bitmap> lstImages = GetTouYingImages(bitImage, bitBase, 1);
748 //for (int i = 0; i < lstImages.Count; i++)
749 //{
750 // lstImages[i].Save("d:\\" + i + ".jpg");
751 //}
752 //标记识别
753 List<string> lstChar = GetImageChar(lstImages);
754 string strNum1 = string.Empty;
755 string strYun = string.Empty;
756 string strNum2 = string.Empty;
757 foreach (string strItem in lstChar)
758 {
759 if (strItem == "$")
760 continue;
761 if (Regex.IsMatch(strItem, @"\d+"))
762 {
763 if (string.IsNullOrEmpty(strYun))
764 {
765 strNum1 += strItem;
766 }
767 else if (string.IsNullOrEmpty(strNum2))
768 {
769 strNum2 = strItem;
770 }
771 }
772 else if (Regex.IsMatch(strItem, @"\+|\-|\#|\%"))
773 {
774 if (string.IsNullOrEmpty(strYun))
775 {
776 strYun = strItem;
777 }
778 }
779 else if (Regex.IsMatch(strItem, @"\="))
780 {
781 break;
782 }
783 }
784
785 if (!string.IsNullOrEmpty(strNum1) && !string.IsNullOrEmpty(strYun) && !string.IsNullOrEmpty(strNum2))
786 {
787 int intNum1 = int.Parse(strNum1);
788 int intNum2 = int.Parse(strNum2);
789 switch (strYun)
790 {
791 case "+": return (intNum1 + intNum2).ToString();
792 case "-": return (intNum1 - intNum2).ToString();
793 case "#": return (intNum1 * intNum2).ToString();
794 case "%": return (intNum1 / intNum2).ToString();
795 default: return string.Empty;
796 }
797 }
798 return string.Empty;
799 }
800
801 /// <summary>
802 /// 功能描述:获取黑龙江验证码结果
803 /// 作 者:huangzh
804 /// 创建日期:2016-09-09 16:46:32
805 /// 任务编号:
806 /// </summary>
807 /// <param name="bitImage">bitImage</param>
808 /// <returns>返回值</returns>
809 private string GetHeiLongJiang(Bitmap bitImage)
810 {
811 Bitmap bitBase = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
812 bitImage = ClearColor(bitImage);
813
814 //灰度
815 bitImage = HuiDu(bitImage);
816
817 //二值化
818 bitImage = ErZhi(bitImage);
819
820 //反转
821 bitImage = ColorFanZhuan(bitImage);
822
823 //去噪
824 bitImage = QuZao(bitImage);
825
826 List<Bitmap> lstImages = GetTouYingImages(bitImage, bitBase, 1);
827 //for (int i = 0; i < lstImages.Count; i++)
828 //{
829 // lstImages[i].Save("d:\\" + i + ".jpg");
830 //}
831 //标记识别
832 List<string> lstChar = GetImageChar(lstImages);
833 string strNum1 = string.Empty;
834 string strYun = string.Empty;
835 string strNum2 = string.Empty;
836 foreach (string strItem in lstChar)
837 {
838 if (strItem == "$")
839 continue;
840 if (Regex.IsMatch(strItem, @"\d+"))
841 {
842 if (string.IsNullOrEmpty(strYun))
843 {
844 strNum1 += strItem;
845 }
846 else if (string.IsNullOrEmpty(strNum2))
847 {
848 strNum2 = strItem;
849 }
850 }
851 else if (Regex.IsMatch(strItem, @"\+|\-|\#|\%"))
852 {
853 if (string.IsNullOrEmpty(strYun))
854 {
855 strYun = strItem;
856 }
857 }
858 else if (Regex.IsMatch(strItem, @"\="))
859 {
860 break;
861 }
862 }
863
864 if (!string.IsNullOrEmpty(strNum1) && !string.IsNullOrEmpty(strYun) && !string.IsNullOrEmpty(strNum2))
865 {
866 int intNum1 = int.Parse(strNum1);
867 int intNum2 = int.Parse(strNum2);
868 switch (strYun)
869 {
870 case "+": return (intNum1 + intNum2).ToString();
871 case "-": return (intNum1 - intNum2).ToString();
872 case "#": return (intNum1 * intNum2).ToString();
873 case "%": return (intNum1 / intNum2).ToString();
874 default: return string.Empty;
875 }
876 }
877 return string.Empty;
878 }
879
880 #endregion
881
882 #region 去除边框
883 private Bitmap ClearBroder(Bitmap bitImage)
884 {
885 string[] strs = m_xml.ConvertIdToName("01").Split(',');//上,右,下,左
886 int[] widths = { int.Parse(strs[0]), int.Parse(strs[1]), int.Parse(strs[2]), int.Parse(strs[3]) };
887 Bitmap bit = (bitImage as Bitmap).Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
888 int intWidth = bit.Width;
889 int intHeight = bit.Height;
890 //左右
891 int inti1 = widths[3];
892 int inti2 = widths[1];
893 for (int i = 0; i < intWidth; i++)
894 {
895 if (i < inti1 || i >= intWidth - inti2)
896 {
897 for (int j = 0; j < intHeight; j++)
898 {
899 Console.WriteLine(i + "," + j);
900 bit.SetPixel(i, j, Color.White);
901 }
902 }
903 }
904
905 int intj1 = widths[0];
906 int intj2 = widths[2];
907 for (int j = 0; j < intHeight; j++)
908 {
909 if (j < intj1 || j >= intHeight - intj2)
910 {
911 for (int i = 0; i < intWidth; i++)
912 {
913 Console.WriteLine(i + "," + j);
914 bit.SetPixel(i, j, Color.White);
915 }
916 }
917 }
918 return bit;
919 }
920 #endregion
921
922 #region 颜色去除
923 /// <summary>
924 /// 功能描述:颜色去除
925 /// 作 者:huangzh
926 /// 创建日期:2016-09-01 15:28:08
927 /// 任务编号:
928 /// </summary>
929 /// <param name="bitImage">bitImage</param>
930 /// <returns>返回值</returns>
931 private Bitmap ClearColor(Bitmap bitImage)
932 {
933 Bitmap bit = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
934
935 string[] strs = m_xml.ConvertIdToName("11").Split('|');
936 List<Color> lstCS = new List<Color>();
937 foreach (var item in strs)
938 {
939 string[] colorStrs = item.Split(',');
940 Color c = Color.FromArgb(int.Parse(colorStrs[0]), int.Parse(colorStrs[1]), int.Parse(colorStrs[2]));
941 lstCS.Add(c);
942 }
943 int intCha = int.Parse(m_xml.ConvertIdToName("12"));
944 string[] toStrs = m_xml.ConvertIdToName("13").Split(',');
945 Color cTo = Color.FromArgb(int.Parse(toStrs[0]), int.Parse(toStrs[1]), int.Parse(toStrs[2]));
946
947 int intWidth = bit.Width;
948 int intHeight = bit.Height;
949 for (int i = 0; i < intWidth; i++)
950 {
951 for (int j = 0; j < intHeight; j++)
952 {
953 Color c = bit.GetPixel(i, j);
954 foreach (var item in lstCS)
955 {
956 if (IsClearColor(item, c, intCha))
957 {
958 bit.SetPixel(i, j, cTo);
959 break;
960 }
961 }
962
963 }
964 }
965
966 return bit;
967 }
968
969 /// <summary>
970 /// 功能描述:是否需要清除颜色
971 /// 作 者:huangzh
972 /// 创建日期:2016-09-01 15:27:28
973 /// 任务编号:
974 /// </summary>
975 /// <param name="c1">c1</param>
976 /// <param name="c2">c2</param>
977 /// <param name="intCha">intCha</param>
978 /// <returns>返回值</returns>
979 private bool IsClearColor(
980 Color c1,
981 Color c2,
982 int intCha)
983 {
984 return Math.Abs(c1.R - c2.R) < intCha && Math.Abs(c1.G - c2.G) < intCha && Math.Abs(c1.B - c2.B) < intCha;
985 }
986 #endregion
987
988 #region 灰度
989 /// <summary>
990 /// 功能描述:灰度
991 /// 作 者:huangzh
992 /// 创建日期:2016-09-01 15:31:00
993 /// 任务编号:
994 /// </summary>
995 /// <param name="bitImage">bitImage</param>
996 /// <returns>返回值</returns>
997 private Bitmap HuiDu(
998 Bitmap bitImage)
999 {
1000 string[] cs = m_xml.ConvertIdToName("21").Split(',');
1001
1002 double dbl1 = double.Parse(cs[0]) / 100;
1003 double dbl2 = double.Parse(cs[1]) / 100;
1004 double dbl3 = double.Parse(cs[2]) / 100;
1005 Bitmap bit = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1006 Grayscale filter = new Grayscale(dbl1, dbl2, dbl3);
1007 // apply the filter
1008 Bitmap grayImage = filter.Apply(bit);
1009 return grayImage;
1010 }
1011 #endregion
1012
1013 #region 二值化
1014 /// <summary>
1015 /// 功能描述:二值化
1016 /// 作 者:huangzh
1017 /// 创建日期:2016-09-01 15:33:28
1018 /// 任务编号:
1019 /// </summary>
1020 /// <param name="bitImage">bitImage</param>
1021 /// <returns>返回值</returns>
1022 private Bitmap ErZhi(Bitmap bitImage)
1023 {
1024 int intErZhi = int.Parse(m_xml.ConvertIdToName("31"));
1025 Bitmap bit = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
1026 Threshold filter = new Threshold(intErZhi);
1027 // apply the filter
1028 filter.ApplyInPlace(bit);
1029 return bit;
1030 }
1031 #endregion
1032
1033 #region 颜色反转
1034 /// <summary>
1035 /// 功能描述:颜色反转
1036 /// 作 者:huangzh
1037 /// 创建日期:2016-09-01 15:34:09
1038 /// 任务编号:
1039 /// </summary>
1040 /// <param name="image">image</param>
1041 /// <returns>返回值</returns>
1042 private Bitmap ColorFanZhuan(Bitmap image)
1043 {
1044 image = image.Clone(new Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1045 for (int i = 0; i < image.Width; i++)
1046 {
1047 for (int j = 0; j < image.Height; j++)
1048 {
1049 Color c = image.GetPixel(i, j);
1050 if (c.Name != "ffffffff")
1051 {
1052 image.SetPixel(i, j, Color.White);
1053 }
1054 else
1055 {
1056 image.SetPixel(i, j, Color.Black);
1057 }
1058 }
1059 }
1060 return image;
1061 }
1062 #endregion
1063
1064 #region 去噪
1065 /// <summary>
1066 /// 功能描述:去噪
1067 /// 作 者:huangzh
1068 /// 创建日期:2016-09-01 15:35:58
1069 /// 任务编号:
1070 /// </summary>
1071 /// <param name="bitImage">bitImage</param>
1072 /// <returns>返回值</returns>
1073 private Bitmap QuZao(Bitmap bitImage)
1074 {
1075 string[] strSizeZao = m_xml.ConvertIdToName("41").Split(',');
1076 Size size = new Size(int.Parse(strSizeZao[0]), int.Parse(strSizeZao[1]));
1077 Bitmap bit = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1078 bit = new BlobsFiltering(size.Width, size.Height, bit.Width, bit.Height).Apply(bit);
1079 return bit;
1080 }
1081 #endregion
1082
1083 #region 去毛边
1084 /// <summary>
1085 /// 功能描述:去毛边
1086 /// 作 者:huangzh
1087 /// 创建日期:2016-09-01 15:36:37
1088 /// 任务编号:
1089 /// </summary>
1090 /// <param name="bitImg">bitImg</param>
1091 /// <returns>返回值</returns>
1092 private static Bitmap ClearMaoBian(Bitmap bitImg)
1093 {
1094 Bitmap bit = bitImg.Clone(new Rectangle(0, 0, bitImg.Width, bitImg.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1095
1096 for (int i = 0; i < bit.Width; i++)
1097 {
1098
1099 for (int j = 0; j < bit.Height; j++)
1100 {
1101 // Console.WriteLine(i + "," + j);
1102 Color c = bit.GetPixel(i, j);
1103
1104 if (c.Name == "ffffffff")
1105 {
1106 //判定上下左右
1107 int intCount = 0;
1108 //上
1109 if (j > 0)
1110 {
1111 Color c1 = bit.GetPixel(i, j - 1);
1112 if (c1.Name != "ffffffff")
1113 intCount++;
1114 }
1115 else
1116 {
1117 intCount++;
1118 }
1119 //下
1120 if (j < bit.Height - 1)
1121 {
1122 Color c2 = bit.GetPixel(i, j + 1);
1123 if (c2.Name != "ffffffff")
1124 intCount++;
1125 }
1126 else
1127 {
1128 intCount++;
1129 }
1130 //左
1131 if (i > 0)
1132 {
1133 Color c3 = bit.GetPixel(i - 1, j);
1134 if (c3.Name != "ffffffff")
1135 intCount++;
1136 }
1137 else
1138 {
1139 intCount++;
1140 }
1141 //右
1142 if (i < bit.Width - 1)
1143 {
1144 Color c4 = bit.GetPixel(i + 1, j);
1145 if (c4.Name != "ffffffff")
1146 intCount++;
1147 }
1148 else
1149 {
1150 intCount++;
1151 }
1152
1153 if (intCount >= 3)
1154 {
1155 bit.SetPixel(i, j, Color.Black);
1156 }
1157 }
1158
1159 }
1160
1161 }
1162 return bit;
1163 }
1164 #endregion
1165
1166 #region 连通并识别
1167
1168 /// <summary>
1169 /// 功能描述:识别字符
1170 /// 作 者:huangzh
1171 /// 创建日期:2016-09-02 09:06:44
1172 /// 任务编号:
1173 /// </summary>
1174 /// <param name="lstImage">lstImage</param>
1175 /// <returns>返回值</returns>
1176 private List<string> GetImageChar(List<Bitmap> lstImage)
1177 {
1178 string strPath = Path.Combine(m_strModePath, "imgs");
1179
1180 List<string> lstKeys = new List<string>();
1181 Console.WriteLine("--------------");
1182 foreach (var item in lstImage)
1183 {
1184 string strKey = GetTextByOneChar(item, strPath);
1185 lstKeys.Add(strKey);
1186 Console.WriteLine(strKey);
1187 }
1188
1189 return lstKeys;
1190 }
1191
1192 /// <summary>
1193 /// 功能描述:获取连通
1194 /// 作 者:huangzh
1195 /// 创建日期:2016-09-01 15:50:18
1196 /// 任务编号:
1197 /// </summary>
1198 /// <param name="bitImage">bitImage</param>
1199 /// <param name="minSize">最小连通域</param>
1200 /// <param name="blnIsCheckWidth">合并检测</param>
1201 /// <param name="intMaxWidth">当blnIsCheckWidth=true时,单个字符最大宽度</param>
1202 /// <param name="blnIsCheckMinWidth">是否旋转为最小宽度</param>
1203 /// <returns></returns>
1204 private List<Bitmap> GetLianTongImage(Bitmap bitImage)
1205 {
1206 string[] strSizeBiao = m_xml.ConvertIdToName("51").Split(',');
1207 Size minSize = new Size(int.Parse(strSizeBiao[0]), int.Parse(strSizeBiao[1]));
1208 bool blnIsCheckWidth = bool.Parse(m_xml.ConvertIdToName("52"));
1209 int intMaxWidth = int.Parse(m_xml.ConvertIdToName("53"));
1210 bool blnIsCheckMinWidth = bool.Parse(m_xml.ConvertIdToName("54"));
1211
1212 Bitmap bit = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1213 Bitmap imageCache = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1214 // process image with blob counter
1215 BlobCounter blobCounter = new BlobCounter();
1216 blobCounter.ProcessImage(bit);
1217 Blob[] blobs = blobCounter.GetObjectsInformation();
1218
1219 // create convex hull searching algorithm
1220 GrahamConvexHull hullFinder = new GrahamConvexHull();
1221
1222 // lock image to draw on it
1223 BitmapData data = bit.LockBits(
1224 new Rectangle(0, 0, bit.Width, bit.Height),
1225 ImageLockMode.ReadWrite, bit.PixelFormat);
1226
1227 Dictionary<Bitmap, int> lstBitNew = new Dictionary<Bitmap, int>();
1228
1229 Dictionary<List<IntPoint>, int> lstedgePoints = new Dictionary<List<IntPoint>, int>();
1230
1231 // process each blob
1232 foreach (Blob blob in blobs)
1233 {
1234 List<IntPoint> leftPoints = new List<IntPoint>();
1235 List<IntPoint> rightPoints = new List<IntPoint>();
1236 List<IntPoint> edgePoints = new List<IntPoint>();
1237
1238 // get blob's edge points
1239 blobCounter.GetBlobsLeftAndRightEdges(blob,
1240 out leftPoints, out rightPoints);
1241
1242 edgePoints.AddRange(leftPoints);
1243 edgePoints.AddRange(rightPoints);
1244
1245 // blob's convex hull
1246 List<IntPoint> hull = hullFinder.FindHull(edgePoints);
1247
1248
1249
1250 lstedgePoints.Add(hull, GetMinX(hull));
1251 }
1252
1253 List<List<IntPoint>> dicLstPoints = (from d in lstedgePoints
1254 orderby d.Value ascending
1255 select d.Key).ToList();
1256
1257 if (blnIsCheckWidth)
1258 {
1259 #region 检测连通域是否可合并
1260 bool isBreak = false;
1261 while (!isBreak)
1262 {
1263 isBreak = true;
1264
1265 int intKeyLength = dicLstPoints.Count;
1266 for (int i = 0; i < intKeyLength; i++)
1267 {
1268 if (i != 0)
1269 {
1270 bool bln = CheckIsHeBing(dicLstPoints[i - 1], dicLstPoints[i], intMaxWidth);
1271 if (bln)
1272 {
1273 dicLstPoints[i].AddRange(dicLstPoints[i - 1]);
1274 dicLstPoints.RemoveAt(i - 1);
1275 isBreak = false;
1276 break;
1277 }
1278 }
1279
1280 if (i != intKeyLength - 1)
1281 {
1282 bool bln = CheckIsHeBing(dicLstPoints[i], dicLstPoints[i + 1], intMaxWidth);
1283 if (bln)
1284 {
1285 dicLstPoints[i].AddRange(dicLstPoints[i + 1]);
1286 dicLstPoints.RemoveAt(i + 1);
1287 isBreak = false;
1288 break;
1289 }
1290 }
1291 }
1292 }
1293 #endregion
1294 }
1295
1296 foreach (List<IntPoint> item in dicLstPoints)
1297 {
1298 List<IntPoint> hull = hullFinder.FindHull(item);
1299 int intMinX = 0;
1300 Bitmap bitNew = GetBitmapByListPoint(hull, imageCache, ref intMinX);
1301 if (bitNew.Width < minSize.Width || bitNew.Height < minSize.Height)
1302 continue;
1303 lstBitNew.Add(bitNew, intMinX);
1304 Drawing.Polygon(data, hull, Color.Red);
1305 }
1306
1307 bit.UnlockBits(data);
1308
1309 Dictionary<Bitmap, int> dic1Asc1 = (from d in lstBitNew
1310 orderby d.Value ascending
1311 select d).ToDictionary(k => k.Key, v => v.Value);
1312
1313 List<Bitmap> lstImage = new List<Bitmap>();
1314
1315 foreach (var item in dic1Asc1)
1316 {
1317 Bitmap bitItem = item.Key;
1318 bitItem = ToResizeAndCenter(bitItem);
1319 if (blnIsCheckMinWidth)
1320 {
1321 bitItem = GetMinWidthBitmap(bitItem);
1322 }
1323 lstImage.Add(bitItem);//添加图片
1324 }
1325
1326 return lstImage;
1327 }
1328
1329 /// <summary>
1330 /// 功能描述:识别单数字
1331 /// 作 者:huangzh
1332 /// 创建日期:2016-08-25 15:19:35
1333 /// 任务编号:
1334 /// </summary>
1335 /// <param name="bit">bit</param>
1336 /// <param name="lstNoChar">lstNoChar</param>
1337 /// <returns>返回值</returns>
1338 private string GetTextByOneChar(Bitmap bit, string strSourceImagPath, List<string> lstNoChar = null)
1339 {
1340 bit = bit.Clone(new Rectangle(0, 0, bit.Width, bit.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1341 var files = Directory.GetFiles(strSourceImagPath);
1342 if (lstNoChar != null && lstNoChar.Count > 0)
1343 {
1344 var newFiles = from p in files
1345 where !lstNoChar.Contains(Path.GetFileName(p).Split('_')[0])
1346 select p;
1347 files = newFiles.ToArray<string>();
1348 }
1349
1350 var templateList = files.Select(i => { return new Bitmap(i); }).ToList();
1351 var templateListFileName = files.Select(i => { return Path.GetFileName(i); }).ToList();
1352
1353 var result = new List<string>();
1354
1355 ExhaustiveTemplateMatching templateMatching = new ExhaustiveTemplateMatching(0.8f);
1356
1357 float max = 0;
1358 int index = 0;
1359
1360 if (bit.Width <= 25 && bit.Height <= 25)
1361 bit = ToResizeAndCenter(bit);
1362 //bit.Save("d:\\111.jpg");
1363 for (int j = 0; j < templateList.Count; j++)
1364 {
1365 var compare = templateMatching.ProcessImage(bit, templateList[j]);
1366 //if (templateListFileName[index].StartsWith("%"))
1367 //{
1368 // Console.WriteLine(templateListFileName[index]);
1369 //}
1370 if (compare.Length > 0 && compare[0].Similarity > max)
1371 {
1372 //记录下最相似的
1373 max = compare[0].Similarity;
1374 index = j;
1375 }
1376 }
1377 if (templateListFileName.Count > 0)
1378 return templateListFileName[index].Split('_')[0];
1379 else
1380 return "";
1381 }
1382
1383
1384 /// <summary>
1385 /// 功能描述:得到最小x
1386 /// 作 者:huangzh
1387 /// 创建日期:2016-09-01 15:42:22
1388 /// 任务编号:
1389 /// </summary>
1390 /// <param name="hull">hull</param>
1391 /// <returns>返回值</returns>
1392 private int GetMinX(List<IntPoint> hull)
1393 {
1394 int x = int.MaxValue;
1395 foreach (IntPoint item in hull)
1396 {
1397 if (item.X < x)
1398 x = item.X;
1399 }
1400 return x;
1401 }
1402
1403 /// <summary>
1404 /// 功能描述:检查是否需要合并(目前仅检查x方向合并)
1405 /// 作 者:huangzh
1406 /// 创建日期:2016-09-01 15:42:56
1407 /// 任务编号:
1408 /// </summary>
1409 /// <param name="lst1">lst1</param>
1410 /// <param name="lst2">lst2</param>
1411 /// <param name="intMaxWidth">intMaxWidth</param>
1412 /// <returns>返回值</returns>
1413 private bool CheckIsHeBing(List<IntPoint> lst1, List<IntPoint> lst2, int intMaxWidth)
1414 {
1415 int minx1 = int.MaxValue, minx2 = int.MaxValue;
1416 int maxx1 = int.MinValue, maxx2 = int.MinValue;
1417
1418 foreach (IntPoint item in lst1)
1419 {
1420 if (item.X > maxx1)
1421 maxx1 = item.X;
1422 if (item.X < minx1)
1423 minx1 = item.X;
1424 }
1425
1426 foreach (IntPoint item in lst2)
1427 {
1428 if (item.X > maxx2)
1429 maxx2 = item.X;
1430 if (item.X < minx2)
1431 minx2 = item.X;
1432 }
1433
1434 int intCenter1 = minx1 + (maxx1 - minx1) / 2;
1435 int intCenter2 = minx2 + (maxx2 - minx2) / 2;
1436 if ((intCenter1 > minx2 && intCenter1 < maxx2) || (intCenter2 > minx1 && intCenter2 < maxx1))
1437 {
1438 int _intMin = minx1 < minx2 ? minx1 : minx2;
1439 int _intMax = maxx1 > maxx2 ? maxx1 : maxx2;
1440
1441 if (_intMax - _intMin > intMaxWidth)
1442 return false;
1443 else
1444 return true;
1445 }
1446 else
1447 return false;
1448 }
1449
1450 /// <summary>
1451 /// 功能描述:根据坐标列表截图
1452 /// 作 者:huangzh
1453 /// 创建日期:2016-09-01 15:43:57
1454 /// 任务编号:
1455 /// </summary>
1456 /// <param name="hull">hull</param>
1457 /// <param name="bitImg">bitImg</param>
1458 /// <param name="_minX">_minX</param>
1459 /// <returns>返回值</returns>
1460 private Bitmap GetBitmapByListPoint(List<IntPoint> hull, Bitmap bitImg, ref int _minX)
1461 {
1462 int minx = int.MaxValue;
1463 int miny = int.MaxValue;
1464 int maxx = int.MinValue;
1465 int maxy = int.MinValue;
1466 foreach (IntPoint item in hull)
1467 {
1468 if (item.X > maxx)
1469 maxx = item.X;
1470 if (item.X < minx)
1471 minx = item.X;
1472
1473 if (item.Y > maxy)
1474 maxy = item.Y;
1475 if (item.Y < miny)
1476 miny = item.Y;
1477 }
1478
1479 Bitmap bit = new Bitmap(maxx - minx + 1, maxy - miny + 1);
1480 int bitImgWidth = bitImg.Width;
1481 int bitImgHeight = bitImg.Height;
1482 for (int i = minx; i <= maxx; i++)
1483 {
1484 for (int j = miny; j <= maxy; j++)
1485 {
1486 Color c = bitImg.GetPixel(i, j);
1487 if (c.R == 0)
1488 c = Color.White;
1489 else
1490 c = Color.Black;
1491 bit.SetPixel(i - minx, j - miny, c);
1492 }
1493 }
1494 _minX = minx;
1495 // bit.Save("d:\\1\\" + Guid.NewGuid() + ".jpg");
1496 return bit;
1497 }
1498
1499 /// <summary>
1500 /// 功能描述:图片放到中心
1501 /// 作 者:huangzh
1502 /// 创建日期:2016-08-25 15:16:42
1503 /// 任务编号:
1504 /// </summary>
1505 /// <param name="bit">bit</param>
1506 /// <param name="w">w</param>
1507 /// <param name="h">h</param>
1508 /// <returns>返回值</returns>
1509 private Bitmap ToResizeAndCenter(Bitmap bit)
1510 {
1511 bit = bit.Clone(new Rectangle(0, 0, bit.Width, bit.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1512
1513 bit = new Invert().Apply(bit);
1514
1515 int sw = bit.Width;
1516 int sh = bit.Height;
1517
1518 int w, h;
1519 if (sw < 25 && sh < 25)
1520 {
1521 w = 25;
1522 h = 25;
1523 }
1524 else
1525 {
1526 w = sw + 5;
1527 h = sh + 5;
1528 }
1529
1530
1531 Crop corpFilter = new Crop(new Rectangle(0, 0, w, h));
1532
1533 bit = corpFilter.Apply(bit);
1534
1535 //再反转回去
1536 bit = new Invert().Apply(bit);
1537
1538 //计算中心位置
1539 int centerX = (w - sw) / 2;
1540 int centerY = (h - sh) / 2;
1541
1542 bit = new CanvasMove(new IntPoint(centerX, centerY), Color.White).Apply(bit);
1543 return bit;
1544 }
1545
1546 /// <summary>
1547 /// 功能描述:得到左右30度最窄的图片
1548 /// 作 者:huangzh
1549 /// 创建日期:2016-08-25 14:58:32
1550 /// 任务编号:
1551 /// </summary>
1552 /// <param name="bitImg">bitImg</param>
1553 /// <returns>返回值</returns>
1554 private Bitmap GetMinWidthBitmap(Bitmap bitImg, float fltNum = 15)
1555 {
1556 Bitmap bitCache = bitImg;
1557 for (float i = fltNum * -1; i < fltNum; i++)
1558 {
1559 if (i == 0)
1560 continue;
1561 Bitmap bit1 = bitImg.Clone(new Rectangle(0, 0, bitImg.Width, bitImg.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1562 Bitmap bit2 = RotateImage(bit1, i);
1563 Bitmap bit3 = GetMinBitmap(bit2);
1564 if (bit3.Width < bitCache.Width)
1565 {
1566 bitCache = bit3;
1567 }
1568 else
1569 {
1570 bit3.Dispose();
1571 }
1572 }
1573 return bitCache;
1574 }
1575
1576 /// <summary>
1577 /// 功能描述:缩小图片
1578 /// 作 者:huangzh
1579 /// 创建日期:2016-08-25 14:55:46
1580 /// 任务编号:
1581 /// </summary>
1582 /// <param name="bit">bit</param>
1583 /// <returns>返回值</returns>
1584 private Bitmap GetMinBitmap(Bitmap bit)
1585 {
1586 int x1 = 0, y1 = 0;
1587 int x2 = 0, y2 = 0;
1588 GetXY(bit, ref x1, ref y1, ref x2, ref y2);
1589 Bitmap bit11 = bit.Clone(new Rectangle(x1, y1, x2 - x1 + 1, y2 - y1 + 1), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1590 return bit11;
1591 }
1592
1593 /// <summary>
1594 /// 功能描述:旋转图片
1595 /// 作 者:huangzh
1596 /// 创建日期:2016-08-25 14:57:11
1597 /// 任务编号:
1598 /// </summary>
1599 /// <param name="b">b</param>
1600 /// <param name="angle">angle</param>
1601 /// <returns>返回值</returns>
1602 private Bitmap RotateImage(Bitmap b, float angle)
1603 {
1604 //对黑白进行颜色反转
1605 b = ColorFanZhuan(b);
1606 RotateNearestNeighbor filter = new RotateNearestNeighbor(angle, true);
1607 Bitmap bnew = filter.Apply(b);
1608 bnew = ColorFanZhuan(bnew);
1609 return bnew;
1610 }
1611
1612 /// <summary>
1613 /// 功能描述:获得最大最小xy
1614 /// 作 者:huangzh
1615 /// 创建日期:2016-08-25 14:55:56
1616 /// 任务编号:
1617 /// </summary>
1618 /// <param name="bit">bit</param>
1619 /// <param name="x1">x1</param>
1620 /// <param name="y1">y1</param>
1621 /// <param name="x2">x2</param>
1622 /// <param name="y2">y2</param>
1623 private void GetXY(
1624 Bitmap bit,
1625 ref int x1,
1626 ref int y1,
1627 ref int x2,
1628 ref int y2)
1629 {
1630 bool bln = false;
1631 #region 最小X
1632 for (int i = 0; i < bit.Width; i++)
1633 {
1634 for (int j = 0; j < bit.Height; j++)
1635 {
1636 Color c = bit.GetPixel(i, j);
1637 if (c.Name != "ffffffff")
1638 {
1639 x1 = i;
1640 bln = true;
1641 break;
1642 }
1643 }
1644 if (bln)
1645 {
1646 break;
1647 }
1648 }
1649 #endregion
1650 #region 最大X
1651 bln = false;
1652 for (int i = bit.Width - 1; i >= 0; i--)
1653 {
1654 for (int j = 0; j < bit.Height; j++)
1655 {
1656 Color c = bit.GetPixel(i, j);
1657 if (c.Name != "ffffffff")
1658 {
1659 x2 = i;
1660 bln = true;
1661 break;
1662 }
1663 }
1664 if (bln)
1665 {
1666 break;
1667 }
1668 }
1669 #endregion
1670 #region 最小Y
1671 bln = false;
1672 for (int j = 0; j < bit.Height; j++)
1673 {
1674 for (int i = 0; i < bit.Width; i++)
1675 {
1676 Color c = bit.GetPixel(i, j);
1677 if (c.Name != "ffffffff")
1678 {
1679 y1 = j;
1680 bln = true;
1681 break;
1682 }
1683 }
1684 if (bln)
1685 {
1686 break;
1687 }
1688 }
1689 #endregion
1690 #region 最大Y
1691 bln = false;
1692 for (int j = bit.Height - 1; j >= 0; j--)
1693 {
1694 for (int i = 0; i < bit.Width; i++)
1695 {
1696 Color c = bit.GetPixel(i, j);
1697 if (c.Name != "ffffffff")
1698 {
1699 y2 = j;
1700 bln = true;
1701 break;
1702 }
1703 }
1704 if (bln)
1705 {
1706 break;
1707 }
1708 }
1709 #endregion
1710 }
1711 #endregion
1712
1713 #region 细化图片
1714 /// <summary>
1715 /// 功能描述:细化图片
1716 /// 作 者:huangzh
1717 /// 创建日期:2016-09-01 16:07:13
1718 /// 任务编号:
1719 /// </summary>
1720 /// <param name="bitImage">bitImage</param>
1721 /// <returns>返回值</returns>
1722 private Bitmap XiHuaBitMap(Bitmap bitImage)
1723 {
1724 Bitmap bit = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1725 bit = XiHua.Xihua(bit, XiHua.array);
1726 return bit;
1727 }
1728 #endregion
1729
1730 #region 膨胀
1731 /// <summary>
1732 /// 功能描述:膨胀
1733 /// 作 者:huangzh
1734 /// 创建日期:2016-09-01 16:08:21
1735 /// 任务编号:
1736 /// </summary>
1737 /// <param name="bitImage">bitImage</param>
1738 /// <returns>返回值</returns>
1739 private Bitmap PangZhang(Bitmap bitImage)
1740 {
1741 Bitmap bit = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1742 Dilatation filter = new Dilatation();
1743 // apply the filter
1744 bit = filter.Apply(bit);
1745 return bit;
1746 }
1747 #endregion
1748
1749 #region 倒影分割
1750
1751 /// <summary>
1752 /// 功能描述:获取图片投影分割
1753 /// 作 者:huangzh
1754 /// 创建日期:2016-09-09 12:20:54
1755 /// 任务编号:
1756 /// </summary>
1757 /// <param name="bitImage">bitImage</param>
1758 /// <param name="bitBase">bitBase</param>
1759 /// <param name="intRemove">1/2</param>
1760 /// <returns>返回值</returns>
1761 private List<Bitmap> GetTouYingImages(Bitmap bitImage, Bitmap bitBase, int intRemove = 2)
1762 {
1763 Bitmap bit = bitImage.Clone(new Rectangle(0, 0, bitImage.Width, bitImage.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
1764 bool blnCheckDG = bool.Parse(m_xml.ConvertIdToName("61", "false"));
1765 int intMaxDG = int.Parse(m_xml.ConvertIdToName("62", "3"));
1766 bool blnCheckWidth = bool.Parse(m_xml.ConvertIdToName("63", "false"));
1767 int intMaxWidth = int.Parse(m_xml.ConvertIdToName("64", "25"));
1768
1769 HorizontalIntensityStatistics his = new HorizontalIntensityStatistics(bit);
1770 Histogram histogram = his.Blue;
1771 List<Rectangle> lstRects = new List<Rectangle>();
1772 int intWidth = bit.Width;
1773 int intHeight = bit.Height;
1774 bool blnHasValue = false;
1775 int intStartX = 0, intEndx = 0;
1776 for (int i = 0; i < histogram.Values.Length; i++)
1777 {
1778 if (histogram.Values[i] == 0 || (blnCheckDG && histogram.Values[i] <= intMaxDG * 256))
1779 {
1780 if (blnHasValue)
1781 {
1782 intEndx = i;
1783 blnHasValue = false;
1784 lstRects.Add(new Rectangle(intStartX, 0, intEndx - intStartX, intHeight));
1785 }
1786 }
1787 else
1788 {
1789 if (!blnHasValue)
1790 {
1791 intStartX = i;
1792 blnHasValue = true;
1793 }
1794 }
1795 }
1796 if (blnHasValue)
1797 {
1798 lstRects.Add(new Rectangle(intStartX, 0, intWidth - intStartX, intHeight));
1799 }
1800
1801 Dictionary<Bitmap, Rectangle> lstBits = new Dictionary<Bitmap, Rectangle>();
1802 lstRects.ForEach(item => lstBits.Add(bit.Clone(item, System.Drawing.Imaging.PixelFormat.Format24bppRgb), item));
1803
1804 //特殊处理,移除最后2个
1805 List<Bitmap> lstKeys = lstBits.Keys.ToList();
1806 bool blnChaoKuan1 = false;
1807 if (lstKeys[lstKeys.Count - 1].Width > intMaxWidth - 5)
1808 blnChaoKuan1 = true;
1809 if (lstKeys[lstKeys.Count - 1].Width > 2 * intMaxWidth)
1810 intRemove = 1;
1811 lstBits.Remove(lstKeys[lstKeys.Count - 1]);
1812 if (intRemove == 2)
1813 {
1814 bool blnChaoKuan2 = false;
1815 if (lstKeys[lstKeys.Count - 2].Width > intMaxWidth - 5)
1816 blnChaoKuan2 = true;
1817 if (!(blnChaoKuan1 && blnChaoKuan2))
1818 lstBits.Remove(lstKeys[lstKeys.Count - 2]);
1819 }
1820
1821 List<Bitmap> lstImages = new List<Bitmap>();
1822 if (blnCheckWidth)
1823 {
1824 foreach (var item in lstBits)
1825 {
1826 if (item.Key.Width >= intMaxWidth)
1827 {
1828 int intColorCount = 0;
1829 Bitmap bitNew = HuiFuColorByImage(item.Key, bitBase, item.Value, ref intColorCount);
1830 int intSpliteNum = bitNew.Width / intMaxWidth + ((bitNew.Width % intMaxWidth) > 0 ? 1 : 0);
1831
1832 Bitmap[] images = ImageJuLei(bitNew, intSpliteNum, intColorCount);
1833
1834 //去噪
1835
1836
1837 List<Bitmap> lstImageNew = ImageOrder(images);
1838 foreach (var itemImage in lstImageNew)
1839 {
1840 lstImages.Add(GetMinBitmap(ColorFanZhuan(itemImage)));//需要做去噪
1841 }
1842 }
1843 else
1844 {
1845 lstImages.Add(GetMinBitmap(ColorFanZhuan(item.Key)));//需要做去噪
1846 }
1847 }
1848 }
1849
1850
1851 List<Bitmap> lstReturn = new List<Bitmap>();
1852
1853 foreach (var item in lstImages)
1854 {
1855 Bitmap bitItem = item;
1856 bitItem = ToResizeAndCenter(bitItem);
1857 if (bitItem.Width > 25 || bitItem.Height > 25)
1858 {
1859 bitItem = new Bitmap(bitItem, new Size(25, 25));
1860 }
1861 lstReturn.Add(bitItem);//添加图片
1862 }
1863
1864 return lstReturn;
1865 }
1866
1867
1868 /// <summary>
1869 /// 功能描述:图片排序
1870 /// 作 者:huangzh
1871 /// 创建日期:2016-09-08 17:44:21
1872 /// 任务编号:
1873 /// </summary>
1874 /// <param name="images">images</param>
1875 /// <returns>返回值</returns>
1876 private List<Bitmap> ImageOrder(Bitmap[] images)
1877 {
1878 Dictionary<int, int> lst = new Dictionary<int, int>();
1879
1880 for (int m = 0; m < images.Length; m++)
1881 {
1882 Bitmap bit = images[m];
1883 int intWidth = bit.Width;
1884 int intHeight = bit.Height;
1885 bool blnBreak = false;
1886 int intMinX = 0;
1887 for (int i = 0; i < intWidth; i++)
1888 {
1889 for (int j = 0; j < intHeight; j++)
1890 {
1891 Color c = bit.GetPixel(i, j);
1892 if (c.Name == "ffffffff")
1893 {
1894 blnBreak = true;
1895 intMinX = i;
1896 break;
1897 }
1898 }
1899 if (blnBreak)
1900 break;
1901 }
1902 lst.Add(m, intMinX);
1903 }
1904
1905 Dictionary<int, int> lstNew = (from d in lst
1906 orderby d.Value
1907 select d).ToDictionary(k => k.Key, v => v.Value);
1908 List<Bitmap> lstImage = new List<Bitmap>();
1909 foreach (var item in lstNew)
1910 {
1911 lstImage.Add(images[item.Key]);
1912 }
1913 return lstImage;
1914 }
1915
1916 /// <summary>
1917 /// 功能描述:恢复图片原色
1918 /// 作 者:huangzh
1919 /// 创建日期:2016-09-08 17:44:10
1920 /// 任务编号:
1921 /// </summary>
1922 /// <param name="bitImage">bitImage</param>
1923 /// <param name="bitSource">bitSource</param>
1924 /// <param name="rect">rect</param>
1925 /// <param name="intColorCount">intColorCount</param>
1926 /// <returns>返回值</returns>
1927 private Bitmap HuiFuColorByImage(
1928 Bitmap bitImage,
1929 Bitmap bitSource,
1930 Rectangle rect,
1931 ref int intColorCount)
1932 {
1933 intColorCount = 0;
1934 int intWidth = bitImage.Width;
1935 int intHeight = bitImage.Height;
1936 for (int i = 0; i < intWidth; i++)
1937 {
1938 for (int j = 0; j < intHeight; j++)
1939 {
1940 Color c = bitImage.GetPixel(i, j);
1941 if (c.Name == "ffffffff")
1942 {
1943 intColorCount++;
1944 bitImage.SetPixel(i, j, bitSource.GetPixel(i + rect.X, j + rect.Y));
1945 }
1946 }
1947 }
1948 return bitImage;
1949 }
1950
1951
1952 /// <summary>
1953 /// 功能描述:颜色聚类分割图片
1954 /// 作 者:huangzh
1955 /// 创建日期:2016-09-08 17:43:58
1956 /// 任务编号:
1957 /// </summary>
1958 /// <param name="bit">bit</param>
1959 /// <param name="intNum">intNum</param>
1960 /// <param name="intColorCount">intColorCount</param>
1961 /// <returns>返回值</returns>
1962 private Bitmap[] ImageJuLei(Bitmap bit, int intNum, int intColorCount)
1963 {
1964 Color[] colors;
1965 List<Color> _lst = new List<Color>();
1966 int intWidth = bit.Width;
1967 int intHeight = bit.Height;
1968 int intColorIndex = 0;
1969 for (int i = 0; i < intWidth; i++)
1970 {
1971 for (int j = 0; j < intHeight; j++)
1972 {
1973 Color c = bit.GetPixel(i, j);
1974 if (c.R != 0 && c.G != 0 && c.B != 0)
1975 {
1976 _lst.Add(c);
1977 intColorIndex++;
1978 }
1979 }
1980 }
1981 colors = _lst.ToArray();
1982 int k = intNum;
1983 Color[][] g;
1984 g = KmeansColor.cluster(colors, k);
1985 List<List<Color>> lstColors = new List<List<Color>>();
1986
1987 foreach (var item in g)
1988 {
1989 List<Color> lst = new List<Color>();
1990 foreach (var item1 in item)
1991 {
1992 Color c = item1;
1993
1994 if (!lst.Contains(c))
1995 {
1996 lst.Add(c);
1997 }
1998 }
1999 lstColors.Add(lst);
2000 }
2001
2002 Bitmap[] bits = new Bitmap[intNum];
2003 for (int m = 0; m < lstColors.Count; m++)
2004 {
2005 List<Color> lst = lstColors[m];
2006 Bitmap bitNew = bit.Clone(new Rectangle(0, 0, bit.Width, bit.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
2007 int intWidthNew = bitNew.Width;
2008 int intHeightNew = bitNew.Height;
2009 for (int i = 0; i < intWidthNew; i++)
2010 {
2011 for (int j = 0; j < intHeightNew; j++)
2012 {
2013 Color cNew = bitNew.GetPixel(i, j);
2014 if (cNew.R != 0 && cNew.G != 0 && cNew.B != 0)
2015 {
2016 if (!lst.Contains(cNew))
2017 {
2018 bitNew.SetPixel(i, j, Color.Black);
2019 }
2020 else
2021 {
2022 bitNew.SetPixel(i, j, Color.White);
2023 }
2024 }
2025 }
2026 }
2027 bitNew = QuZao(bitNew);
2028 bits[m] = bitNew;
2029 }
2030
2031 return bits;
2032 }
2033
2034 #endregion
2035
2036 private static class XiHua
2037 {
2038 public static int[] array = {0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,
2039 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,
2040 0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,
2041 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,
2042 1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
2043 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2044 1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,
2045 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2046 0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,
2047 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,
2048 0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,
2049 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
2050 1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
2051 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
2052 1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,
2053 1,1,0,0,1,1,1,0,1,1,0,0,1,0,0,0};
2054
2055 public static bool isWhite(Color color)
2056 {
2057 if (color.R + color.G + color.B > 400)
2058 {
2059 return true;
2060 }
2061 return false;
2062 }
2063
2064 public static Bitmap VThin(Bitmap image, int[] array)
2065 {
2066 int h = image.Height;
2067 int w = image.Width;
2068 int NEXT = 1;
2069 for (int i = 0; i < h; i++)
2070 {
2071 for (int j = 0; j < w; j++)
2072 {
2073 if (NEXT == 0)
2074 {
2075 NEXT = 1;
2076 }
2077 else
2078 {
2079 int M;
2080 if (0 < j && j < w - 1)
2081 {
2082 if (isBlack(image.GetPixel(j - 1, i)) && isBlack(image.GetPixel(j, i)) && isBlack(image.GetPixel(j + 1, i)))
2083 { // 三个点都为黑色的时候M=0,否则M=1
2084 M = 0;
2085 }
2086 else
2087 {
2088 M = 1;
2089 }
2090 }
2091 else
2092 {
2093 M = 1;
2094 }
2095 if (isBlack(image.GetPixel(j, i)) && M != 0)
2096 {
2097 int[] a = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2098 for (int k = 0; k < 3; k++)
2099 {
2100 for (int l = 0; l < 3; l++)
2101 {
2102 if ((-1 < (i - 1 + k) && (i - 1 + k) < h) && (-1 < (j - 1 + l) && (j - 1 + l) < w) && isWhite(image.GetPixel(j - 1 + l, i - 1 + k)))
2103 {
2104 a[k * 3 + l] = 1;
2105 }
2106 }
2107 }
2108 int sum = a[0] * 1 + a[1] * 2 + a[2] * 4 + a[3] * 8 + a[5] * 16 + a[6] * 32 + a[7] * 64 + a[8] * 128;
2109 if (array[sum] == 0)
2110 {
2111 image.SetPixel(j, i, Color.Black);
2112 }
2113 else
2114 {
2115 image.SetPixel(j, i, Color.White);
2116 }
2117 if (array[sum] == 1)
2118 {
2119 NEXT = 0;
2120 }
2121 }
2122 }
2123 }
2124 }
2125 return image;
2126 }
2127
2128 public static Bitmap HThin(Bitmap image, int[] array)
2129 {
2130 int h = image.Height;
2131 int w = image.Width;
2132 int NEXT = 1;
2133 for (int j = 0; j < w; j++)
2134 {
2135 for (int i = 0; i < h; i++)
2136 {
2137 if (NEXT == 0)
2138 {
2139 NEXT = 1;
2140 }
2141 else
2142 {
2143 int M;
2144 if (0 < i && i < h - 1)
2145 {
2146 if (isBlack(image.GetPixel(j, i - 1)) && isBlack(image.GetPixel(j, i)) && isBlack(image.GetPixel(j, i + 1)))
2147 {
2148 M = 0;
2149 }
2150 else
2151 {
2152 M = 1;
2153 }
2154 }
2155 else
2156 {
2157 M = 1;
2158 }
2159 if (isBlack(image.GetPixel(j, i)) && M != 0)
2160 {
2161 int[] a = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2162 for (int k = 0; k < 3; k++)
2163 {
2164 for (int l = 0; l < 3; l++)
2165 {
2166 if ((-1 < (i - 1 + k) && (i - 1 + k) < h) && (-1 < (j - 1 + l) && (j - 1 + l) < w) && isWhite(image.GetPixel(j - 1 + l, i - 1 + k)))
2167 {
2168 a[k * 3 + l] = 1;
2169 }
2170 }
2171 }
2172 int sum = a[0] * 1 + a[1] * 2 + a[2] * 4 + a[3] * 8 + a[5] * 16 + a[6] * 32 + a[7] * 64 + a[8] * 128;
2173 if (array[sum] == 0)
2174 {
2175 image.SetPixel(j, i, Color.Black);
2176 }
2177 else
2178 {
2179 image.SetPixel(j, i, Color.White);
2180 }
2181 if (array[sum] == 1)
2182 {
2183 NEXT = 0;
2184 }
2185 }
2186 }
2187 }
2188 }
2189 return image;
2190 }
2191
2192 public static Bitmap Xihua(Bitmap image, int[] array)
2193 {
2194 image = image.Clone(new Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
2195 int num = 10;
2196 Bitmap iXihua = image;
2197 for (int i = 0; i < num; i++)
2198 {
2199 VThin(iXihua, array);
2200 HThin(iXihua, array);
2201 }
2202 return iXihua;
2203 }
2204
2205
2206 public static bool isBlack(Color color)
2207 {
2208 if (color.R + color.G + color.B <= 600)
2209 {
2210 return true;
2211 }
2212 return false;
2213 }
2214
2215 }
2216 }
2217 }
备忘