2015年5月20日
C#实现验证码中粘连字符分割(五)
在《C#实现验证码中粘连字符分割(四)》一文中我们说到了找含粘连字符验证码图片中谷点的方法,一般情况下,找到的谷点均大于我们需要分割的字符数。以我所收集的10张验证码图片为样本,用上一篇文章提到的寻找谷点的方法均找到的谷点的数量均大于待分割字符的数量,因此我们必须过滤掉一部分无效谷点。
写文章时贴代码可能有所遗漏,这里提供完整的工程下载链接:链接: http://pan.baidu.com/s/1sjJoWKt 密码: xdeb
滤除原则需要因图片而异,图片中待分割的字符数,每个字符所占据的大致宽度,谷点与边界的距离,谷点与谷点的距离都是我们需要考虑的因素。
我目前采用的初步的过滤方法为:
(1) 与左右两边的距离小于1/8总宽度的谷点滤除。
(2) 相邻两个谷点间距小于3个像素的仅保留一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
/// <summary> ///在四字符的前提下对谷点进行过滤,过滤原则: ///1.与左右边界间隔距离小于1/8字符宽度的谷点淘汰; ///2.若两个谷点之间的宽度差距小于3个像素点,则靠左侧的像素点被淘汰 /// </summary> /// <param name="valleyCollection">谷点列表集合</param> /// <param name="Boundary">图片中字符所在区域的边界</param> /// <returns>过滤后的谷点列表</returns> public static ImgValley filterImgValley(ImgValley valleyCollection, ImgBoundary Boundary) { ArrayList filterUpValley = valleyCollection.upValley; ArrayList filterDownValley = valleyCollection.downValley; int upCount = filterUpValley.Count; int downCount = filterDownValley.Count; int leftWidth = Boundary.widthMin; int rightWidth = Boundary.widthMax; int filterWidth = (rightWidth - leftWidth) >> 3; int tmpWidth0 = 0; int tmpWidth1 = 0; // ArrayList removeList = new ArrayList(); PixPos pos0 = new PixPos(); PixPos pos1 = new PixPos(); for (int i = 0; i < upCount; i++) { pos0 = (PixPos)filterUpValley[i]; if (i < (upCount - 1)) { pos1 = (PixPos)filterUpValley[i + 1]; } tmpWidth0 = pos0.widthPos; tmpWidth1 = pos1.widthPos; if ((System.Math.Abs(tmpWidth1 - tmpWidth0) < 3) || ((tmpWidth0 - leftWidth) < filterWidth) || ((rightWidth - tmpWidth0) < filterWidth)) { filterUpValley.RemoveAt(i); upCount--; } } /* for (int i = 0; i < downCount; i++) { pos0 = (PixPos)filterDownValley[i]; if (i < (upCount - 1)) { pos1 = (PixPos)filterDownValley[i + 1]; } tmpWidth0 = pos0.widthPos; tmpWidth1 = pos1.widthPos; if ((System.Math.Abs(tmpWidth1 - tmpWidth0) < 3) || ((tmpWidth0 - leftWidth) < filterWidth) || ((rightWidth - tmpWidth0) < filterWidth)) { // removeList.Add(i); filterDownValley.RemoveAt(i); upCount--; } } */ filterDownValley.TrimToSize(); ImgValley filterValley = new ImgValley(); filterValley.upValley = filterUpValley; filterValley.downValley = filterDownValley; return filterValley; } |
目前根据此方案滤除后的谷点去分割图像,10个样本仅完全成功分割了1个,其他图片分割出的字符或多或少有一些缺失或者多余笔画,因此谷点查找与谷点滤除方案有待改进。