最近在复习OPENCV的知识,学习caffe的深度神经网络,正好想起以前做过的车牌识别项目,可以拿出来研究下
以前的环境是VS2013和OpenCV2.4.9,感觉OpenCV2.4.9是个经典版本啊!不过要使用caffe模型的话,还是要最新的OpenCV3.3更合适!
一、车牌图片库
以前也是网上下的,如果找不到的小伙伴可以从我这儿下: 链接:http://pan.baidu.com/s/1hrQF92G 密码:43jl
里面有数字 “0-9”,字母“A-Z”的训练图片各50张。
测试车牌图片当时是从他人得到已经定位到车牌的图片,类似如下:
目标当然就是对这些车牌图片进行预处理,单字符分割,单字符识别!
二、预处理
图像的预处理做来做去就是滤波去噪,光照补偿,灰度/二值化,形态学基本操作等等。这些图片都是自然场景得到所以基本的去噪操作可以做一下,然后为了单字符分割,灰度化和形态学可以结合效果调整。
光照补偿其实一直是个问题,大多数有直方图均衡化,亮度参考白,利用公式统计补偿图片。这方面也可以结合图像增强方法来做!笔者当时觉得前两者对大多数场景已经适用。
二值化可以使用 cv::threshold函数,如:
1 Mat t1=imread("2.png",1);2 cvtColor(inimg, gimg, CV_BGR2GRAY);3 threshold(gimg, gimg, 100, 255, CV_THRESH_BINARY);4 imshow("gimg", gimg);
第一行imread(),由于flag设为1所以读的是彩图,采用cvtColor函数转化为灰度图。如果你读入就是灰度图可以省略第二行代码。第三行就是转化为二值化函数,阈值100可以修改,在灰度对比不明显是有必要!
效果:
如果预处理做的好,某些小的白色区域是可以去掉的。这个效果也可以识别。
同时可以发现车牌外围被一圈白色包围,如若能去除外围白色,对于单字符分割更有益。但其实通过寻找列像素之间的变化,白色区域只是影响了阈值不会对结果太大影响。
想要去除白色外圈可以参考:http://blog.csdn.net/u011630458/article/details/43733057
如果想要使用直方图均衡化,OPENCV有equalizeHist(inputmat, outputmat);非常方便,但是效果不好。
使用直方图均衡化后的上述车牌二值化图片:
效果更惨烈了,因为均衡化就是让直方图的像素分布更加平衡,上图黑色多,均衡之后自然白色多了,反而不好!
二、单字符分割
单字符分割主要策略就是检测列像素的总和变化,因为没有字符的区域基本是黑色,像素值低;有字符的区域白色较多,列像素和就变大了!
列像素变化的阈值是个问题,看到很多博客是固定的阈值进行检测,除非你处理后的二值化图像非常完美,不然有的图片混入了白色区域就会分割错误!而且对于得到分割宽度如果太小也应该使用策略进行剔除,没有一定的宽度限制分割后的图片可能是很多个窄窄的小区域。。。
1 int getColSum(Mat& bimg, intcol)2 {3 int height =bimg.rows;4 int sum = 0;5 for (int i = 1; i < height; i++)6 {7 sum += bimg.at(i, col);8 }9 cout << sum <
13 in