颜色聚类
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 ///47 /// 功能描述:构造函数 48 /// 作 者:huangzh 49 /// 创建日期:2016-09-01 15:21:27 50 /// 任务编号: 51 /// 52 /// 验证码类型 53 /// 验证码识别模板文件夹路径 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 /// 69 /// 功能描述:识别验证码结果 70 /// 作 者:huangzh 71 /// 创建日期:2016-09-01 16:25:45 72 /// 任务编号: 73 /// 74 /// bit 75 /// 返回值 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 /// 110 /// 功能描述:获取天津验证码结果 111 /// 作 者:huangzh 112 /// 创建日期:2016-09-01 16:26:00 113 /// 任务编号: 114 /// 115 /// bitImage 116 /// 识别结果,如果为空,则为识别失败 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 /// 181 /// 功能描述:获取辽宁验证码结果 182 /// 作 者:huangzh 183 /// 创建日期:2016-09-02 09:30:56 184 /// 任务编号: 185 /// 186 /// bitImage 187 /// 返回值 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 /// 206 /// 功能描述:获取江苏验证码结果 207 /// 作 者:huangzh 208 /// 创建日期:2016-09-02 09:35:09 209 /// 任务编号: 210 /// 211 /// bitImage 212 /// 返回值 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 /// 246 /// 功能描述:获取江西验证码结果 247 /// 作 者:huangzh 248 /// 创建日期:2016-09-02 10:18:13 249 /// 任务编号: 250 /// 251 /// bitImage 252 /// 返回值 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 /// 314 /// 功能描述:获取重庆验证码结果 315 /// 作 者:huangzh 316 /// 创建日期:2016-09-02 10:30:53 317 /// 任务编号: 318 /// 319 /// bitImage 320 /// 返回值 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 /// 385 /// 功能描述:获取宁夏验证码结果 386 /// 作 者:huangzh 387 /// 创建日期:2016-09-02 10:41:18 388 /// 任务编号: 389 /// 390 /// bitImage 391 /// 返回值 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 /// 453 /// 功能描述:获取新疆验证码结果 454 /// 作 者:huangzh 455 /// 创建日期:2016-09-02 10:46:09 456 /// 任务编号: 457 /// 458 /// bitImage 459 /// 返回值 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 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 /// 542 /// 功能描述:获取天眼查验证码结果 543 /// 作 者:huangzh 544 /// 创建日期:2016-09-06 12:28:32 545 /// 任务编号: 546 /// 547 /// bitImage 548 /// 返回值 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 lstImages = GetLianTongImage(bitImage); 557 List<string> lstChar = GetImageChar(lstImages); 558 return string.Join("", lstChar); 559 } 560 561 /// 562 /// 功能描述:获取北京验证码结果 563 /// 作 者:huangzh 564 /// 创建日期:2016-09-07 16:14:42 565 /// 任务编号: 566 /// 567 /// bitImage 568 /// 返回值 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 /// 644 /// 功能描述:获取青海验证码结果 645 /// 作 者:huangzh 646 /// 创建日期:2016-09-08 17:20:13 647 /// 任务编号: 648 /// 649 /// bitImage 650 /// 返回值 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 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 /// 723 /// 功能描述:获取山西识别结果 724 /// 作 者:huangzh 725 /// 创建日期:2016-09-09 12:14:46 726 /// 任务编号: 727 /// 728 /// bitImage 729 /// 返回值 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 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 /// 802 /// 功能描述:获取黑龙江验证码结果 803 /// 作 者:huangzh 804 /// 创建日期:2016-09-09 16:46:32 805 /// 任务编号: 806 /// 807 /// bitImage 808 /// 返回值 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 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 /// 924 /// 功能描述:颜色去除 925 /// 作 者:huangzh 926 /// 创建日期:2016-09-01 15:28:08 927 /// 任务编号: 928 /// 929 /// bitImage 930 /// 返回值 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 lstCS = new List (); 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 /// 970 /// 功能描述:是否需要清除颜色 971 /// 作 者:huangzh 972 /// 创建日期:2016-09-01 15:27:28 973 /// 任务编号: 974 /// 975 /// c1 976 /// c2 977 /// intCha 978 /// 返回值 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 /// 990 /// 功能描述:灰度 991 /// 作 者:huangzh 992 /// 创建日期:2016-09-01 15:31:00 993 /// 任务编号: 994 /// 995 /// bitImage 996 /// 返回值 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 /// 1015 /// 功能描述:二值化 1016 /// 作 者:huangzh 1017 /// 创建日期:2016-09-01 15:33:28 1018 /// 任务编号: 1019 /// 1020 /// bitImage 1021 /// 返回值 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 /// 1035 /// 功能描述:颜色反转 1036 /// 作 者:huangzh 1037 /// 创建日期:2016-09-01 15:34:09 1038 /// 任务编号: 1039 /// 1040 /// image 1041 /// 返回值 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 /// 1066 /// 功能描述:去噪 1067 /// 作 者:huangzh 1068 /// 创建日期:2016-09-01 15:35:58 1069 /// 任务编号: 1070 /// 1071 /// bitImage 1072 /// 返回值 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 /// 1085 /// 功能描述:去毛边 1086 /// 作 者:huangzh 1087 /// 创建日期:2016-09-01 15:36:37 1088 /// 任务编号: 1089 /// 1090 /// bitImg 1091 /// 返回值 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 /// 1169 /// 功能描述:识别字符 1170 /// 作 者:huangzh 1171 /// 创建日期:2016-09-02 09:06:44 1172 /// 任务编号: 1173 /// 1174 /// lstImage 1175 /// 返回值 1176 private List<string> GetImageChar(List 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 /// 1193 /// 功能描述:获取连通 1194 /// 作 者:huangzh 1195 /// 创建日期:2016-09-01 15:50:18 1196 /// 任务编号: 1197 /// 1198 /// bitImage 1199 /// 最小连通域 1200 /// 合并检测 1201 /// 当blnIsCheckWidth=true时,单个字符最大宽度 1202 /// 是否旋转为最小宽度 1203 /// 1204 private List 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 int> lstBitNew = new Dictionary int>(); 1228 1229 Dictionary , int> lstedgePoints = new Dictionary
, int>(); 1230 1231 // process each blob 1232 foreach (Blob blob in blobs) 1233 { 1234 List
leftPoints = new List (); 1235 List rightPoints = new List (); 1236 List edgePoints = new List (); 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 hull = hullFinder.FindHull(edgePoints); 1247 1248 1249 1250 lstedgePoints.Add(hull, GetMinX(hull)); 1251 } 1252 1253 List > 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
item in dicLstPoints) 1297 { 1298 List 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 int> dic1Asc1 = (from d in lstBitNew 1310 orderby d.Value ascending 1311 select d).ToDictionary(k => k.Key, v => v.Value); 1312 1313 List lstImage = new List (); 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 /// 1330 /// 功能描述:识别单数字 1331 /// 作 者:huangzh 1332 /// 创建日期:2016-08-25 15:19:35 1333 /// 任务编号: 1334 /// 1335 /// bit 1336 /// lstNoChar 1337 /// 返回值 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 /// 1385 /// 功能描述:得到最小x 1386 /// 作 者:huangzh 1387 /// 创建日期:2016-09-01 15:42:22 1388 /// 任务编号: 1389 /// 1390 /// hull 1391 /// 返回值 1392 private int GetMinX(List 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 /// 1404 /// 功能描述:检查是否需要合并(目前仅检查x方向合并) 1405 /// 作 者:huangzh 1406 /// 创建日期:2016-09-01 15:42:56 1407 /// 任务编号: 1408 /// 1409 /// lst1 1410 /// lst2 1411 /// intMaxWidth 1412 /// 返回值 1413 private bool CheckIsHeBing(List lst1, List 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 /// 1451 /// 功能描述:根据坐标列表截图 1452 /// 作 者:huangzh 1453 /// 创建日期:2016-09-01 15:43:57 1454 /// 任务编号: 1455 /// 1456 /// hull 1457 /// bitImg 1458 /// _minX 1459 /// 返回值 1460 private Bitmap GetBitmapByListPoint(List 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 /// 1500 /// 功能描述:图片放到中心 1501 /// 作 者:huangzh 1502 /// 创建日期:2016-08-25 15:16:42 1503 /// 任务编号: 1504 /// 1505 /// bit 1506 /// w 1507 /// h 1508 /// 返回值 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 /// 1547 /// 功能描述:得到左右30度最窄的图片 1548 /// 作 者:huangzh 1549 /// 创建日期:2016-08-25 14:58:32 1550 /// 任务编号: 1551 /// 1552 /// bitImg 1553 /// 返回值 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 /// 1577 /// 功能描述:缩小图片 1578 /// 作 者:huangzh 1579 /// 创建日期:2016-08-25 14:55:46 1580 /// 任务编号: 1581 /// 1582 /// bit 1583 /// 返回值 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 /// 1594 /// 功能描述:旋转图片 1595 /// 作 者:huangzh 1596 /// 创建日期:2016-08-25 14:57:11 1597 /// 任务编号: 1598 /// 1599 /// b 1600 /// angle 1601 /// 返回值 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 /// 1613 /// 功能描述:获得最大最小xy 1614 /// 作 者:huangzh 1615 /// 创建日期:2016-08-25 14:55:56 1616 /// 任务编号: 1617 /// 1618 /// bit 1619 /// x1 1620 /// y1 1621 /// x2 1622 /// y2 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 /// 1715 /// 功能描述:细化图片 1716 /// 作 者:huangzh 1717 /// 创建日期:2016-09-01 16:07:13 1718 /// 任务编号: 1719 /// 1720 /// bitImage 1721 /// 返回值 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 /// 1732 /// 功能描述:膨胀 1733 /// 作 者:huangzh 1734 /// 创建日期:2016-09-01 16:08:21 1735 /// 任务编号: 1736 /// 1737 /// bitImage 1738 /// 返回值 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 /// 1752 /// 功能描述:获取图片投影分割 1753 /// 作 者:huangzh 1754 /// 创建日期:2016-09-09 12:20:54 1755 /// 任务编号: 1756 /// 1757 /// bitImage 1758 /// bitBase 1759 /// 1/2 1760 /// 返回值 1761 private List 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 lstRects = new List (); 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 lstBits = new Dictionary (); 1802 lstRects.ForEach(item => lstBits.Add(bit.Clone(item, System.Drawing.Imaging.PixelFormat.Format24bppRgb), item)); 1803 1804 //特殊处理,移除最后2个 1805 List 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 lstImages = new List (); 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 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 lstReturn = new List (); 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 /// 1869 /// 功能描述:图片排序 1870 /// 作 者:huangzh 1871 /// 创建日期:2016-09-08 17:44:21 1872 /// 任务编号: 1873 /// 1874 /// images 1875 /// 返回值 1876 private List 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 lstImage = new List (); 1909 foreach (var item in lstNew) 1910 { 1911 lstImage.Add(images[item.Key]); 1912 } 1913 return lstImage; 1914 } 1915 1916 /// 1917 /// 功能描述:恢复图片原色 1918 /// 作 者:huangzh 1919 /// 创建日期:2016-09-08 17:44:10 1920 /// 任务编号: 1921 /// 1922 /// bitImage 1923 /// bitSource 1924 /// rect 1925 /// intColorCount 1926 /// 返回值 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 /// 1953 /// 功能描述:颜色聚类分割图片 1954 /// 作 者:huangzh 1955 /// 创建日期:2016-09-08 17:43:58 1956 /// 任务编号: 1957 /// 1958 /// bit 1959 /// intNum 1960 /// intColorCount 1961 /// 返回值 1962 private Bitmap[] ImageJuLei(Bitmap bit, int intNum, int intColorCount) 1963 { 1964 Color[] colors; 1965 List _lst = new List (); 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 > lstColors = new List
>(); 1986 1987 foreach (var item in g) 1988 { 1989 List
lst = new List (); 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 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 }
备忘