在车牌识别系统中, 车牌字符能够正确分割的前提是车牌图像能够水平,以至于水平投影和垂直投影能够正常进行。如果车牌倾斜没有矫正,那么水平投影和垂直投影,甚至铆钉都无法正常处理。所以,当车辆信息中获取车牌的第一步,应该是检查倾斜角度,做倾斜矫正。
倾斜矫正,这里使用的算法:
1、倾斜角度检测: 霍夫变换
关于hough变换,可以参考前面图像处理博文:
http://blog.csdn.net/liujia2100/article/details/6989693 直线检测
http://blog.csdn.net/liujia2100/article/details/6989688 文本图像倾斜矫正
2、倾斜矫正: 图像旋转
下面详细说明倾斜矫正过程:
原车牌图像为(从车牌图像中,可以看到车牌有倾斜角度):
1、 获取车牌在车辆中的粗略位置(可以用多种方法,这里暂不分析)
2、提取车牌整体图片数据, 根据第一步结果,提取出,车牌在辆大体位置信息。
关于车牌定位,我使用两部,第一步粗略定位,然后做一些预处理,比如倾斜矫正,然后第二部才是精确定位,只提取车牌的位置信息图像
3、利用HSV颜色空间转换,获取车牌背景蓝色区域位置,获取车牌粗略信息图像后,由于车牌背景颜色与周围颜色有很明显的区别,这里采用HSV颜色过滤的方法,过滤绿色背景图像
4、水平膨胀, 水平膨胀的目的,是为了边缘检测,只要求检测边缘,尽量除去字符信息,也可以降低hough变换的运算量
5、水平差分运算,相当于 边缘检测,经过上面的处理后,才进行边缘检测
6、这个时候就可以利用hough变换检测直线了。
由于hough变换运算量十分大,所以,尽量减少图像中的白点,来降低计算量,因此前面才做了这么多步骤。
请看下图的红线,就是检测出来的角度,为177度(Hough代码在下面)。
7、利用旋转算法,旋转刚才粗略提取的车牌位置(旋转代码在下面),尽管旋转后的车牌有些锯齿,但是已经能够保证水平,就可以使用水平投影和垂直投影了
这是旋转后的车牌,有些锯齿出现,由于图像分辨率较低,就没有用差值运算。
8、精确提取车牌
9、正常分割字符
10、识别结果
由于正弦余弦运算,计算量比较大,这里进行一部分优化,就是正弦余弦计算用数组代替。
生成正弦,余弦数组的的代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> int main(void) { char buf[20]; int i; float p; float k; FILE *fcos; FILE *fsin; fcos = fopen(".\\cos.txt", "wb"); fsin = fopen(".\\sin.txt", "wb"); if(fcos == NULL || fsin == NULL) { printf("open error\n"); exit(-1); } i = 0; for(i = 0; i <= 180; i++) { k = 3.1415926 * i / 180.0; p = cos(k); if((i%16 == 0)) fwrite("\n",strlen("\n"),1,fcos); sprintf(buf,"%f, ", p); fwrite(buf,strlen(buf),1,fcos); } for(i = 0; i <= 180; i++) { k = 3.1415926 * i / 180.0; p = sin(k); if((i%16 == 0)) fwrite("\n",strlen("\n"),