车牌、验证码识别的普通方法为:
1.将图片灰度化与二值化。
2.去噪,然后切割成一个一个的字符。
3.提取每一个字符的特征,生成特征矢量或特征矩阵。
4.分类与学习。将特征矢量或特征矩阵与样本库进行比对,挑选出相似的那类样本,将这类样本的值作为输出结果。
下面借着代码,描述一下上述过程。
1. 图片的灰度化与二值化
这样做的目的是将图片的每一个象素变成0或者255,以便以计算。同时,也可以去除部分噪音。图片的灰度化与二值化的前提是bmp图片,如果不是,则需要首先转换为bmp图片。
1 protected static Color Gray(Color c) 2 { 3 int rgb = Convert.ToInt32((double) (((0.3 * c.R) + (0.59 * c.G)) + (0.11 * c.B))); 4 return Color.FromArgb(rgb, rgb, rgb); 5 } 6 |
通过将图片灰度化,每一个象素就变成了一个
0-255
的灰度值。
然后是将灰度值二值化为 0 或255。一般的处理方法是设定一个区间,比如,[a,b],将[a,b]之间的灰度全部变成255,其它的变成0。这里我采用的是网上广为流行的自适应二值化算法。
1 public static void Binarizate(Bitmap map) 2 { 3 int tv = ComputeThresholdValue(map); 4 int x = map.Width; 5 int y = map.Height; 6 for (int i = 0; i < x; i++) 7 { 8 for (int j = 0; j < y; j++) 9 { 10 if (map.GetPixel(i, j).R >= tv) 11 { 12 map.SetPixel(i, j, Color.FromArgb(0xff, 0xff, 0xff)); 13 } 14 else 15 { 16 map.SetPixel(i, j, Color.FromArgb(0, 0, 0)); 17 } 18 } 19 } 20 } 21 22 private static int ComputeThresholdValue(Bitmap img) 23 { 24 int i; 25 int k; 26 double csum; 27 int thresholdValue = 1; 28 int[] ihist = new int[0x100]; 29 for (i = 0; i < 0x100; i++) 30 { 31 ihist[i] = 0; 32 } 33 int gmin = 0xff; 34 int gmax = 0; 35 for (i = 1; i < (img.Width - 1); i++) 36 { 37 for (int j = 1; j < (img.Height - 1); j++) 38 { 39 int cn = img.GetPixel(i, j).R; 40 ihist[cn]++; 41 if (cn > gmax) 42 { 43 gmax = cn; 44 } 45 if (cn < gmin) 46 { 47 gmin = cn; 48 } 49 } 50 } 51 double sum = csum = 0.0; 52 int n = 0; 53 for (k = 0; k <= 0xff; k++) 54 { 55 sum += k * ihist[k]; 56 n += ihist[k]; 57 } 58 if (n == 0) 59 { 60 return 60; 61 } 62 double fmax = -1.0; 63 int n1 = 0; 64 for (k = 0; k < 0xff; k++) 65 { 66 n1 += ihist[k]; 67 if (n1 != 0) 68 { 69 int n2 = n - n1; 70 if (n2 == 0) 71 { 72 return thresholdValue; 73 } 74 csum += k * ihist[k]; 75 double m1 = csum / ((double) n1); 76 double m2 = (sum - csum) / ((double) n2); 77 double sb = ((n1 * n2) * (m1 - m2)) * (m1 - m2); 78 if (sb > fmax) 79 { 80 fmax = sb; 81 thresholdValue = k; 82 } 83 } 84 } 85 return thresholdValue; 86 } 87
|
灰度化与二值化之前的图片:
灰度化与二值化之后的图片:
注:对于车牌识别来说,这个算法还不错。对于验证码识别,可能需要针对特定的网站设计特殊的二值化算法,以过滤杂色。
2.去噪,然后切割成一个一个的字符
上面这张车牌切割是比较简单的,从左到右扫描一下,碰见空大的,咔嚓一刀,就解决了。但有一些车牌,比如这张:
简单的扫描就解决不了。因此需要一个比较通用的去噪和切割算法。这里我采用的是比较朴素的方法:将上面的图片看成是一个平面。将图片向水平方向投影,这样有字的地方的投影值就高,没字的地方投影得到的值就低。
然后,用一根扫描线从下向上扫描。这个扫描线会与图中曲线存在交点,这些交点会将山头分割成一个又一个区域。车牌图片一般是7个字符,因此,当扫描线将山头分割成七个区域时停止。然后根据这七个区域向水平线的投影的坐标就可以将图片中的七个字符分割出来。
但是,现实是复杂的。比如,“川”字,它的水平投影是三个山头。按上面这种扫描方法会将它切开。因此,对于上面的切割,需要加上约束条件:每个山头有一个中心线,山头与山头的中心线的距离必需在某一个值之上,否则,则需要将这两个山头进行合并。加上这个约束之后,便可以有效的切割了。
以上是水平投影。然后还需要做垂直投影与切割。这里的垂直投影与切割就一个山头,因此好处理一些。
水平投影及切割代码:
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[i]++; 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;
|
代码中的
Pair,
代表扫描线与曲线的一对交点:
1 private class Pair 2 { 3 public Pair(); 4 public int CharPixelCount { get; set; } 5 public int CharPixelXDensity { get; } 6 public int End { get; set; } 7 public int Start { get; set; } 8 public BitmapConverter.PairStatus Status { get; set; } 9 public int Width { get; } 10 }
|
PairStatus代表Pair的状态。
1 private enum PairStatus 2 { 3 JustCreated, 4 Start, 5 End 6 }
|
3.
提取每一个字符的特征,生成特征矢量或特征矩阵
将切割出来的字符,分割成一个一个的小块,比如3×3,5×5,或3×5,或10×8,然后统计一下每小块的值为255的像素数量,这样得到一个矩阵M,或者将这个矩阵简化为矢量V
通过以上3步,就可以将一个车牌中的字符数值化为矢量了。
4.分类与学习。将特征矢量或特征矩阵与样本库进行比对,挑选出相似的那类样本,将这类样本的值作为输出结果。
分享到:
相关推荐
车牌识别 验证码识别
C#字符验证识别,验证码、车牌号、身份证号字符拆分源码
Java ORC验证码和文章、车牌智能识别资料和工程代码Java ORC验证码和文章、车牌智能识别资料和工程代码Java ORC验证码和文章、车牌智能识别资料和工程代码Java ORC验证码和文章、车牌智能识别资料和工程代码Java ORC...
引言:本文主要对于车牌识别系统来说, D,0, O, I, 1等等太相似了。然后,汉字的识别难度也不小,因此很难达到分辨率在95%以上,但是可以作为图像处理技术的小论文,在此放出,同时描述一下思路及算法。
全文分两部分,第一部分讲车牌识别及普通验证码这一类识别的普通方法,第二部分讲对类似QQ验证码,Gmail验证码这一类变态验证码的识别方法和思路。
老外用纯C#写的一个OCR项目,带培训和测试,使用神经网络算法,而且没有使用第三方库,对研究验证码识别,图象识别,车牌识别等图象识别很有参考价值,代码完整,已在VS2010调试通过. 基本使用说明: 1、点“Load ...
经典算法 全文分两部分,第一部分讲车牌识别及普通验证码这一类识别的普通方法,第二部分讲对类似QQ验证码,Gmail验证码这一类变态验证码的识别方法和思路。
Keras-master python基于BI-LSTM+CRF的中文命名实体识别 PytorchChinsesNER-pytorch-master Python_毕业设计基于Opencv的车牌识别系统VLPR-master python 基于torch进行验证码识别,识别率达94%captcha_identify....
该文件详细了验证码的识别过程,对专业人士很有帮助,值得收藏
车牌定位是车牌识别系统的重要组成部分。针对车牌目标所在区域梯度变换频繁的特点,利用高通滤波保留梯度变换频繁区域,形态学处理后,将相邻区域进行合并以确定车牌的候选区域。再结合车牌的几何特征与区域目标背景...
图像识别代码,可以识别数字和字母,原理简单,对于图像清晰的图片识别率很高,用于识别验证码和交通车牌
老外写的一个OCR项目,带培训和测试,使用神经网络算法,而且没有使用第三方库,对研究验证码识别,图象识别,车牌识别等图象识别很有参考价值,代码完整,已在VS2010调试通过. 基本使用说明: 1、点“Load Training Set”...
【Python应用实战案例】python opencv+pytesseract 验证码识别
网络上收集的49篇验证码识别、车牌照识别的论文
基于端到端的深度学习的车牌、验证码、文档等字符识别,可以基于此进行样本生成和模型训练。
字符识别练习字符拆分(验证码、车牌号、身份证号等)
用matlab实现的csdn验证码识别。供大家参考。。。。。比较初级
3.1.1 车牌、交通标志识别(新能源、国内外、复杂环境下车牌) 3.1.2 发票、身份证、银行卡识别 3.1.3 人脸类别和表情识别 3.1.4 打靶识别 3.1.5 字符识别(字母、数字、手写体、汉字、验证码) 3.1.6 病灶识别...