没有合适的资源?快使用搜索试试~ 我知道了~
图形数字的识别算法
4星 · 超过85%的资源 需积分: 9 6 下载量 150 浏览量
2013-09-02
10:56:38
上传
评论 1
收藏 337KB DOCX 举报
温馨提示
试读
11页
图形验证码的识别算法,重点进行图片的灰度与切割
资源推荐
资源详情
资源评论
图形数字的识别算法车牌识别及验证码识别的一般思路 本文源自我之前花了 天时间做
的一个简单的车牌识别系统。那个项目,时间太紧,样本也有限,达不到对方要求的
识别率(主要对于车牌来说,,,, 等等太相似了。然后,汉字的识别难度也不
小),因此未被对方接受。在此放出,同时描述一下思路及算法。 全文分两部分,第一部
分讲车牌识别及普通验证码这一类识别的普通方法,第二部分讲对类似 验证码,
验证码这一类变态验证码的识别方法和思路。 一、车牌验证码识别的普通方法 车
牌、验证码识别的普通方法为: () 将图片灰度化与二值化 () 去噪,然后切割成一
个一个的字符 () 提取每一个字符的特征,生成特征矢量或特征矩阵 () 分类与学习。
将特征矢量或特征矩阵与样本库进行比对,挑选出相似的那类样本,将这类样本的值作为
输出结果。 下面借着代码,描述一下上述过程。因为更新 ,我以前以 储
存的代码访问不了,因此部分代码是用 !" 反编译过来的,望见谅。 () 图片的
灰度化与二值化 这样做的目的是将图片的每一个象素变成 或者 255,以便以计算。同时,
也可以去除部分噪音。 图片的灰度化与二值化的前提是 # 图片,如果不是,则需要首
先转换为 # 图片。 用代码说话,我的将图片灰度化的代码(算法是在网上搜到的):
$"#"! !%!! $""&'$"" ()*!+,$"*!-."*!''"/(
'''-0 -(1'-0 -((1'-0 -2(((3!/*$""-4"5+'+++(367
通过将图片灰度化,每一个象素就变成了一个 8 的灰度值。 然后是将灰度值二值化为
或 。一般的处理方法是设定一个区间,比如,9:,将9:之间的灰度全部变成
,其它的变成 。这里我采用的是网上广为流行的自适应二值化算法。 $"
#/ %!! "2*;!'2!##()*!!,$"#/!.<%<"/'#(3
*!=,#->!<3*!&,#-?+<!37"'*!,3@=311(ABBBB)C"'*!D,3D@
&3D11(BBBBBBBB)'#-!E='D(-F,!(BBBBBBBBBBBB)BBBBBBBBBBBBBBBB#-!E='
D$""-4"5+'===((3BBBBBBBBBBBB6%BBBBBBBBBBBB)7
#-!E='D$""-4"5+'((3ABBBBBBBBBBBB6CBBBBBBBB6BBBB66
#!%!! *!$"#/!.<%<"/'2!#+()*!3*!G37"/
%/3A*!!<%<"/,3C*!9:<%!,*H*!9=:3"',3@=31
1(BBBB)BBBBBBBB<%! ,3BBBB6*!+*,=3*!+=,3"',3@
'+->!<8(311(7BBBB)A"'*!D,3D@'+-?+<!8(3D11(CBBBBBBBB)*! *,
+-!E='D(-3BBBBBBBBBBBB<%!9 *:113' *F+=(BBBBBBBBBBBB)
+=, *3BBBBBBBBBBBB6' *@+*(7BBBBBBBBBBBB)ABBBBBBBBBBBBBBBB+*, *3CBBBBBBBBBBBB6
BBBBBBBB6BBBB6"/%/, %/,-3*!*,3"'G,3G@,=3G11(
BBBB)BBBBBBBB%/1,G0<%!9G:37BBBBBBBB*1,<%!9G:3ABBBB6C'*,,(BBBB)7
!/*737BBBB67"/=,8-37*!*,37"'G,3G@=3G11(7BBBB)
77BBBBBBBB*1,<%!9G:37A'*I,(7CBBBBBBBB)7*!*,*8*3A'*,,(A
)A!/*!<%<"/3ABBBBBBBBBBBB6ABBBBBBBBBBBB %/1,G0<%!9G:3A"/,
%/''"/(*(3A7"/,'%/8 %/(''"/(*(3AA"/%,''*0
*(0'8((0'8(3AC'%F=(ABBBBBBBBBBBB)CBBBBBBBBBBBBBBBB=,%3C
!<%<"/,G3CBBBBBBBBBBBB6CBBBBBBBB6CBBBB6C!/*!<%<"/3C76CACC灰
度化与二值化之前的图片:
灰度化与二值化之后的图片:
注:对于车牌识别来说,这个算法还不错。对于验证码识别,可能需要针对特定的网站设
计特殊的二值化算法,以过滤杂色。 (2) 去噪,然后切割成一个一个的字符 上面这张车
牌切割是比较简单的,从左到右扫描一下,碰见空大的,咔嚓一刀,就解决了。但有一些
车牌,比如这张:
BBBB简单的扫描就解决不了。因此需要一个比较通用的去噪和切割算法。这里我采用的是比
较朴素的方法: 将上面的图片看成是一个平面。将图片向水平方向投影,这样有字的地
方的投影值就高,没字的地方投影得到的值就低。这样会得到一根曲线,像一个又一个山
头。下面是我手画示意图:
然后,用一根扫描线(上图中的 S)从下向上扫描。这个扫描线会与图中曲线存在交点,
这些交点会将山头分割成一个又一个区域。车牌图片一般是 7 个字符,因此,当扫描线将
山头分割成七个区域时停止。然后根据这七个区域向水平线的投影的坐标就可以将图片中
的七个字符分割出来。 但是,现实是复杂的。比如,“川”字,它的水平投影是三个山头。
按上面这种扫描方法会将它切开。因此,对于上面的切割,需要加上约束条件:每个山头
有一个中心线,山头与山头的中心线的距离必需在某一个值之上,否则,则需要将这两个
山头进行合并。加上这个约束之后,便可以有效的切割了。 以上是水平投影。然后还需要
做垂直投影与切割。这里的垂直投影与切割就一个山头,因此好处理一些。 切割结果如下:
水平投影及切割代码: Code 1 public static IList<Bitmap> Split(Bitmap map,
int count) 2 { 3 if (count <= 0) 4 { 5 throw new
ArgumentOutOfRangeException("Count 必须大于 0."); 6 } 7
IList<Bitmap> resultList = new List<Bitmap>(); 8 int x = map.Width; 9 int y
= map.Height; 10 int splitBitmapMinWidth = 4; 11 int[] xNormal = new int[x];
12 for (int i = 0; i < x; i++) 13 { 14 for (int j = 0; j < y; j++) 15 { 16 if
(map.GetPixel(i, j).R == CharGrayValue) 17 { 18 xNormal+
+; 19 } 20 } 21 } 22 Pair pair = new Pair(); 23 for (int i = 0;
i < y; i++) 24 { 25 IList<Pair> pairList = new List<Pair>(count + 1);
26 for (int j = 0; j < x; j++) 27 { 28 if (xNormal[j] >= i) 29 { 30 if
((j == (x - 1)) && (pair.Status == PairStatus.Start)) 31 { 32
pair.End = j; 33 pair.Status = PairStatus.End; 34 if ((pair.End -
pair.Start) >= splitBitmapMinWidth) 35 { 36
pairList.Add(pair); 37 } 38 pair = new Pair(); 39
} 40 else if (pair.Status == PairStatus.JustCreated) 41 { 42
pair.Start = j; 43 pair.Status = PairStatus.Start; 44 } 45
} 46 else if (pair.Status == PairStatus.Start) 47 { 48
pair.End = j; 49 pair.Status = PairStatus.End; 50 if ((pair.End -
pair.Start) >= splitBitmapMinWidth) 51 { 52
pairList.Add(pair); 53 } 54 pair = new Pair(); 55 }
56 if (pairList.Count > count) 57 { 58 break; 59 } 60 } 61
if (pairList.Count == count) 62 { 63 foreach (Pair p in pairList) 64
{ 65 if (p.Width < (map.Width / 10)) 66 { 67 int width = (map.Width
/ 10) - p.Width; 68 p.Start = Math.Max(0, p.Start - (width / 2)); 69
p.End = Math.Min((int) (p.End + (width / 2)), (int) (map.Width - 1)); 70
} 71 } 72 foreach (Pair p in pairList) 73 { 74 int newMapWidth
= (p.End - p.Start) + 1; 75 Bitmap newMap = new
Bitmap(newMapWidth, y); 76 for (int ni = p.Start; ni <= p.End; ni++) 77
{ 78 for (int nj = 0; nj < y; nj++) 79 { 80
newMap.SetPixel(ni - p.Start, nj, map.GetPixel(ni, nj)); 81 } 82
} 83 resultList.Add(newMap); 84 } 85 return resultList; 86
} 87 } 88 return resultList; 89 } 90 代码中的 E代表扫描线与曲线的一对交点:
$"#! %%E)#/ E'(3#/ *!$<E=$"/*!)BB+!3%!36
#/ *!$<E=J*%!&)+!367#/ *!K*)+!3BB%!36A#/ *!!!
)BB+!3BB%!36C#/ 2!#$"*!-E!!/%!!/%)BB+!3BB%!36#/ *!>!<)
+!366PairStatus 代表 Pair 的状态。具体哪个状态是什么意义,我已经忘了。
$"#!*/E!!/%)BBBBL/%!$!BBBB!!BBBBK*76A以上这一段
代码写的很辛苦,因为要处理很多特殊情况。那个 E!!/%也是为处理特殊情况引进的。
垂直投影与切割的代码简单一些,不贴了,见附后的 的 2!#$"*!-.?+<! 方法。
以上用到的是朴素的去噪与切割方法。有些图片,尤其是验证码图片,需要特别的去噪处理。
具体操作方法就是,打开 $=+(<!!#HHH- "#"D !- "M2+#< %
=+-%#=),或者 E*!-!,用上面的那些图片处理方法,看看能否有效去噪。记住自
己的操作步骤,然后翻他们的源代码,将其中的算法提取出来。还有什么细化啊,滤波啊,这
些处理可以提高图片的质量。具体可参考 .M 的代码或图像处理书籍。 () 提取每一个字
符的特征,生成特征矢量或特征矩阵 将切割出来的字符,分割成一个一个的小块,比如
×,×,或 ×,或 ×C,然后统计一下每小块的值为 的像素数量,这样得到一个
矩阵 N,或者将这个矩阵简化为矢量 。 通过以上 步,就可以将一个车牌中的字符数值化为
剩余10页未读,继续阅读
资源评论
- orcmylove2014-01-06代码很普通,网上的免费资源。用处不大
Iceberg-X
- 粉丝: 124
- 资源: 21
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功