if(flag==0)

{

pos= i;

while(VCount[i]==0){i++;xx++;}

if(xx < (wid/4))

{

str.Format("xx=%d wid/4=%d i=%dposi[k-1]=%d",xx,wid/4,i,posi[k-1]);

MessageBox("汉字有分割"+str);

xx=0;

while(VCount[i]!=0){i++;xx++;}

if(xx<=8)

{

xx= 0;

while(VCount[i]==0){i++;xx++;}

if(xx

while(VCount[i]!=0 && i

}

}

else

{

i= pos;

}

}

flag=1;

if(i>= lWidth)

{

posi[k++]=i-1;

}

else

{

posi[k++]=i+1;

}

//如果是字符第二个和第三个字符中间的点,去除。如果是1,宽度增加

if(posi[k-1]-posi[k-2]<=wid)

{

if(i<=(lWidth/8*3))

{

intx = posi[k-1]-posi[k-2]; k=k-2;

str.Format("%d%d %d %d",x,wid,i,BottomLine-TopLine);

}

else

{

posi[k-1]= posi[k-1]+wid/3;

posi[k-2]= posi[k-2]-wid/3;

}

}

if(k>=14)

{

success= 1;

break;

}

}

if(success== 0)

{

MessageBox("字符分隔出错,程序结束识别过程!");

}

3.归一化处理

字符分割的好坏关系到后面归一化处理关键。如果字符分割不成立,归一化处理过程也就不能成功。刚开始实验的时候,我先进行的细化处理,然后再进行归一化处理,但是归一化处理后有,字符基本失去了原来的骨架结构,所以我这里先进行归一化处理。

所谓归一化处理,就是为了在分割字符时,字符大小不相同,所以要将字符归一化为25×50像素大小的图像。图像x轴缩放比率为 ,y轴缩放比率为 ,原图像宽度和高度为lWidth,lHeight[12]。缩放比率由公式:

在放大或缩小图像过程中,产生的像素可能在原图中不能找到相应的像素点。这样就必须采用插值处理的方法。一般插值处理的方法有两种,一种是直接赋值为与它最相邻的像素值,另一种则通过插值算法来计算相应像素值。第一种方法计算过程较简单效率高,但是效果不是很好,比如有时候会出现马赛克现象;所以,这里采用第二种方法,虽然预算量有点复杂,但是最后归一化后的字符不会失真。对后面做细化处理过程做好了铺垫。通过实验得出,采用双线性插值法比最近邻插值法效果好,所以本文中归一化采用双线性插值法。

图4-14 上面为原图像二值化后的结果,下面图像为归一化后的结果

归一化关键代码如下:

//针对图像每行进行操作

for(i= 0; i < NewHeight; i++)

{

//针对图像每列进行操作

for(j= 0; j < NewWidth; j++)

{

//指向新DIB第i行,第j个象素的指针

//注意此处宽度和高度是新DIB的宽度和高度

lpDst = (char*)lpNewDIBBits + NewLineBytes * (NewHeight - 1 - i) + j;

x= j / fXZoomRatio;

y= i / fYZoomRatio;

if(tag)

{ //tag=1,则执行以下的最近邻插值代码

i0= (LONG) (y + 0.5);

j0= (LONG) (x + 0.5);

//判断是否在源图范围内

if((j0 >= 0) && (j0 < Width) && (i0 >= 0) && (i0< Height))

{

//指向源DIB第i0行,第j0个象素的指针

lpSrc = (char*)lpTempDIBBits + LineBytes * (Height - 1 - i0) + j0;

*lpDst= *lpSrc;

}

else

{

//对于源图中没有的象素,直接赋值为255

*((unsigned char*)lpDst) = 255;

}

}

else

{//否则,执行下面的双线性插值代码

doublem = x - LONG(x);//X方向的小数部分

doublen = y - LONG(y);//Y方向的小数部分

unsignedchar rd, ld, lu, ru;//r:右;l:左;d:下;u:上

unsignedchar pix;

ld= *((char *)lpTempDIBBits + LineBytes * (Height - 1 - LONG(y)) + LONG(x));//左下角点的像素值

rd= *((char *)lpTempDIBBits + LineBytes * (Height - 1 - LONG(y)) + LONG(x) +1);// 右下角点的像素值

lu= *((char *)lpTempDIBBits + LineBytes * (Height - 1 - LONG(y) - 1) +LONG(x));// 左上角点的像素值

ru= *((char *)lpTempDIBBits + LineBytes * (Height - 1 - LONG(y) - 1) + LONG(x) +1);// 右上角点的像素值

pix= (1 - m) * (1 - n) * ld + (1 - m) * n * lu + m * n * ru + m * (1 - n) * rd;//双线性插值,得到变换后的像素

*((unsigned char*)lpDst) = pix;//将像素值赋给目的图片

}

}

}

4.细化处理

对图像的喜欢过程实际是求图像骨架的过程。骨架是二维二值目标的重要描述,它指图像中央的骨骼部分,是描述图像几何及拓扑性质的重要特征之一。细化算法有很多。按照迭代方法,分为两类,一类是非迭代过程,一类是迭代过程。非迭代算法有基于距离变换的方法等。迭代方法是通过重复删除像素边缘,直到得到单独像素宽度的图像为止。现在用的比较多的细化算法有Hilditch、Pavlidis、Rosenfeld细化算法和索引表细化算法等[13]。下面主要介绍这四种算法。

Hilditch、Pavlidis、Rosenfeld细化算法:这类算法则是在程序中直接运算,根据运算结果来判定是否可以删除点的算法,差别在于不同算法的判定条件不同。

其中Hilditch算法比较适用于二值图像,是用的比较普遍的细化算法,在本文中我用了该算法后发现会有马赛克效果,所以本文中没有引用该算法; Pavlidis算法用位运算进行特定模式的匹配,所得的骨架是8连接的,使用于0-1二值图像 ;Rosenfeld算法是一种并行细化方法,所得的骨架形态是8-连接的,使用于0-1二值图像 。 后两种算法的效果要更好一些,但是处理某些图像时效果一般,第一种算法适用性强一些[13]。

索引表细化算法:经过预处理后得到待细化的图像是0、1二值图像。像素值为1的是需要细化的部分,像素值为0的是背景区域。基于索引表的算法就是依据一定的判断依据,产生一个表,然后根据要细化的点的八个邻域的情况进行匹配,若表中元素是1,若表中元素是1,则删除该点(改为背景),若是0则保留。因为一个像素的8个邻域共有256种可能情况,因此,索引表的大小一般为256种。

车牌图像进行预处理后,细化处理是关系到后面能否正确提取字符特征值的关键,所以本文中在比较了几种细化方法后,使用Rosenfeld骨架细化的方法,细化处理后可以得到图像中字符的基本骨架,不会破坏原来的连通性。

Rosenfeld细化过程主要是保持原来图像的连通性

通过归一化 后,再将图像进行细化,基本保存了字符特征的骨架特征。所以后面就是要进行的字符特征提取操作。Rosenfeld效果如下所示:

4-19大小归一化后再细化的图像

5.字符特征提取

字符特征提取的好坏,直接影响字符识别的结果。字符特征提取是一个字符识别过程必不可少的过程。目前,字符特征提取的方法很多,比如:基于网格像素统计方法[5],基于笔画,轮廓,骨架特征等。我之前做了基于网格像素统计的方法,通过实验,发现识别能力比较差,不能达到预想的结果。

针对上面的结果,我参考何兆成等人的方法,在字符细化后的基础上,通过统计字符笔画斜率特征,字符侧面深度等特征作为字符提取的特征,得到22个特征值。具体统计方法如下:

(1)基于笔画斜率的累计特征提取

字符最具代表性的特征是笔画,不同的字符有不同的笔画数量,形态,长度等,所以可将笔画的斜率累计值作为特征进行特征值提取。笔画斜率有正斜率,负斜率,零斜率三部分,分别统计字符零斜率,正斜率,负斜率的累加和。斜率的统计过程,例如从字符左边扫描,当前的扫描点为 ,下一个扫描点为为 。斜率K值计算如下:

通过上面的过程,从字符左侧开始计算斜率特征,可以得到3个特征。我这里从字符左右上下四个方向统计斜率特征可以得到12个特征值。

(2)拐点幅度累计特征提取

在字符中字符的拐点含有丰富的特征。所以统计拐点幅度特征累计和,可以得到4个特征值。拐点幅度特征 计算如下:

(3)字符轮廓深度特征提取

不同的字符在轮廓上有着明显差异。比如“S”和“C”。如下图中的“S”字符,从右侧扫描深度的时候有着有很多的凹凸信息。而字符“C”从右侧扫描的过程中,字符的中间凹陷比较明显。所以通过扫描字符四个方向的轮廓深度,也能得到4个轮廓特征值。

(4)字符跳跃点统计

由于字符“1”和“B”从左侧扫描过程中基本上没有区别。所以,为了更准确些。我这里通过统计字符水平扫描跳跃点和垂直扫描字符跳跃点来区分。很明显,字符“1”和字符“B”水平和垂直方向的跳跃点有明显的差别。以上过程可以得到2个字符特征。

通过以上分析总共可以得到22个字符特征值。将这些特征进行训练,即可得到所需的结果。关键代码如下(计算左边的特征值为例):

if(left[i]==-1)

{

while(left[i] == -1) i++;

}

begin=i;i=Height-1;

if(left[i] == -1)

{

while(left[i] == -1) i--;

}

end = i;

for(i=begin;i<=end;i++)

{

if(left[i] == -1)

left[i] = left[i+1];

}

//扫描深度

for(i=begin;i<=end;i++)

{

feature[4] += left[i];

}

feature[4]=feature[4]/10;

double *leftradio = new double[end-begin];

for(i=0;ileftradio[i]=0;

int n=0;

for(i=begin;i<=(end-4);i++)

{

//如果斜率为零

if(left[i] == left[i+4])

{

feature[0]++;

leftradio[n]=0;

}

else

{

leftradio[n] =(left[i]-left[i+4])/4.0;

if(leftradio[n] <0) //如果斜率小于0

feature[1]++;

else //斜率大于0

feature[2]++;

}

n++;

}

for(i=1;i{

feature[3] +=fabs(leftradio[i]-leftradio[i-1]);

}

5.神经网络训练

通过提取的特征值,识别的算法有很多,包括分类器算法,模板匹配算法,基于概率统计的Bayes分类器算法,聚类分析算法等。我这里采用的是BP神经网络分类器算法。

将提取的特征值,输入层为22个特征,隐含层为80个特征,输出层为34个特征。这里去除字母“I”和“O”。字符0-9,24个字母一共34个输出。说明:由于有34个输出,所以这里理想情况下输出结果为33个0和一个1.只是1在第i个输出。i对应的数字编号如0则对应0,1对应1,9对应9,字符“A”对应10,字符“B”对应11,依次类推,字符“Z”对应33。

Matlab创建网络及训练的代码实现如下:

%创建BP网络

net_1=newff(minmax(p),[80,34],{'tansig','purelin'},'traingdm')

%当前输入层权值和阈值

inputWeights=net_1.IW{1,1};

inputbias=net_1.b{1};

%当前网络层权值和阈值

layerWeights=net_1.LW{2,1};

layerbias=net_1.b{2};

%设置训练参数

net_1.trainParam.show = 50;

net_1.trainParam.lr = 0.01; %学习率

net_1.trainParam.mc = 0.9;

net_1.trainParam.epochs = 10000;%训练次数

net_1.trainParam.goal = 1e0; %目标误差

%调用 TRAINGDM 算法训练 BP 网络

[net_1,tr]=train(net_1,p,q);

6.车牌图像识别结果测试

因为车牌中的汉字与字母数字的结构以及骨架不同,所以汉字的识别过程需要另外再做处理,所以本文处理的是车牌除汉字外的车牌图像识别过程。通过最终的测试实验结果,数字的识别结果正确率比较高,字符的识别正确率比较低一点(由于训练用的英文字符比较少)。

识别结果

c语言车牌识别原理,解析车牌识别技术,融合多种算法的原理和过程相关推荐

  1. 汉字进行计算机识别的原理,原理解析 文字识别技术是如何实现的?_4G评测-中关村在线...

    原理解析 文字识别技术是如何实现的? OCR文字识别是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,然后用字符识别方法将形状翻译成计算机文字的过程 和语音识别技术一样,人们对文字识别早在50年 ...

  2. 手指静脉细化算法过程原理解析 以及python实现细化算法

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8672489.html 文中的一些图片以及思想很多都是参考https://www.cnblogs ...

  3. 微信语音技术原理_智能语音技术中麦克风阵列的原理

    麦克风阵列(Microphone Array),从字面上,指的是麦克风的排列.也就是说由一定数目的声学传感器(一般是麦克风)组成,用来对声场的空间特性进行采样并处理的系统. 早在20世纪70.80年代 ...

  4. 数字签名技术以及RSA算法的原理实现

    数字签名技术 1)对称加密与非对称加密 对称加密:对文件的加密和解密采用的都是同一个密钥,有IDEA和DES两种加密算法 非对称加密:有一对公钥和私钥 如果我们使用公钥加密,必须得用私钥解密:如果使用 ...

  5. 【面试必备】奉上最通俗易懂的XGBoost、LightGBM、BERT、XLNet原理解析

    一只小狐狸带你解锁 炼丹术&NLP 秘籍 在非深度学习的机器学习模型中,基于GBDT算法的XGBoost.LightGBM等有着非常优秀的性能,校招算法岗面试中"出镜率"非 ...

  6. Java类加载原理解析(转)

    1       基本信息 摘要: 每个java开发人员对java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java技术体系中的类加载.Java的类加 ...

  7. Java类加载原理解析

    Java类加载原理解析 基本信息摘要: 每个java开发人员对java.lang.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java技术体系中的类加载.Java ...

  8. mysql新增列并同时增加数据_图解MySQL | [原理解析] MySQL 为表添加列 是怎么quot;立刻quot;完成的...

    在上一期图解 图解MySQL | MySQL DDL为什么成本高?中,我们介绍了: 传统情况下,为表添加列需要对表进行重建 腾讯团队为 MySQL 引入了 Instant Add Column 的方案 ...

  9. mysql新增字段位置_图解MySQL | [原理解析] MySQL 为表添加列 是怎么quot;立刻quot;完成的...

    在上一期图解 图解MySQL | MySQL DDL为什么成本高?中,我们介绍了: 传统情况下,为表添加列需要对表进行重建 腾讯团队为 MySQL 引入了 Instant Add Column 的方案 ...

  10. Nacos-注册中心原理解析

    Nacos-注册中心原理解析 一.注册中心 二.Nacos注册中心原理解析 2.1 NamingService 2.2 NacosNamingService 2.2.1 NamingProxy 2.2 ...

最新文章

  1. IOS笔记本----读写.plist文件
  2. nrf51822蓝牙芯片ble_app_proximity程序总结
  3. 通过getGeneratedKeys获取记录的主键
  4. ubuntu安装VMware Tools
  5. linux-basic(8)linux磁盘与文件系统管理
  6. 搭建Servlet在线视频
  7. 矩阵字符串配置任意合并表格布局
  8. 家里宽带628连不上_WiFi密码正确,别人正常但是自己的手机却连不上WiFi是怎么回事?...
  9. 手机modem开发(15)---FT 测试天线注意事项
  10. C++11左值和右值引用讲解
  11. 我肝了一个月,给你写出了这本 Java 开发手册!
  12. Spark2.2出现异常:ERROR SparkUI: Failed to bind SparkUI
  13. 终于把ORACLE 10g的2门考试给搞结束了
  14. C#复制文件夹下的所有内容到另一个文件夹
  15. tinygrad ->要求python3.8以上
  16. 【黑灰产犯罪研究】网络水军
  17. win7命令行打开计算机,Win7怎么打开cmd命令提示符_Win7打开命令提示符教程-192路由网...
  18. [转]小总结一下矩阵的对角化
  19. 短信或者邮件链接打开 APP(URL Scheme)
  20. 第十一章 性能与可伸缩性 Java并发编程实战 阅读总结

热门文章

  1. 施耐德PLC Unity Pro xl 软件使用四
  2. 希捷移动硬盘打不开怎么办?
  3. 使用Easy CHM工具对文件生成API文档
  4. 如何查看硬盘对应的主板接口属性
  5. CDA的考试体系与人才能力模型
  6. /etc/config/wireless解析
  7. php我的世界网页地图,探险家地图 - Minecraft Wiki,最详细的官方我的世界百科
  8. hadoop put命令的格式_hadoop Shell命令详解
  9. 好用的抖音视频剪辑软件推荐
  10. 1.1.1.1校园网_突破校园网限制,开启寝室Wifi