天天看点

《Mastering Opencv ...读书笔记系列》车牌识别(II)

   继上一篇文章后,现在要做的就是从车牌图像上使用optical character recognition算法将字符提取出来。对于每一块被检测的车牌,使用带监督的神经网络机器学习算法来识别字符。

本文内容:

1.字符分割 

2.神经网络训练方法

3.使用神经网络预测字符

一、字符分割【OCR Segment】

在使用神经网络对每个字符进行预测之前,我们必须从车牌图像中扣取改字符图片,因此有如下步骤:

本文的输入图像为上一篇文章的车牌:

《Mastering Opencv ...读书笔记系列》车牌识别(II)

a.二值化车牌

《Mastering Opencv ...读书笔记系列》车牌识别(II)

b.求轮廓

《Mastering Opencv ...读书笔记系列》车牌识别(II)

c.求最小外接矩形

《Mastering Opencv ...读书笔记系列》车牌识别(II)

d.用纵横比及面积,筛选外接矩形

《Mastering Opencv ...读书笔记系列》车牌识别(II)

e.调整统一矩形大小并保存每个字符的图片【注意:分割得到顺序和车牌字符顺序无关,可能不同】

《Mastering Opencv ...读书笔记系列》车牌识别(II)

代码:

图片显示可以自己边注释边显示,另外提前给出了第二部分的累计水平垂直直方图和低分辨率采样的方法,并把这种特征的图像保存下来了。

二、神经网络训练

1.多层感知机简介:

多层感知机结构:【隐层数量为1层或多层,实际上自从引入了深度学习后,才有多层】

《Mastering Opencv ...读书笔记系列》车牌识别(II)

其中,每个神经元结构如下:

《Mastering Opencv ...读书笔记系列》车牌识别(II)

每个神经元都是相似的且每个神经元都有自己的判定边界,有多个输入和多个输出。不同权重的输入结合激励函数得到不同的输出。常见的激励函数有S型、高斯型、上图的hadrlim型。单层的单个神经元可以将输入向量分为两类,而一个有S个神经元的感知机,可以将输入向量分为2^S类

2.获取训练数据

和上一篇训练SVM所使用的特征不同,现在使用每个字符的累计直方图和低分辨率采样图像构成的高维向量作为训练神经网络的特征。训练的样本矩阵P为N*M,其中N(行)代表各个样本图片的融合特征,M(列)为类别。从书中给的已经训练好的orc.xml看,N有675行,M有30列,30列代表西班牙车牌有30种字符0-9和20个英文字母组成,675是这么来的,比如字符0有35张图片样本,对应产生35行高维向量,字符1有40张样本图片,对应产生40行高维向量,然后按照不同分辨率5*5、10*10、15*15、20*20采样【书中ocr.xml只有675,只采用5*5分辨率】。矩阵P实际上是对每一种高维向量的类别标注:

《Mastering Opencv ...读书笔记系列》车牌识别(II)

  在Opencv中使用多层感知机需要配置training data矩阵、classes矩阵、隐层神经元数量。其中,训练数据矩阵和列别标识矩阵均从ocr.xml文件获取【下文会介绍】,这里只采用单隐层,包含10个神经元,输入层为675行,输出层为30行。

  计算ocr.xml文件具体步骤:

a.将上一步分割得到的每个字符进行人工分类【可放在不同目录下】,比如最终字符0有35张图片,字符a有30张图片并定义数组【这些数字之和为675】:

b.读取某个字符目录下的一张图片,提取累计直方图特征和不同低分辨率图像,具体如下:

(1)统计水平、垂直方向直方图,比如水平直方图,扫描图像每一行,统计每行非零元素的个数,这样就构成1*row矩阵,然后用该矩阵的最大值,规范化该矩阵。

(2)使用resize函数,按照不同分辨率得到图像矩阵

(3)将垂直直方图,水平直方图,低分辨率图像【按行读取】,都存进一个1*(vcol+hcol+h*w)的矩阵

(4)将上述矩阵连同标记一起写入xml文件中

累计直方图及低分辨率图像效果如下:【左下角为字符图像原始大小20*20,由上角为低分辨率采样后放大的图像100*100,右下角为水平直方图,左上角为垂直直方图】

《Mastering Opencv ...读书笔记系列》车牌识别(II)

具体训练代码为:

三、使用神经网络检测字符

a.读取一张车牌图像

b.配置神经网络参数,并使用xml文件训练神经网络【参数配置上述已经说过了】

c.提取该车牌图像的累计直方图和低分辨率图像特征矩阵

d.将该特征矩阵作为神经网络输入,经网络计算,得到预测结果【字符索引】

e.按照每个字符图像的相对位置,进行字符重新排序

f.得到最终字符【和书中不同的是,我的输入图像是车牌而不是整幅图像,因此绝对坐标是不同的,但字符间的相对位置还是对的,只是不能在车牌照片上显示数字而已,我直接答应到控制台上】

《Mastering Opencv ...读书笔记系列》车牌识别(II)

具体代码:

又用到了车牌类,这里面有车牌字符相对位置调整的函数,都给出来吧:

Plate.h:

Plate.cpp:

主要处理的函数:

这边运行时间略长,大概10s以下吧。这就是android不能做太多图像处理的原因,运行速度不给力啊。

上上后面做的评估是对隐层神经元数量和不同分辨率的一种统计,没多大花头,以后要用再看吧。而且车牌识别已经做烂了,没什么动力了~~

好吧,下一篇尝试将车牌检测与识别都移植到android上试试。

继续阅读